ldbm_instance_config.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  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. /* This file handles configuration information that is specific
  42. * to ldbm instances.
  43. */
  44. #include "back-ldbm.h"
  45. #include "dblayer.h"
  46. /* Forward declarations for the callbacks */
  47. int ldbm_instance_search_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);
  48. int ldbm_instance_modify_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg);
  49. static char *ldbm_instance_attrcrypt_filter = "(objectclass=nsAttributeEncryption)";
  50. /* dse entries add for a new ldbm instance */
  51. static char *ldbm_instance_skeleton_entries[] =
  52. {
  53. "dn:cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config\n"
  54. "objectclass:top\n"
  55. "objectclass:extensibleObject\n"
  56. "cn:monitor\n",
  57. "dn:cn=index, cn=%s, cn=%s, cn=plugins, cn=config\n"
  58. "objectclass:top\n"
  59. "objectclass:extensibleObject\n"
  60. "cn:index\n",
  61. "dn:cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config\n"
  62. "objectclass:top\n"
  63. "objectclass:extensibleObject\n"
  64. "cn:encrypted attributes\n",
  65. "dn:cn=encrypted attribute keys, cn=%s, cn=%s, cn=plugins, cn=config\n"
  66. "objectclass:top\n"
  67. "objectclass:extensibleObject\n"
  68. "cn:encrypted attribute keys\n",
  69. ""
  70. };
  71. /*------------------------------------------------------------------------
  72. * Get and set functions for ldbm instance variables
  73. *----------------------------------------------------------------------*/
  74. static void *
  75. ldbm_instance_config_cachesize_get(void *arg)
  76. {
  77. ldbm_instance *inst = (ldbm_instance *) arg;
  78. return (void *) cache_get_max_entries(&(inst->inst_cache));
  79. }
  80. static int
  81. ldbm_instance_config_cachesize_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  82. {
  83. ldbm_instance *inst = (ldbm_instance *) arg;
  84. int retval = LDAP_SUCCESS;
  85. long val = (long) value;
  86. /* Do whatever we can to make sure the data is ok. */
  87. if (apply) {
  88. cache_set_max_entries(&(inst->inst_cache), val);
  89. }
  90. return retval;
  91. }
  92. static void *
  93. ldbm_instance_config_cachememsize_get(void *arg)
  94. {
  95. ldbm_instance *inst = (ldbm_instance *) arg;
  96. return (void *) cache_get_max_size(&(inst->inst_cache));
  97. }
  98. static int
  99. ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  100. {
  101. ldbm_instance *inst = (ldbm_instance *) arg;
  102. int retval = LDAP_SUCCESS;
  103. size_t val = (size_t) value;
  104. /* Do whatever we can to make sure the data is ok. */
  105. if (apply) {
  106. cache_set_max_size(&(inst->inst_cache), val);
  107. }
  108. return retval;
  109. }
  110. static void *
  111. ldbm_instance_config_readonly_get(void *arg)
  112. {
  113. ldbm_instance *inst = (ldbm_instance *)arg;
  114. return (void *)((uintptr_t)inst->inst_be->be_readonly);
  115. }
  116. static void *
  117. ldbm_instance_config_instance_dir_get(void *arg)
  118. {
  119. ldbm_instance *inst = (ldbm_instance *)arg;
  120. if (inst->inst_dir_name == NULL)
  121. return slapi_ch_strdup("");
  122. else if (inst->inst_parent_dir_name)
  123. {
  124. int len = strlen(inst->inst_parent_dir_name) +
  125. strlen(inst->inst_dir_name) + 2;
  126. char *full_inst_dir = (char *)slapi_ch_malloc(len);
  127. PR_snprintf(full_inst_dir, len, "%s%c%s",
  128. inst->inst_parent_dir_name, get_sep(inst->inst_parent_dir_name),
  129. inst->inst_dir_name);
  130. return full_inst_dir;
  131. }
  132. else
  133. return slapi_ch_strdup(inst->inst_dir_name);
  134. }
  135. static void *
  136. ldbm_instance_config_require_index_get(void *arg)
  137. {
  138. ldbm_instance *inst = (ldbm_instance *)arg;
  139. return (void *)((uintptr_t)inst->require_index);
  140. }
  141. static int
  142. ldbm_instance_config_instance_dir_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  143. {
  144. ldbm_instance *inst = (ldbm_instance *)arg;
  145. if (!apply) {
  146. return LDAP_SUCCESS;
  147. }
  148. if ((value == NULL) || (strlen(value) == 0))
  149. {
  150. inst->inst_dir_name = NULL;
  151. inst->inst_parent_dir_name = NULL;
  152. }
  153. else
  154. {
  155. char *dir = (char *)value;
  156. if (is_fullpath(dir))
  157. {
  158. char sep = get_sep(dir);
  159. char *p = strrchr(dir, sep);
  160. if (NULL == p) /* should not happens, tho */
  161. {
  162. inst->inst_parent_dir_name = NULL;
  163. inst->inst_dir_name = rel2abspath(dir); /* normalize dir;
  164. strdup'ed in
  165. rel2abspath */
  166. }
  167. else
  168. {
  169. *p = '\0';
  170. inst->inst_parent_dir_name = rel2abspath(dir); /* normalize dir;
  171. strdup'ed in
  172. rel2abspath */
  173. inst->inst_dir_name = slapi_ch_strdup(p+1);
  174. *p = sep;
  175. }
  176. }
  177. else
  178. {
  179. inst->inst_parent_dir_name = NULL;
  180. inst->inst_dir_name = slapi_ch_strdup(dir);
  181. }
  182. }
  183. return LDAP_SUCCESS;
  184. }
  185. static int
  186. ldbm_instance_config_readonly_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  187. {
  188. ldbm_instance *inst = (ldbm_instance *)arg;
  189. uintptr_t pval = (uintptr_t)value;
  190. if (!apply) {
  191. return LDAP_SUCCESS;
  192. }
  193. if (CONFIG_PHASE_RUNNING == phase) {
  194. /* if the instance is busy, we'll save the user's readonly settings
  195. * but won't change them until the instance is un-busy again.
  196. */
  197. if (! (inst->inst_flags & INST_FLAG_BUSY)) {
  198. slapi_mtn_be_set_readonly(inst->inst_be, (int)pval);
  199. }
  200. if ((int)pval) {
  201. inst->inst_flags |= INST_FLAG_READONLY;
  202. } else {
  203. inst->inst_flags &= ~INST_FLAG_READONLY;
  204. }
  205. } else {
  206. slapi_be_set_readonly(inst->inst_be, (int)pval);
  207. }
  208. return LDAP_SUCCESS;
  209. }
  210. static int
  211. ldbm_instance_config_require_index_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  212. {
  213. ldbm_instance *inst = (ldbm_instance *)arg;
  214. if (!apply) {
  215. return LDAP_SUCCESS;
  216. }
  217. inst->require_index = (int)((uintptr_t)value);
  218. return LDAP_SUCCESS;
  219. }
  220. /*------------------------------------------------------------------------
  221. * ldbm instance configuration array
  222. *----------------------------------------------------------------------*/
  223. static config_info ldbm_instance_config[] = {
  224. {CONFIG_INSTANCE_CACHESIZE, CONFIG_TYPE_LONG, "-1", &ldbm_instance_config_cachesize_get, &ldbm_instance_config_cachesize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
  225. {CONFIG_INSTANCE_CACHEMEMSIZE, CONFIG_TYPE_SIZE_T, "10485760", &ldbm_instance_config_cachememsize_get, &ldbm_instance_config_cachememsize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
  226. {CONFIG_INSTANCE_READONLY, CONFIG_TYPE_ONOFF, "off", &ldbm_instance_config_readonly_get, &ldbm_instance_config_readonly_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
  227. {CONFIG_INSTANCE_REQUIRE_INDEX, CONFIG_TYPE_ONOFF, "off", &ldbm_instance_config_require_index_get, &ldbm_instance_config_require_index_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
  228. {CONFIG_INSTANCE_DIR, CONFIG_TYPE_STRING, NULL, &ldbm_instance_config_instance_dir_get, &ldbm_instance_config_instance_dir_set, CONFIG_FLAG_ALWAYS_SHOW},
  229. {NULL, 0, NULL, NULL, NULL, 0}
  230. };
  231. void
  232. ldbm_instance_config_setup_default(ldbm_instance *inst)
  233. {
  234. config_info *config;
  235. char err_buf[BUFSIZ];
  236. for (config = ldbm_instance_config; config->config_name != NULL; config++) {
  237. ldbm_config_set((void *)inst, config->config_name, ldbm_instance_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */);
  238. }
  239. }
  240. static int
  241. parse_ldbm_instance_entry(Slapi_Entry *e, char **instance_name)
  242. {
  243. Slapi_Attr *attr = NULL;
  244. for (slapi_entry_first_attr(e, &attr); attr;
  245. slapi_entry_next_attr(e, attr, &attr)) {
  246. char *attr_name = NULL;
  247. slapi_attr_get_type(attr, &attr_name);
  248. if (strcasecmp(attr_name, "cn") == 0) {
  249. Slapi_Value *sval = NULL;
  250. struct berval *bval;
  251. slapi_attr_first_value(attr, &sval);
  252. bval = (struct berval *) slapi_value_get_berval(sval);
  253. *instance_name = slapi_ch_strdup((char *)bval->bv_val);
  254. }
  255. }
  256. return 0;
  257. }
  258. /* When a new instance is started, we need to read the dse to
  259. * find out what indexes should be maintained. This function
  260. * does that. Returns 0 on success. */
  261. static int
  262. read_instance_index_entries(ldbm_instance *inst)
  263. {
  264. Slapi_PBlock *tmp_pb;
  265. int scope = LDAP_SCOPE_SUBTREE;
  266. char basedn[BUFSIZ];
  267. const char *searchfilter = "(objectclass=nsIndex)";
  268. /* Construct the base dn of the subtree that holds the index entries
  269. * for this instance. */
  270. PR_snprintf(basedn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
  271. inst->inst_name, inst->inst_li->li_plugin->plg_name);
  272. /* Set up a tmp callback that will handle the init for each index entry */
  273. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  274. basedn, scope, searchfilter, ldbm_index_init_entry_callback,
  275. (void *) inst);
  276. /* Do a search of the subtree containing the index entries */
  277. tmp_pb = slapi_pblock_new();
  278. slapi_search_internal_set_pb(tmp_pb, basedn, LDAP_SCOPE_SUBTREE,
  279. searchfilter, NULL, 0, NULL, NULL, inst->inst_li->li_identity, 0);
  280. slapi_search_internal_pb (tmp_pb);
  281. /* Remove the tmp callback */
  282. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  283. basedn, scope, searchfilter, ldbm_index_init_entry_callback);
  284. slapi_free_search_results_internal(tmp_pb);
  285. slapi_pblock_destroy(tmp_pb);
  286. return 0;
  287. }
  288. /* When a new instance is started, we need to read the dse to
  289. * find out what attributes should be encrypted. This function
  290. * does that. Returns 0 on success. */
  291. static int
  292. read_instance_attrcrypt_entries(ldbm_instance *inst)
  293. {
  294. Slapi_PBlock *tmp_pb;
  295. int scope = LDAP_SCOPE_SUBTREE;
  296. char basedn[BUFSIZ];
  297. const char *searchfilter = ldbm_instance_attrcrypt_filter;
  298. /* Construct the base dn of the subtree that holds the index entries
  299. * for this instance. */
  300. PR_snprintf(basedn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
  301. inst->inst_name, inst->inst_li->li_plugin->plg_name);
  302. /* Set up a tmp callback that will handle the init for each index entry */
  303. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  304. basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback,
  305. (void *) inst);
  306. /* Do a search of the subtree containing the index entries */
  307. tmp_pb = slapi_pblock_new();
  308. slapi_search_internal_set_pb(tmp_pb, basedn, LDAP_SCOPE_SUBTREE,
  309. searchfilter, NULL, 0, NULL, NULL, inst->inst_li->li_identity, 0);
  310. slapi_search_internal_pb (tmp_pb);
  311. /* Remove the tmp callback */
  312. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  313. basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback);
  314. slapi_free_search_results_internal(tmp_pb);
  315. slapi_pblock_destroy(tmp_pb);
  316. return 0;
  317. }
  318. /* Handles the parsing of the config entry for an ldbm instance. Returns 0
  319. * on success. */
  320. static int
  321. parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_info *config_array)
  322. {
  323. Slapi_Attr *attr = NULL;
  324. for (slapi_entry_first_attr(e, &attr); attr;
  325. slapi_entry_next_attr(e, attr, &attr)) {
  326. char *attr_name = NULL;
  327. Slapi_Value *sval = NULL;
  328. struct berval *bval;
  329. char err_buf[BUFSIZ];
  330. slapi_attr_get_type(attr, &attr_name);
  331. /* There are some attributes that we don't care about,
  332. * like objectclass. */
  333. if (ldbm_config_ignored_attr(attr_name)) {
  334. continue;
  335. }
  336. /* We have to handle suffix attributes a little differently */
  337. if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) {
  338. Slapi_DN suffix;
  339. slapi_attr_first_value(attr, &sval);
  340. bval = (struct berval *) slapi_value_get_berval(sval);
  341. slapi_sdn_init_dn_byref(&suffix, bval->bv_val);
  342. if (!slapi_be_issuffix(inst->inst_be, &suffix)) {
  343. be_addsuffix(inst->inst_be, &suffix);
  344. }
  345. slapi_sdn_done(&suffix);
  346. continue;
  347. }
  348. /* We are assuming that each of these attributes are to have
  349. * only one value. If they have more than one value, like
  350. * the nsslapd-suffix attribute, then they need to be
  351. * handled differently. */
  352. slapi_attr_first_value(attr, &sval);
  353. bval = (struct berval *) slapi_value_get_berval(sval);
  354. if (ldbm_config_set((void *) inst, attr_name, config_array, bval,
  355. err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */) != LDAP_SUCCESS) {
  356. LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n",
  357. attr_name, err_buf, 0);
  358. return 1;
  359. }
  360. }
  361. /* Read the index entries */
  362. read_instance_index_entries(inst);
  363. /* Read the attribute encryption entries */
  364. read_instance_attrcrypt_entries(inst);
  365. return 0;
  366. }
  367. /* general-purpose callback to deny an operation */
  368. static int ldbm_instance_deny_config(Slapi_PBlock *pb, Slapi_Entry *e,
  369. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  370. {
  371. *returncode = LDAP_UNWILLING_TO_PERFORM;
  372. return SLAPI_DSE_CALLBACK_ERROR;
  373. }
  374. /* Reads in any config information held in the dse for the given
  375. * entry. Creates dse entries used to configure the given instance
  376. * if they don't already exist. Registers dse callback functions to
  377. * maintain those dse entries. Returns 0 on success. */
  378. int
  379. ldbm_instance_config_load_dse_info(ldbm_instance *inst)
  380. {
  381. struct ldbminfo *li = inst->inst_li;
  382. Slapi_PBlock *search_pb;
  383. Slapi_Entry **entries = NULL;
  384. int res;
  385. char dn[BUFSIZ];
  386. /* We try to read the entry
  387. * cn=instance_name, cn=ldbm database, cn=plugins, cn=config. If the
  388. * entry is there, then we process the config information it stores.
  389. */
  390. PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
  391. inst->inst_name, li->li_plugin->plg_name);
  392. search_pb = slapi_pblock_new();
  393. slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_BASE,
  394. "objectclass=*", NULL, 0, NULL, NULL,
  395. li->li_identity, 0);
  396. slapi_search_internal_pb (search_pb);
  397. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  398. if (res != LDAP_SUCCESS) {
  399. LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n", 0, 0, 0);
  400. return 1;
  401. } else {
  402. /* Need to parse the configuration information for the ldbm
  403. * plugin that is held in the DSE. */
  404. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
  405. &entries);
  406. if ((!entries) || (!entries[0])) {
  407. LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n",
  408. 0, 0, 0);
  409. return 1;
  410. }
  411. if (0 != parse_ldbm_instance_config_entry(inst, entries[0],
  412. ldbm_instance_config)) {
  413. LDAPDebug(LDAP_DEBUG_ANY, "Error parsing the config DSE\n",
  414. 0, 0, 0);
  415. return 1;
  416. }
  417. }
  418. if (search_pb)
  419. {
  420. slapi_free_search_results_internal(search_pb);
  421. slapi_pblock_destroy(search_pb);
  422. }
  423. /* Add skeleton dse entries for this instance */
  424. /* IF they already exist, that's ok */
  425. ldbm_config_add_dse_entries(li, ldbm_instance_skeleton_entries,
  426. inst->inst_name, li->li_plugin->plg_name,
  427. inst->inst_name, 0);
  428. /* setup the dse callback functions for the ldbm instance config entry */
  429. PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
  430. inst->inst_name, li->li_plugin->plg_name);
  431. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
  432. LDAP_SCOPE_BASE, "(objectclass=*)",
  433. ldbm_instance_search_config_entry_callback, (void *) inst);
  434. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  435. LDAP_SCOPE_BASE, "(objectclass=*)",
  436. ldbm_instance_modify_config_entry_callback, (void *) inst);
  437. slapi_config_register_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
  438. LDAP_SCOPE_BASE, "(objectclass=*)",
  439. ldbm_instance_search_config_entry_callback, (void *) inst);
  440. slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  441. LDAP_SCOPE_BASE, "(objectclass=*)",
  442. ldbm_instance_deny_config, (void *)inst);
  443. /* delete is handled by a callback set in ldbm_config.c */
  444. /* don't forget the monitor! */
  445. PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
  446. inst->inst_name, li->li_plugin->plg_name);
  447. /* make callback on search; deny add/modify/delete */
  448. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
  449. LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search,
  450. (void *)inst);
  451. slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  452. LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config,
  453. (void *)inst);
  454. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  455. LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config,
  456. (void *)inst);
  457. /* delete is okay */
  458. /* Callbacks to handle indexes */
  459. PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
  460. inst->inst_name, li->li_plugin->plg_name);
  461. slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  462. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  463. ldbm_instance_index_config_add_callback, (void *) inst);
  464. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
  465. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  466. ldbm_instance_index_config_delete_callback, (void *) inst);
  467. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  468. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  469. ldbm_instance_index_config_modify_callback, (void *) inst);
  470. /* Callbacks to handle attribute encryption */
  471. PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
  472. inst->inst_name, li->li_plugin->plg_name);
  473. slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  474. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  475. ldbm_instance_attrcrypt_config_add_callback, (void *) inst);
  476. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
  477. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  478. ldbm_instance_attrcrypt_config_delete_callback, (void *) inst);
  479. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  480. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  481. ldbm_instance_attrcrypt_config_modify_callback, (void *) inst);
  482. return 0;
  483. }
  484. /*
  485. * Config. DSE callback for instance entry searches.
  486. */
  487. int
  488. ldbm_instance_search_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  489. {
  490. char buf[BUFSIZ];
  491. struct berval *vals[2];
  492. struct berval val;
  493. ldbm_instance *inst = (ldbm_instance *) arg;
  494. config_info *config;
  495. int x;
  496. const Slapi_DN *suffix;
  497. vals[0] = &val;
  498. vals[1] = NULL;
  499. returntext[0] = '\0';
  500. /* show the suffixes */
  501. attrlist_delete(&e->e_attrs, CONFIG_INSTANCE_SUFFIX);
  502. x = 0;
  503. do {
  504. suffix = slapi_be_getsuffix(inst->inst_be, x);
  505. if (suffix != NULL) {
  506. val.bv_val = (char *) slapi_sdn_get_dn(suffix);
  507. val.bv_len = strlen (val.bv_val);
  508. attrlist_merge( &e->e_attrs, CONFIG_INSTANCE_SUFFIX, vals );
  509. }
  510. x++;
  511. } while(suffix!=NULL);
  512. PR_Lock(inst->inst_config_mutex);
  513. for(config = ldbm_instance_config; config->config_name != NULL; config++) {
  514. /* Go through the ldbm_config table and fill in the entry. */
  515. if (!(config->config_flags & (CONFIG_FLAG_ALWAYS_SHOW | CONFIG_FLAG_PREVIOUSLY_SET))) {
  516. /* This config option shouldn't be shown */
  517. continue;
  518. }
  519. ldbm_config_get((void *) inst, config, buf);
  520. val.bv_val = buf;
  521. val.bv_len = strlen(buf);
  522. slapi_entry_attr_replace(e, config->config_name, vals);
  523. }
  524. PR_Unlock(inst->inst_config_mutex);
  525. *returncode = LDAP_SUCCESS;
  526. return SLAPI_DSE_CALLBACK_OK;
  527. }
  528. /* This function is used by the instance modify callback to add a new
  529. * suffix. It return LDAP_SUCCESS on success.
  530. */
  531. int
  532. add_suffix(ldbm_instance *inst, struct berval **bvals, int apply_mod, char *returntext)
  533. {
  534. Slapi_DN suffix;
  535. int x;
  536. returntext[0] = '\0';
  537. for (x = 0; bvals[x]; x++) {
  538. slapi_sdn_init_dn_byref(&suffix, bvals[x]->bv_val);
  539. if (!slapi_be_issuffix(inst->inst_be, &suffix) && apply_mod) {
  540. be_addsuffix(inst->inst_be, &suffix);
  541. }
  542. slapi_sdn_done(&suffix);
  543. }
  544. return LDAP_SUCCESS;
  545. }
  546. /*
  547. * Config. DSE callback for instance entry modifies.
  548. */
  549. int
  550. ldbm_instance_modify_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
  551. {
  552. int i;
  553. char *attr_name;
  554. LDAPMod **mods;
  555. int rc = LDAP_SUCCESS;
  556. int apply_mod = 0;
  557. ldbm_instance *inst = (ldbm_instance *) arg;
  558. /* This lock is probably way too conservative, but we don't expect much
  559. * contention for it. */
  560. PR_Lock(inst->inst_config_mutex);
  561. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  562. returntext[0] = '\0';
  563. /*
  564. * First pass: set apply mods to 0 so only input validation will be done;
  565. * 2nd pass: set apply mods to 1 to apply changes to internal storage
  566. */
  567. for ( apply_mod = 0; apply_mod <= 1 && LDAP_SUCCESS == rc; apply_mod++ ) {
  568. for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
  569. attr_name = mods[i]->mod_type;
  570. if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) {
  571. /* naughty naughty, we don't allow this */
  572. rc = LDAP_UNWILLING_TO_PERFORM;
  573. if (returntext) {
  574. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
  575. "Can't change the root suffix of a backend");
  576. }
  577. LDAPDebug(LDAP_DEBUG_ANY,
  578. "ldbm: modify attempted to change the root suffix "
  579. "of a backend (which is not allowed)\n",
  580. 0, 0, 0);
  581. continue;
  582. }
  583. /* There are some attributes that we don't care about, like
  584. * modifiersname. */
  585. if (ldbm_config_ignored_attr(attr_name)) {
  586. continue;
  587. }
  588. if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
  589. (mods[i]->mod_op & LDAP_MOD_ADD)) {
  590. rc= LDAP_UNWILLING_TO_PERFORM;
  591. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
  592. (mods[i]->mod_op & LDAP_MOD_DELETE) ?
  593. "Deleting" : "Adding");
  594. } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
  595. /* This assumes there is only one bval for this mod. */
  596. rc = ldbm_config_set((void *) inst, attr_name,
  597. ldbm_instance_config, mods[i]->mod_bvalues[0], returntext,
  598. CONFIG_PHASE_RUNNING, apply_mod);
  599. }
  600. }
  601. }
  602. PR_Unlock(inst->inst_config_mutex);
  603. *returncode = rc;
  604. if (LDAP_SUCCESS == rc) {
  605. return SLAPI_DSE_CALLBACK_OK;
  606. } else {
  607. return SLAPI_DSE_CALLBACK_ERROR;
  608. }
  609. }
  610. /* This function is used to set instance config attributes. It can be used as a
  611. * shortcut to doing an internal modify operation on the config DSE.
  612. */
  613. void
  614. ldbm_instance_config_internal_set(ldbm_instance *inst, char *attrname, char *value)
  615. {
  616. char err_buf[BUFSIZ];
  617. struct berval bval;
  618. bval.bv_val = value;
  619. bval.bv_len = strlen(value);
  620. if (ldbm_config_set((void *) inst, attrname, ldbm_instance_config, &bval,
  621. err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */) != LDAP_SUCCESS) {
  622. LDAPDebug(LDAP_DEBUG_ANY,
  623. "Internal Error: Error setting instance config attr %s to %s: %s\n",
  624. attrname, value, err_buf);
  625. exit(1);
  626. }
  627. }
  628. static int ldbm_instance_generate(struct ldbminfo *li, char *instance_name,
  629. Slapi_Backend **ret_be)
  630. {
  631. Slapi_Backend *new_be = NULL;
  632. int rc = 0;
  633. /* Create a new instance, process config info for it,
  634. * and then call slapi_be_new and create a new backend here
  635. */
  636. new_be = slapi_be_new(LDBM_DATABASE_TYPE_NAME /* type */, instance_name,
  637. 0 /* public */, 1 /* do log changes */);
  638. new_be->be_database = li->li_plugin;
  639. ldbm_instance_create(new_be, instance_name);
  640. ldbm_instance_config_load_dse_info(new_be->be_instance_info);
  641. rc = ldbm_instance_create_default_indexes(new_be);
  642. /* if USN plugin is enabled, set slapi_counter */
  643. if (plugin_enabled("USN", li->li_identity)) {
  644. /* slapi_counter_new sets the initial value to 0 */
  645. new_be->be_usn_counter = slapi_counter_new();
  646. }
  647. if (ret_be != NULL) {
  648. *ret_be = new_be;
  649. }
  650. return rc;
  651. }
  652. int
  653. ldbm_instance_postadd_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  654. {
  655. backend *be = NULL;
  656. struct ldbm_instance *inst;
  657. char *instance_name;
  658. struct ldbminfo *li = (struct ldbminfo *)arg;
  659. int rval = 0;
  660. parse_ldbm_instance_entry(entryBefore, &instance_name);
  661. ldbm_instance_generate(li, instance_name, &be);
  662. inst = ldbm_instance_find_by_name(li, instance_name);
  663. /* Add default indexes */
  664. ldbm_instance_create_default_user_indexes(inst);
  665. /* Initialize and register callbacks for VLV indexes */
  666. vlv_init(inst);
  667. /* this is an ACTUAL ADD being done while the server is running!
  668. * start up the appropriate backend...
  669. */
  670. rval = ldbm_instance_start(be);
  671. if (0 != rval)
  672. {
  673. LDAPDebug(LDAP_DEBUG_ANY,
  674. "ldbm_instance_postadd_instance_entry_callback: "
  675. "ldbm_instnace_start (%s) failed (%d)\n",
  676. instance_name, rval, 0);
  677. }
  678. slapi_ch_free((void **)&instance_name);
  679. /* instance must be fully ready before we call this */
  680. slapi_mtn_be_started(be);
  681. return SLAPI_DSE_CALLBACK_OK;
  682. }
  683. int
  684. ldbm_instance_add_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  685. {
  686. char *instance_name;
  687. struct ldbm_instance *inst= NULL;
  688. struct ldbminfo *li= (struct ldbminfo *) arg;
  689. int rc = 0;
  690. parse_ldbm_instance_entry(entryBefore, &instance_name);
  691. /* Make sure we don't create two instances with the same name. */
  692. inst = ldbm_instance_find_by_name(li, instance_name);
  693. if (inst != NULL) {
  694. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: ldbm instance %s already exists\n",
  695. instance_name, 0, 0);
  696. if (returntext != NULL)
  697. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "An ldbm instance with the name %s already exists\n",
  698. instance_name);
  699. if (returncode != NULL)
  700. *returncode = LDAP_UNWILLING_TO_PERFORM;
  701. slapi_ch_free((void **)&instance_name);
  702. return SLAPI_DSE_CALLBACK_ERROR;
  703. }
  704. if (pb == NULL) {
  705. /* called during startup -- do the rest now */
  706. rc = ldbm_instance_generate(li, instance_name, NULL);
  707. if (!rc) {
  708. inst = ldbm_instance_find_by_name(li, instance_name);
  709. rc = ldbm_instance_create_default_user_indexes(inst);
  710. }
  711. }
  712. /* if called during a normal ADD operation, the postadd callback
  713. * will do the rest.
  714. */
  715. slapi_ch_free((void **)&instance_name);
  716. return (rc == 0) ? SLAPI_DSE_CALLBACK_OK : SLAPI_DSE_CALLBACK_ERROR;
  717. }
  718. /* unregister the DSE callbacks on a backend -- this needs to be done when
  719. * deleting a backend, so that adding the same backend later won't cause
  720. * these expired callbacks to be called.
  721. */
  722. static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
  723. {
  724. struct ldbminfo *li = inst->inst_li;
  725. char dn[BUFSIZ];
  726. /* tear down callbacks for the instance config entry */
  727. PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
  728. inst->inst_name, li->li_plugin->plg_name);
  729. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
  730. LDAP_SCOPE_BASE, "(objectclass=*)",
  731. ldbm_instance_search_config_entry_callback);
  732. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  733. LDAP_SCOPE_BASE, "(objectclass=*)",
  734. ldbm_instance_modify_config_entry_callback);
  735. slapi_config_remove_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
  736. LDAP_SCOPE_BASE, "(objectclass=*)",
  737. ldbm_instance_search_config_entry_callback);
  738. slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  739. LDAP_SCOPE_BASE, "(objectclass=*)",
  740. ldbm_instance_deny_config);
  741. /* now the cn=monitor entry */
  742. PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
  743. inst->inst_name, li->li_plugin->plg_name);
  744. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
  745. LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search);
  746. slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  747. LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config);
  748. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  749. LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config);
  750. /* now the cn=index entries */
  751. PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
  752. inst->inst_name, li->li_plugin->plg_name);
  753. slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  754. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  755. ldbm_instance_index_config_add_callback);
  756. slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
  757. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  758. ldbm_instance_index_config_delete_callback);
  759. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  760. LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
  761. ldbm_instance_index_config_modify_callback);
  762. /* now the cn=encrypted attributes entries */
  763. PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
  764. inst->inst_name, li->li_plugin->plg_name);
  765. slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
  766. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  767. ldbm_instance_attrcrypt_config_add_callback);
  768. slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
  769. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  770. ldbm_instance_attrcrypt_config_delete_callback);
  771. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
  772. LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
  773. ldbm_instance_attrcrypt_config_modify_callback);
  774. vlv_remove_callbacks(inst);
  775. }
  776. int
  777. ldbm_instance_post_delete_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  778. {
  779. char *instance_name;
  780. struct ldbminfo *li = (struct ldbminfo *)arg;
  781. struct ldbm_instance *inst = NULL;
  782. parse_ldbm_instance_entry(entryBefore, &instance_name);
  783. inst = ldbm_instance_find_by_name(li, instance_name);
  784. if (inst == NULL) {
  785. LDAPDebug(LDAP_DEBUG_ANY, "ldbm: instance '%s' does not exist! (2)\n",
  786. instance_name, 0, 0);
  787. if (returntext) {
  788. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No ldbm instance exists with the name '%s' (2)\n",
  789. instance_name);
  790. }
  791. if (returncode) {
  792. *returncode = LDAP_UNWILLING_TO_PERFORM;
  793. }
  794. slapi_ch_free((void **)&instance_name);
  795. return SLAPI_DSE_CALLBACK_ERROR;
  796. }
  797. LDAPDebug(LDAP_DEBUG_ANY, "ldbm: removing '%s'.\n", instance_name, 0, 0);
  798. {
  799. struct ldbminfo *li = (struct ldbminfo *) inst->inst_be->be_database->plg_private;
  800. dblayer_private *priv = (dblayer_private*) li->li_dblayer_private;
  801. struct dblayer_private_env *pEnv = priv->dblayer_env;
  802. if(pEnv) {
  803. PRDir *dirhandle = NULL;
  804. char inst_dir[MAXPATHLEN*2];
  805. char *inst_dirp = NULL;
  806. if (inst->inst_dir_name == NULL){
  807. dblayer_get_instance_data_dir(inst->inst_be);
  808. }
  809. inst_dirp = dblayer_get_full_inst_dir(li, inst,
  810. inst_dir, MAXPATHLEN*2);
  811. if (NULL != inst_dirp) {
  812. dirhandle = PR_OpenDir(inst_dirp);
  813. /* the db dir instance may have been removed already */
  814. if (dirhandle) {
  815. PRDirEntry *direntry = NULL;
  816. char *dbp = NULL;
  817. char *p = NULL;
  818. while (NULL != (direntry = PR_ReadDir(dirhandle,
  819. PR_SKIP_DOT|PR_SKIP_DOT_DOT))) {
  820. int rc;
  821. if (!direntry->name)
  822. break;
  823. dbp = PR_smprintf("%s/%s", inst_dirp, direntry->name);
  824. if (NULL == dbp) {
  825. LDAPDebug (LDAP_DEBUG_ANY,
  826. "ldbm_instance_post_delete_instance_entry_callback:"
  827. " failed to generate db path: %s/%s\n",
  828. inst_dirp, direntry->name, 0);
  829. break;
  830. }
  831. p = strstr(dbp, LDBM_FILENAME_SUFFIX);
  832. if (NULL != p &&
  833. strlen(p) == strlen(LDBM_FILENAME_SUFFIX)) {
  834. rc = dblayer_db_remove(pEnv, dbp, 0);
  835. } else {
  836. rc = PR_Delete(dbp);
  837. }
  838. PR_ASSERT(rc == 0);
  839. PR_smprintf_free(dbp);
  840. }
  841. PR_CloseDir(dirhandle);
  842. }
  843. PR_RmDir(inst_dirp);
  844. } /* non-null dirhandle */
  845. if (inst_dirp != inst_dir) {
  846. slapi_ch_free_string(&inst_dirp);
  847. }
  848. } /* non-null pEnv */
  849. }
  850. ldbm_instance_unregister_callbacks(inst);
  851. slapi_be_free(&inst->inst_be);
  852. ldbm_instance_destroy(inst);
  853. slapi_ch_free((void **)&instance_name);
  854. return SLAPI_DSE_CALLBACK_OK;
  855. }
  856. int
  857. ldbm_instance_delete_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  858. {
  859. char *instance_name;
  860. struct ldbminfo *li = (struct ldbminfo *)arg;
  861. struct ldbm_instance *inst = NULL;
  862. parse_ldbm_instance_entry(entryBefore, &instance_name);
  863. inst = ldbm_instance_find_by_name(li, instance_name);
  864. if (inst == NULL) {
  865. LDAPDebug(LDAP_DEBUG_ANY, "ldbm: instance '%s' does not exist!\n",
  866. instance_name, 0, 0);
  867. if (returntext) {
  868. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No ldbm instance exists with the name '%s'\n",
  869. instance_name);
  870. }
  871. if (returncode) {
  872. *returncode = LDAP_UNWILLING_TO_PERFORM;
  873. }
  874. slapi_ch_free((void **)&instance_name);
  875. return SLAPI_DSE_CALLBACK_ERROR;
  876. }
  877. /* check if some online task is happening */
  878. if (instance_set_busy(inst) != 0) {
  879. LDAPDebug(LDAP_DEBUG_ANY, "ldbm: '%s' is in the middle of a task. "
  880. "Cancel the task or wait for it to finish, "
  881. "then try again.\n", instance_name, 0, 0);
  882. if (returntext) {
  883. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "ldbm instance '%s' is in the middle of a "
  884. "task. Cancel the task or wait for it to finish, "
  885. "then try again.\n", instance_name);
  886. }
  887. if (returncode) {
  888. *returncode = LDAP_UNWILLING_TO_PERFORM;
  889. }
  890. slapi_ch_free((void **)&instance_name);
  891. return SLAPI_DSE_CALLBACK_ERROR;
  892. }
  893. /* okay, we're gonna delete this database instance. take it offline. */
  894. LDAPDebug(LDAP_DEBUG_ANY, "ldbm: Bringing %s offline...\n",
  895. instance_name, 0, 0);
  896. slapi_mtn_be_stopping(inst->inst_be);
  897. dblayer_instance_close(inst->inst_be);
  898. cache_destroy_please(&inst->inst_cache);
  899. slapi_ch_free((void **)&instance_name);
  900. return SLAPI_DSE_CALLBACK_OK;
  901. }