instance.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include "back-ldbm.h"
  42. /* Forward declarations */
  43. static void ldbm_instance_destructor(void **arg);
  44. /* Creates and initializes a new ldbm_instance structure.
  45. * Also sets up some default indexes for the new instance.
  46. */
  47. int ldbm_instance_create(backend *be, char *name)
  48. {
  49. struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
  50. ldbm_instance *inst;
  51. /* Allocate storage for the ldbm_instance structure. Information specific
  52. * to this instance of the ldbm backend will be held here. */
  53. inst = (ldbm_instance *) slapi_ch_calloc(1, sizeof(ldbm_instance));
  54. /* Record the name of this instance. */
  55. inst->inst_name = strdup(name);
  56. /* initialize the entry cache */
  57. if (! cache_init(&(inst->inst_cache), DEFAULT_CACHE_SIZE,
  58. DEFAULT_CACHE_ENTRIES)) {
  59. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: cache_init failed\n",
  60. 0, 0, 0);
  61. return -1;
  62. }
  63. /* Lock for the list of open db handles */
  64. inst->inst_handle_list_mutex = PR_NewLock();
  65. if (NULL == inst->inst_handle_list_mutex) {
  66. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
  67. 0, 0, 0);
  68. return -1;
  69. }
  70. /* Lock used to synchronize modify operations. */
  71. inst->inst_db_mutex = PR_NewLock();
  72. if (NULL == inst->inst_db_mutex) {
  73. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
  74. 0, 0, 0);
  75. return -1;
  76. }
  77. if ((inst->inst_config_mutex = PR_NewLock()) == NULL) {
  78. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
  79. 0, 0, 0);
  80. return -1;
  81. }
  82. if ((inst->inst_nextid_mutex = PR_NewLock()) == NULL) {
  83. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewLock failed\n",
  84. 0, 0, 0);
  85. return -1;
  86. }
  87. if ((inst->inst_indexer_cv = PR_NewCondVar(inst->inst_nextid_mutex)) == NULL) {
  88. LDAPDebug(LDAP_DEBUG_ANY, "ldbm_instance_create: PR_NewCondVar failed\n", 0, 0, 0 );
  89. return -1;
  90. }
  91. inst->inst_be = be;
  92. inst->inst_li = li;
  93. be->be_instance_info = inst;
  94. /* Initialize the fields with some default values. */
  95. ldbm_instance_config_setup_default(inst);
  96. /* Add this new instance to the the set of instances */
  97. {
  98. Object *instance_obj;
  99. instance_obj = object_new((void *) inst, &ldbm_instance_destructor);
  100. objset_add_obj(li->li_instance_set, instance_obj);
  101. object_release(instance_obj);
  102. }
  103. return 0;
  104. }
  105. /* create the default indexes separately
  106. * (because when we're creating a new backend while the server is running,
  107. * the DSE needs to be pre-seeded first.)
  108. */
  109. int ldbm_instance_create_default_indexes(backend *be)
  110. {
  111. char *argv[ 9 ];
  112. ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
  113. /* write the dse file only on the final index */
  114. int flags = LDBM_INSTANCE_CONFIG_DONT_WRITE;
  115. /*
  116. * Always index entrydn, parentid, objectclass, subordinatecount
  117. * copiedFrom, and aci,
  118. * since they are used by some searches, replication and the
  119. * ACL routines.
  120. */
  121. argv[ 0 ] = "entrydn";
  122. argv[ 1 ] = "eq";
  123. argv[ 2 ] = NULL;
  124. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  125. argv[ 0 ] = "parentid";
  126. argv[ 1 ] = "eq";
  127. argv[ 2 ] = NULL;
  128. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  129. argv[ 0 ] = "objectclass";
  130. argv[ 1 ] = "eq";
  131. argv[ 2 ] = NULL;
  132. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  133. argv[ 0 ] = "aci";
  134. argv[ 1 ] = "pres";
  135. argv[ 2 ] = NULL;
  136. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  137. #if 0 /* don't need copiedfrom */
  138. argv[ 0 ] = "copiedfrom";
  139. argv[ 1 ] = "pres";
  140. argv[ 2 ] = NULL;
  141. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  142. #endif
  143. argv[ 0 ] = "numsubordinates";
  144. argv[ 1 ] = "pres";
  145. argv[ 2 ] = NULL;
  146. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  147. argv[ 0 ] = SLAPI_ATTR_UNIQUEID;
  148. argv[ 1 ] = "eq";
  149. argv[ 2 ] = NULL;
  150. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  151. /* For MMR, we need this attribute (to replace use of dncomp in delete). */
  152. argv[ 0 ] = ATTR_NSDS5_REPLCONFLICT;
  153. argv[ 1 ] = "eq,pres";
  154. argv[ 2 ] = NULL;
  155. ldbm_instance_config_add_index_entry(inst, 2, argv, flags);
  156. /* write the dse file only on the final index */
  157. argv[ 0 ] = SLAPI_ATTR_NSCP_ENTRYDN;
  158. argv[ 1 ] = "eq";
  159. argv[ 2 ] = NULL;
  160. ldbm_instance_config_add_index_entry(inst, 2, argv, 0);
  161. argv[ 0 ] = LDBM_PSEUDO_ATTR_DEFAULT;
  162. argv[ 1 ] = "none";
  163. argv[ 2 ] = NULL;
  164. /* ldbm_instance_config_add_index_entry(inst, 2, argv); */
  165. attr_index_config( be, "ldbm index init", 0, 2, argv, 1 );
  166. /*
  167. * ancestorid is special, there is actually no such attr type
  168. * but we still want to use the attr index file APIs.
  169. */
  170. argv[ 0 ] = "ancestorid";
  171. argv[ 1 ] = "eq";
  172. argv[ 2 ] = NULL;
  173. attr_index_config( be, "ldbm index init", 0, 2, argv, 1 );
  174. return 0;
  175. }
  176. /* Starts a backend instance */
  177. int
  178. ldbm_instance_start(backend *be)
  179. {
  180. int rc;
  181. PR_Lock (be->be_state_lock);
  182. if (be->be_state != BE_STATE_STOPPED &&
  183. be->be_state != BE_STATE_DELETED) {
  184. LDAPDebug( LDAP_DEBUG_TRACE,
  185. "ldbm_instance_start: warning - backend is in a wrong state - %d\n",
  186. be->be_state, 0, 0 );
  187. PR_Unlock (be->be_state_lock);
  188. return 0;
  189. }
  190. rc = dblayer_instance_start(be, DBLAYER_NORMAL_MODE);
  191. be->be_state = BE_STATE_STARTED;
  192. PR_Unlock (be->be_state_lock);
  193. return rc;
  194. }
  195. /* Stops a backend instance */
  196. int
  197. ldbm_instance_stop(backend *be)
  198. {
  199. int rc;
  200. ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
  201. PR_Lock (be->be_state_lock);
  202. if (be->be_state != BE_STATE_STARTED) {
  203. LDAPDebug( LDAP_DEBUG_ANY,
  204. "ldbm_back_close: warning - backend %s is in the wrong state - %d\n",
  205. inst ? inst->inst_name : "", be->be_state, 0 );
  206. PR_Unlock (be->be_state_lock);
  207. return 0;
  208. }
  209. rc = dblayer_instance_close(be);
  210. be->be_state = BE_STATE_STOPPED;
  211. PR_Unlock (be->be_state_lock);
  212. cache_destroy_please(&inst->inst_cache);
  213. return rc;
  214. }
  215. /* Walks down the set of instances, starting each one. */
  216. int
  217. ldbm_instance_startall(struct ldbminfo *li)
  218. {
  219. Object *inst_obj;
  220. ldbm_instance *inst;
  221. int rc = 0;
  222. inst_obj = objset_first_obj(li->li_instance_set);
  223. while (inst_obj != NULL) {
  224. int rc1;
  225. inst = (ldbm_instance *) object_get_data(inst_obj);
  226. rc1 = ldbm_instance_start(inst->inst_be);
  227. if (rc1 != 0) {
  228. rc = rc1;
  229. } else {
  230. vlv_init(inst);
  231. slapi_mtn_be_started(inst->inst_be);
  232. }
  233. inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
  234. }
  235. return rc;
  236. }
  237. /* Walks down the set of instances, stopping each one. */
  238. int ldbm_instance_stopall(struct ldbminfo *li)
  239. {
  240. Object *inst_obj;
  241. ldbm_instance *inst;
  242. inst_obj = objset_first_obj(li->li_instance_set);
  243. while (inst_obj != NULL) {
  244. inst = (ldbm_instance *) object_get_data(inst_obj);
  245. ldbm_instance_stop(inst->inst_be);
  246. inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
  247. }
  248. return 0;
  249. }
  250. /* Walks down the set of instance, looking for one
  251. * with the given name. Returns a pointer to the
  252. * instance if found, and NULL if not found. The
  253. * string compare on the instance name is NOT case
  254. * sensitive.
  255. */
  256. /* Currently this function doesn't bump
  257. * the ref count of the instance returned.
  258. */
  259. ldbm_instance *
  260. ldbm_instance_find_by_name(struct ldbminfo *li, char *name)
  261. {
  262. Object *inst_obj;
  263. ldbm_instance *inst;
  264. inst_obj = objset_first_obj(li->li_instance_set);
  265. while (inst_obj != NULL) {
  266. inst = (ldbm_instance *) object_get_data(inst_obj);
  267. if (!strcasecmp(inst->inst_name, name)) {
  268. /* Currently we release the object here. There is no
  269. * function for callers of this function to call to
  270. * release the object.
  271. */
  272. object_release(inst_obj);
  273. return inst;
  274. }
  275. inst_obj = objset_next_obj(li->li_instance_set, inst_obj);
  276. }
  277. return NULL;
  278. }
  279. /* Called when all references to the instance are gone. */
  280. /* (ie, only when an instance is being deleted) */
  281. static void
  282. ldbm_instance_destructor(void **arg)
  283. {
  284. ldbm_instance *inst = (ldbm_instance *) *arg;
  285. LDAPDebug(LDAP_DEBUG_ANY, "Destructor for instance %s called\n",
  286. inst->inst_name, 0, 0);
  287. slapi_ch_free((void **)&inst->inst_name);
  288. PR_DestroyLock(inst->inst_config_mutex);
  289. slapi_ch_free((void **)&inst->inst_dir_name);
  290. PR_DestroyLock(inst->inst_db_mutex);
  291. PR_DestroyLock(inst->inst_handle_list_mutex);
  292. PR_DestroyLock(inst->inst_nextid_mutex);
  293. PR_DestroyCondVar(inst->inst_indexer_cv);
  294. attrinfo_deletetree(inst);
  295. if (inst->inst_dataversion) {
  296. slapi_ch_free((void **)&inst->inst_dataversion);
  297. }
  298. /* cache has already been destroyed */
  299. slapi_ch_free((void **)&inst);
  300. }
  301. static int
  302. ldbm_instance_comparator(Object *object, const void *name)
  303. {
  304. void *data = object_get_data(object);
  305. return (data == name) ? 0 : 1;
  306. }
  307. /* find the instance in the objset and remove it */
  308. int
  309. ldbm_instance_destroy(ldbm_instance *inst)
  310. {
  311. Object *object = NULL;
  312. struct ldbminfo *li = inst->inst_li;
  313. object = objset_find(li->li_instance_set, ldbm_instance_comparator, inst);
  314. if (object == NULL) {
  315. return -1;
  316. }
  317. /* decref from objset_find */
  318. object_release(object);
  319. /* now remove from the instance set */
  320. objset_remove_obj(li->li_instance_set, object);
  321. return 0;
  322. }