diff options
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/instance.c')
-rw-r--r-- | ldap/servers/slapd/back-ldbm/instance.c | 353 |
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; +} |