summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-ndb/init.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--servers/slapd/back-ndb/init.cpp451
1 files changed, 451 insertions, 0 deletions
diff --git a/servers/slapd/back-ndb/init.cpp b/servers/slapd/back-ndb/init.cpp
new file mode 100644
index 0000000..e611d64
--- /dev/null
+++ b/servers/slapd/back-ndb/init.cpp
@@ -0,0 +1,451 @@
+/* init.cpp - initialize ndb backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2008-2021 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Howard Chu for inclusion
+ * in OpenLDAP Software. This work was sponsored by MySQL.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/stdlib.h>
+#include <ac/errno.h>
+#include <sys/stat.h>
+#include "back-ndb.h"
+#include <lutil.h>
+#include "config.h"
+
+extern "C" {
+ static BI_db_init ndb_db_init;
+ static BI_db_close ndb_db_close;
+ static BI_db_open ndb_db_open;
+ static BI_db_destroy ndb_db_destroy;
+}
+
+static struct berval ndb_optable = BER_BVC("OL_opattrs");
+
+static struct berval ndb_opattrs[] = {
+ BER_BVC("structuralObjectClass"),
+ BER_BVC("entryUUID"),
+ BER_BVC("creatorsName"),
+ BER_BVC("createTimestamp"),
+ BER_BVC("entryCSN"),
+ BER_BVC("modifiersName"),
+ BER_BVC("modifyTimestamp"),
+ BER_BVNULL
+};
+
+static int ndb_oplens[] = {
+ 0, /* structuralOC, default */
+ 36, /* entryUUID */
+ 0, /* creatorsName, default */
+ 26, /* createTimestamp */
+ 40, /* entryCSN */
+ 0, /* modifiersName, default */
+ 26, /* modifyTimestamp */
+ -1
+};
+
+static Uint32 ndb_lastrow[1];
+NdbInterpretedCode *ndb_lastrow_code;
+
+static int
+ndb_db_init( BackendDB *be, ConfigReply *cr )
+{
+ struct ndb_info *ni;
+ int rc = 0;
+
+ Debug( LDAP_DEBUG_TRACE,
+ LDAP_XSTRING(ndb_db_init) ": Initializing ndb database\n",
+ 0, 0, 0 );
+
+ /* allocate backend-database-specific stuff */
+ ni = (struct ndb_info *) ch_calloc( 1, sizeof(struct ndb_info) );
+
+ be->be_private = ni;
+ be->be_cf_ocs = be->bd_info->bi_cf_ocs;
+
+ ni->ni_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
+
+ ldap_pvt_thread_rdwr_init( &ni->ni_ai_rwlock );
+ ldap_pvt_thread_rdwr_init( &ni->ni_oc_rwlock );
+ ldap_pvt_thread_mutex_init( &ni->ni_conn_mutex );
+
+#ifdef DO_MONITORING
+ rc = ndb_monitor_db_init( be );
+#endif
+
+ return rc;
+}
+
+static int
+ndb_db_close( BackendDB *be, ConfigReply *cr );
+
+static int
+ndb_db_open( BackendDB *be, ConfigReply *cr )
+{
+ struct ndb_info *ni = (struct ndb_info *) be->be_private;
+ char sqlbuf[BUFSIZ], *ptr;
+ int rc, i;
+
+ if ( be->be_suffix == NULL ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: need suffix" );
+ Debug( LDAP_DEBUG_ANY, "%s\n",
+ cr->msg, 0, 0 );
+ return -1;
+ }
+
+ Debug( LDAP_DEBUG_ARGS,
+ LDAP_XSTRING(ndb_db_open) ": \"%s\"\n",
+ be->be_suffix[0].bv_val, 0, 0 );
+
+ if ( ni->ni_nconns < 1 )
+ ni->ni_nconns = 1;
+
+ ni->ni_cluster = (Ndb_cluster_connection **)ch_calloc( ni->ni_nconns, sizeof( Ndb_cluster_connection *));
+ for ( i=0; i<ni->ni_nconns; i++ ) {
+ ni->ni_cluster[i] = new Ndb_cluster_connection( ni->ni_connectstr );
+ rc = ni->ni_cluster[i]->connect( 20, 5, 1 );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: ni_cluster[%d]->connect failed (%d)",
+ i, rc );
+ goto fail;
+ }
+ }
+ for ( i=0; i<ni->ni_nconns; i++ ) {
+ rc = ni->ni_cluster[i]->wait_until_ready( 30, 30 );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: ni_cluster[%d]->wait failed (%d)",
+ i, rc );
+ goto fail;
+ }
+ }
+
+ mysql_init( &ni->ni_sql );
+ if ( !mysql_real_connect( &ni->ni_sql, ni->ni_hostname, ni->ni_username, ni->ni_password,
+ "", ni->ni_port, ni->ni_socket, ni->ni_clflag )) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: mysql_real_connect failed, %s (%d)",
+ mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
+ rc = -1;
+ goto fail;
+ }
+
+ sprintf( sqlbuf, "CREATE DATABASE IF NOT EXISTS %s", ni->ni_dbname );
+ rc = mysql_query( &ni->ni_sql, sqlbuf );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: CREATE DATABASE %s failed, %s (%d)",
+ ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
+ goto fail;
+ }
+
+ sprintf( sqlbuf, "USE %s", ni->ni_dbname );
+ rc = mysql_query( &ni->ni_sql, sqlbuf );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: USE DATABASE %s failed, %s (%d)",
+ ni->ni_dbname, mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
+ goto fail;
+ }
+
+ ptr = sqlbuf;
+ ptr += sprintf( ptr, "CREATE TABLE IF NOT EXISTS " DN2ID_TABLE " ("
+ "eid bigint unsigned NOT NULL, "
+ "object_classes VARCHAR(1024) NOT NULL, "
+ "a0 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a1 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a2 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a3 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a4 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a5 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a6 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a7 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a8 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a9 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a10 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a11 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a12 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a13 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a14 VARCHAR(128) NOT NULL DEFAULT '', "
+ "a15 VARCHAR(128) NOT NULL DEFAULT '', "
+ "PRIMARY KEY (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15), "
+ "UNIQUE KEY eid (eid) USING HASH" );
+ /* Create index columns */
+ if ( ni->ni_attridxs ) {
+ ListNode *ln;
+ int newcol = 0;
+
+ *ptr++ = ',';
+ *ptr++ = ' ';
+ for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
+ NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data;
+ ptr += sprintf( ptr, "`%s` VARCHAR(%d), ",
+ ai->na_name.bv_val, ai->na_len );
+ }
+ ptr = lutil_strcopy(ptr, "KEY " INDEX_NAME " (" );
+
+ for ( ln = ni->ni_attridxs; ln; ln=ln->ln_next ) {
+ NdbAttrInfo *ai = (NdbAttrInfo *)ln->ln_data;
+ if ( newcol ) *ptr++ = ',';
+ *ptr++ = '`';
+ ptr = lutil_strcopy( ptr, ai->na_name.bv_val );
+ *ptr++ = '`';
+ ai->na_ixcol = newcol + 18;
+ newcol++;
+ }
+ *ptr++ = ')';
+ }
+ strcpy( ptr, ") ENGINE=ndb" );
+ rc = mysql_query( &ni->ni_sql, sqlbuf );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: CREATE TABLE " DN2ID_TABLE " failed, %s (%d)",
+ mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
+ goto fail;
+ }
+
+ rc = mysql_query( &ni->ni_sql, "CREATE TABLE IF NOT EXISTS " NEXTID_TABLE " ("
+ "a bigint unsigned AUTO_INCREMENT PRIMARY KEY ) ENGINE=ndb" );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: CREATE TABLE " NEXTID_TABLE " failed, %s (%d)",
+ mysql_error(&ni->ni_sql), mysql_errno(&ni->ni_sql) );
+ goto fail;
+ }
+
+ {
+ NdbOcInfo *oci;
+
+ rc = ndb_aset_get( ni, &ndb_optable, ndb_opattrs, &oci );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: ndb_aset_get( %s ) failed (%d)",
+ ndb_optable.bv_val, rc );
+ goto fail;
+ }
+ for ( i=0; ndb_oplens[i] >= 0; i++ ) {
+ if ( ndb_oplens[i] )
+ oci->no_attrs[i]->na_len = ndb_oplens[i];
+ }
+ rc = ndb_aset_create( ni, oci );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: ndb_aset_create( %s ) failed (%d)",
+ ndb_optable.bv_val, rc );
+ goto fail;
+ }
+ ni->ni_opattrs = oci;
+ }
+ /* Create attribute sets */
+ {
+ ListNode *ln;
+
+ for ( ln = ni->ni_attrsets; ln; ln=ln->ln_next ) {
+ NdbOcInfo *oci = (NdbOcInfo *)ln->ln_data;
+ rc = ndb_aset_create( ni, oci );
+ if ( rc ) {
+ snprintf( cr->msg, sizeof( cr->msg ),
+ "ndb_db_open: ndb_aset_create( %s ) failed (%d)",
+ oci->no_name.bv_val, rc );
+ goto fail;
+ }
+ }
+ }
+ /* Initialize any currently used objectClasses */
+ {
+ Ndb *ndb;
+ const NdbDictionary::Dictionary *myDict;
+
+ ndb = new Ndb( ni->ni_cluster[0], ni->ni_dbname );
+ ndb->init(1024);
+
+ myDict = ndb->getDictionary();
+ ndb_oc_read( ni, myDict );
+ delete ndb;
+ }
+
+#ifdef DO_MONITORING
+ /* monitor setup */
+ rc = ndb_monitor_db_open( be );
+ if ( rc != 0 ) {
+ goto fail;
+ }
+#endif
+
+ return 0;
+
+fail:
+ Debug( LDAP_DEBUG_ANY, "%s\n",
+ cr->msg, 0, 0 );
+ ndb_db_close( be, NULL );
+ return rc;
+}
+
+static int
+ndb_db_close( BackendDB *be, ConfigReply *cr )
+{
+ int i;
+ struct ndb_info *ni = (struct ndb_info *) be->be_private;
+
+ mysql_close( &ni->ni_sql );
+ if ( ni->ni_cluster ) {
+ for ( i=0; i<ni->ni_nconns; i++ ) {
+ if ( ni->ni_cluster[i] ) {
+ delete ni->ni_cluster[i];
+ ni->ni_cluster[i] = NULL;
+ }
+ }
+ ch_free( ni->ni_cluster );
+ ni->ni_cluster = NULL;
+ }
+
+#ifdef DO_MONITORING
+ /* monitor handling */
+ (void)ndb_monitor_db_close( be );
+#endif
+
+ return 0;
+}
+
+static int
+ndb_db_destroy( BackendDB *be, ConfigReply *cr )
+{
+ struct ndb_info *ni = (struct ndb_info *) be->be_private;
+
+#ifdef DO_MONITORING
+ /* monitor handling */
+ (void)ndb_monitor_db_destroy( be );
+#endif
+
+ ldap_pvt_thread_mutex_destroy( &ni->ni_conn_mutex );
+ ldap_pvt_thread_rdwr_destroy( &ni->ni_ai_rwlock );
+ ldap_pvt_thread_rdwr_destroy( &ni->ni_oc_rwlock );
+
+ ch_free( ni );
+ be->be_private = NULL;
+
+ return 0;
+}
+
+extern "C" int
+ndb_back_initialize(
+ BackendInfo *bi )
+{
+ static char *controls[] = {
+ LDAP_CONTROL_ASSERT,
+ LDAP_CONTROL_MANAGEDSAIT,
+ LDAP_CONTROL_NOOP,
+ LDAP_CONTROL_PAGEDRESULTS,
+ LDAP_CONTROL_PRE_READ,
+ LDAP_CONTROL_POST_READ,
+ LDAP_CONTROL_SUBENTRIES,
+ LDAP_CONTROL_X_PERMISSIVE_MODIFY,
+#ifdef LDAP_X_TXN
+ LDAP_CONTROL_X_TXN_SPEC,
+#endif
+ NULL
+ };
+
+ int rc = 0;
+
+ /* initialize the underlying database system */
+ Debug( LDAP_DEBUG_TRACE,
+ LDAP_XSTRING(ndb_back_initialize) ": initialize ndb backend\n", 0, 0, 0 );
+
+ ndb_init();
+
+ ndb_lastrow_code = new NdbInterpretedCode( NULL, ndb_lastrow, 1 );
+ ndb_lastrow_code->interpret_exit_last_row();
+ ndb_lastrow_code->finalise();
+
+ bi->bi_flags |=
+ SLAP_BFLAG_INCREMENT |
+ SLAP_BFLAG_SUBENTRIES |
+ SLAP_BFLAG_ALIASES |
+ SLAP_BFLAG_REFERRALS;
+
+ bi->bi_controls = controls;
+
+ bi->bi_open = 0;
+ bi->bi_close = 0;
+ bi->bi_config = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = ndb_db_init;
+ bi->bi_db_config = config_generic_wrapper;
+ bi->bi_db_open = ndb_db_open;
+ bi->bi_db_close = ndb_db_close;
+ bi->bi_db_destroy = ndb_db_destroy;
+
+ bi->bi_op_add = ndb_back_add;
+ bi->bi_op_bind = ndb_back_bind;
+ bi->bi_op_compare = ndb_back_compare;
+ bi->bi_op_delete = ndb_back_delete;
+ bi->bi_op_modify = ndb_back_modify;
+ bi->bi_op_modrdn = ndb_back_modrdn;
+ bi->bi_op_search = ndb_back_search;
+
+ bi->bi_op_unbind = 0;
+
+#if 0
+ bi->bi_extended = ndb_extended;
+
+ bi->bi_chk_referrals = ndb_referrals;
+#endif
+ bi->bi_operational = ndb_operational;
+ bi->bi_has_subordinates = ndb_has_subordinates;
+ bi->bi_entry_release_rw = 0;
+ bi->bi_entry_get_rw = ndb_entry_get;
+
+ /*
+ * hooks for slap tools
+ */
+ bi->bi_tool_entry_open = ndb_tool_entry_open;
+ bi->bi_tool_entry_close = ndb_tool_entry_close;
+ bi->bi_tool_entry_first = ndb_tool_entry_first;
+ bi->bi_tool_entry_next = ndb_tool_entry_next;
+ bi->bi_tool_entry_get = ndb_tool_entry_get;
+ bi->bi_tool_entry_put = ndb_tool_entry_put;
+#if 0
+ bi->bi_tool_entry_reindex = ndb_tool_entry_reindex;
+ bi->bi_tool_sync = 0;
+ bi->bi_tool_dn2id_get = ndb_tool_dn2id_get;
+ bi->bi_tool_entry_modify = ndb_tool_entry_modify;
+#endif
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ rc = ndb_back_init_cf( bi );
+
+ return rc;
+}
+
+#if SLAPD_NDB == SLAPD_MOD_DYNAMIC
+
+/* conditionally define the init_module() function */
+extern "C" { int init_module( int argc, char *argv[] ); }
+
+SLAP_BACKEND_INIT_MODULE( ndb )
+
+#endif /* SLAPD_NDB == SLAPD_MOD_DYNAMIC */
+