summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/back-ldbm/instance.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/instance.c')
-rw-r--r--ldap/servers/slapd/back-ldbm/instance.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/ldap/servers/slapd/back-ldbm/instance.c b/ldap/servers/slapd/back-ldbm/instance.c
new file mode 100644
index 00000000..aa672000
--- /dev/null
+++ b/ldap/servers/slapd/back-ldbm/instance.c
@@ -0,0 +1,353 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include "back-ldbm.h"
+
+/* Forward declarations */
+static void ldbm_instance_destructor(void **arg);
+
+
+
+/* Creates and initializes a new ldbm_instance structure.
+ * Also sets up some default indexes for the new instance.
+ */
+int ldbm_instance_create(backend *be, char *name)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
+ ldbm_instance *inst;
+
+ /* Allocate storage for the ldbm_instance structure. Information specific
+ * to this instance of the ldbm backend will be held here. */
+ inst = (ldbm_instance *) slapi_ch_calloc(1, sizeof(ldbm_instance));
+
+ /* Record the name of this instance. */
+ inst->inst_name = strdup(name);
+
+ /* initialize the entry cache */
+ if (! cache_init(&(inst->inst_cache), DEFAULT_CACHE_SIZE,
+ DEFAULT_CACHE_ENTRIES)) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: cache_init failed\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ /* Lock for the list of open db handles */
+ inst->inst_handle_list_mutex = PR_NewLock();
+ if (NULL == inst->inst_handle_list_mutex) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ /* Lock used to synchronize modify operations. */
+ inst->inst_db_mutex = PR_NewLock();
+ if (NULL == inst->inst_db_mutex) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ if ((inst->inst_config_mutex = PR_NewLock()) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ if ((inst->inst_nextid_mutex = PR_NewLock()) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ if ((inst->inst_indexer_cv = PR_NewCondVar(inst->inst_nextid_mutex)) == NULL) {
+ LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewCondVar failed\n", 0, 0, 0 );
+ return -1;
+ }
+
+ inst->inst_be = be;
+ inst->inst_li = li;
+ be->be_instance_info = inst;
+
+ /* Initialize the fields with some default values. */
+ ldbm_instance_config_setup_default(inst);
+
+ /* Add this new instance to the the set of instances */
+ {
+ Object *instance_obj;
+
+ instance_obj = object_new((void *) inst, &ldbm_instance_destructor);
+ objset_add_obj(li->li_instance_set, instance_obj);
+ object_release(instance_obj);
+ }
+
+ return 0;
+}
+
+/* create the default indexes separately
+ * (because when we're creating a new backend while the server is running,
+ * the DSE needs to be pre-seeded first.)
+ */
+int ldbm_instance_create_default_indexes(backend *be)
+{
+ char *argv[ 9 ];
+ ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
+ /* write the dse file only on the final index */
+ int flags = LDBM_INSTANCE_CONFIG_DONT_WRITE;
+
+ /*
+ * Always index entrydn, parentid, objectclass, subordinatecount
+ * copiedFrom, and aci,
+ * since they are used by some searches, replication and the
+ * ACL routines.
+ */
+
+ argv[ 0 ] = "entrydn";
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ argv[ 0 ] = "parentid";
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ argv[ 0 ] = "objectclass";
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ argv[ 0 ] = "aci";
+ argv[ 1 ] = "pres";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+#if 0 /* don't need copiedfrom */
+ argv[ 0 ] = "copiedfrom";
+ argv[ 1 ] = "pres";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+#endif
+
+ argv[ 0 ] = "numsubordinates";
+ argv[ 1 ] = "pres";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ argv[ 0 ] = SLAPI_ATTR_UNIQUEID;
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ /* For MMR, we need this attribute (to replace use of dncomp in delete). */
+ argv[ 0 ] = ATTR_NSDS5_REPLCONFLICT;
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
+
+ /* write the dse file only on the final index */
+ argv[ 0 ] = SLAPI_ATTR_NSCP_ENTRYDN;
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ ldbm_instance_config_add_index_entry(inst, 2, argv, 0);
+
+ argv[ 0 ] = LDBM_PSEUDO_ATTR_DEFAULT;
+ argv[ 1 ] = "none";
+ argv[ 2 ] = NULL;
+ /* ldbm_instance_config_add_index_entry(inst, 2, argv); */
+ attr_index_config( be, "ldbm index init", 0, 2, argv, 1 );
+
+ /*
+ * ancestorid is special, there is actually no such attr type
+ * but we still want to use the attr index file APIs.
+ */
+ argv[ 0 ] = "ancestorid";
+ argv[ 1 ] = "eq";
+ argv[ 2 ] = NULL;
+ attr_index_config( be, "ldbm index init", 0, 2, argv, 1 );
+
+ return 0;
+}
+
+
+/* Starts a backend instance */
+int
+ldbm_instance_start(backend *be)
+{
+ int rc;
+ PR_Lock (be->be_state_lock);
+
+ if (be->be_state != BE_STATE_STOPPED &&
+ be->be_state != BE_STATE_DELETED) {
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "ldbm_instance_start: warning - backend is in a wrong state - %d\n",
+ be->be_state, 0, 0 );
+ PR_Unlock (be->be_state_lock);
+ return 0;
+ }
+
+ rc = dblayer_instance_start(be, DBLAYER_NORMAL_MODE);
+ be->be_state = BE_STATE_STARTED;
+
+ PR_Unlock (be->be_state_lock);
+
+ return rc;
+}
+
+
+/* Stops a backend instance */
+int
+ldbm_instance_stop(backend *be)
+{
+ int rc;
+ ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
+
+ PR_Lock (be->be_state_lock);
+
+ if (be->be_state != BE_STATE_STARTED) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "ldbm_back_close: warning - backend %s is in the wrong state - %d\n",
+ inst ? inst->inst_name : "", be->be_state, 0 );
+ PR_Unlock (be->be_state_lock);
+ return 0;
+ }
+
+ rc = dblayer_instance_close(be);
+
+ be->be_state = BE_STATE_STOPPED;
+ PR_Unlock (be->be_state_lock);
+
+ cache_destroy_please(&inst->inst_cache);
+
+ return rc;
+}
+
+
+/* Walks down the set of instances, starting each one. */
+int
+ldbm_instance_startall(struct ldbminfo *li)
+{
+ Object *inst_obj;
+ ldbm_instance *inst;
+ int rc = 0;
+
+ inst_obj = objset_first_obj(li->li_instance_set);
+ while (inst_obj != NULL) {
+ int rc1;
+ inst = (ldbm_instance *) object_get_data(inst_obj);
+ rc1 = ldbm_instance_start(inst->inst_be);
+ if (rc1 != 0) {
+ rc = rc1;
+ } else {
+ vlv_init(inst);
+ }
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
+ }
+
+ return rc;
+}
+
+
+/* Walks down the set of instances, stopping each one. */
+int ldbm_instance_stopall(struct ldbminfo *li)
+{
+ Object *inst_obj;
+ ldbm_instance *inst;
+
+ inst_obj = objset_first_obj(li->li_instance_set);
+ while (inst_obj != NULL) {
+ inst = (ldbm_instance *) object_get_data(inst_obj);
+ ldbm_instance_stop(inst->inst_be);
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
+ }
+
+ return 0;
+}
+
+
+/* Walks down the set of instance, looking for one
+ * with the given name. Returns a pointer to the
+ * instance if found, and NULL if not found. The
+ * string compare on the instance name is NOT case
+ * sensitive.
+ */
+/* Currently this function doesn't bump
+ * the ref count of the instance returned.
+ */
+ldbm_instance *
+ldbm_instance_find_by_name(struct ldbminfo *li, char *name)
+{
+ Object *inst_obj;
+ ldbm_instance *inst;
+
+ inst_obj = objset_first_obj(li->li_instance_set);
+ while (inst_obj != NULL) {
+ inst = (ldbm_instance *) object_get_data(inst_obj);
+ if (!strcasecmp(inst->inst_name, name)) {
+ /* Currently we release the object here. There is no
+ * function for callers of this function to call to
+ * release the object.
+ */
+ object_release(inst_obj);
+ return inst;
+ }
+ inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
+ }
+ return NULL;
+}
+
+
+/* Called when all references to the instance are gone. */
+/* (ie, only when an instance is being deleted) */
+static void
+ldbm_instance_destructor(void **arg)
+{
+ ldbm_instance *inst = (ldbm_instance *) *arg;
+
+ LDAPDebug(LDAP_DEBUG_ANY, "Destructor for instance %s called\n",
+ inst->inst_name, 0, 0);
+
+ slapi_ch_free((void **)&inst->inst_name);
+ PR_DestroyLock(inst->inst_config_mutex);
+ slapi_ch_free((void **)&inst->inst_dir_name);
+ PR_DestroyLock(inst->inst_db_mutex);
+ PR_DestroyLock(inst->inst_handle_list_mutex);
+ PR_DestroyLock(inst->inst_nextid_mutex);
+ PR_DestroyCondVar(inst->inst_indexer_cv);
+ attrinfo_deletetree(inst);
+ if (inst->inst_dataversion) {
+ slapi_ch_free((void **)&inst->inst_dataversion);
+ }
+ /* cache has already been destroyed */
+
+ slapi_ch_free((void **)&inst);
+}
+
+
+static int
+ldbm_instance_comparator(Object *object, const void *name)
+{
+ void *data = object_get_data(object);
+ return (data == name) ? 0 : 1;
+}
+
+
+/* find the instance in the objset and remove it */
+int
+ldbm_instance_destroy(ldbm_instance *inst)
+{
+ Object *object = NULL;
+ struct ldbminfo *li = inst->inst_li;
+
+ object = objset_find(li->li_instance_set, ldbm_instance_comparator, inst);
+ if (object == NULL) {
+ return -1;
+ }
+ /* decref from objset_find */
+ object_release(object);
+
+ /* now remove from the instance set */
+ objset_remove_obj(li->li_instance_set, object);
+ return 0;
+}