ldbm_index_config.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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 instance indexes.
  43. */
  44. #include "back-ldbm.h"
  45. #include "dblayer.h"
  46. /* Forward declarations for the callbacks */
  47. int ldbm_instance_index_config_add_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg);
  48. int ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg);
  49. /* attrinfo2ConfIndexes: converts attrinfo into "pres,eq,sub,approx"
  50. * as seen in index entries within dse.ldif
  51. */
  52. static char *attrinfo2ConfIndexes (struct attrinfo *pai)
  53. {
  54. char buffer[128];
  55. buffer[0] = '\0';
  56. if (!(IS_INDEXED( pai->ai_indexmask ))) { /* skip if no index */
  57. strcat (buffer, "none");
  58. }
  59. if (pai->ai_indexmask & INDEX_PRESENCE) {
  60. if (strlen (buffer)) {
  61. strcat (buffer, ",");
  62. }
  63. strcat (buffer, "pres");
  64. }
  65. if (pai->ai_indexmask & INDEX_EQUALITY) {
  66. if (strlen (buffer)) {
  67. strcat (buffer, ",");
  68. }
  69. strcat (buffer, "eq");
  70. }
  71. if (pai->ai_indexmask & INDEX_APPROX) {
  72. if (strlen(buffer)) {
  73. strcat (buffer, ",");
  74. }
  75. strcat (buffer, "approx");
  76. }
  77. if (pai->ai_indexmask & INDEX_SUB) {
  78. if (strlen (buffer)) {
  79. strcat (buffer, ",");
  80. }
  81. strcat (buffer, "sub");
  82. }
  83. return (slapi_ch_strdup (buffer) );
  84. }
  85. /* attrinfo2ConfMatchingRules: converts attrinfo into matching rule oids, as
  86. * seen in index entries within dse.ldif
  87. */
  88. static char *attrinfo2ConfMatchingRules (struct attrinfo *pai)
  89. {
  90. int i;
  91. char buffer[1024];
  92. buffer[0] = '\0';
  93. if (pai->ai_index_rules) {
  94. strcat (buffer, "\t");
  95. for (i = 0; pai->ai_index_rules[i]; i++) {
  96. PL_strcatn (buffer, sizeof(buffer), pai->ai_index_rules[i]);
  97. if (pai->ai_index_rules[i+1]) {
  98. PL_strcatn (buffer, sizeof(buffer), ",");
  99. }
  100. }
  101. }
  102. return (slapi_ch_strdup (buffer) );
  103. }
  104. /* used by the two callbacks below, to parse an index entry into something
  105. * awkward that we can pass to attr_index_config().
  106. */
  107. #define MAX_TMPBUF 1024
  108. #define ZCAT_SAFE(_buf, _x1, _x2) do { \
  109. if (strlen(_buf) + strlen(_x1) + strlen(_x2) + 2 < MAX_TMPBUF) { \
  110. strcat(_buf, _x1); \
  111. strcat(_buf, _x2); \
  112. } \
  113. } while (0)
  114. static int ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e,
  115. const char *trace_string,
  116. char **index_name)
  117. {
  118. char *arglist[] = { NULL, NULL, NULL, NULL };
  119. int argc = 0, i;
  120. int isFirst;
  121. Slapi_Attr *attr;
  122. const struct berval *attrValue;
  123. Slapi_Value *sval;
  124. char tmpBuf[MAX_TMPBUF];
  125. /* Get the name of the attribute to index which will be the value
  126. * of the cn attribute. */
  127. if (slapi_entry_attr_find(e, "cn", &attr) != 0) {
  128. LDAPDebug(LDAP_DEBUG_ANY, "Warning: malformed index entry %s\n",
  129. slapi_entry_get_dn(e), 0, 0);
  130. return LDAP_OPERATIONS_ERROR;
  131. }
  132. slapi_attr_first_value(attr, &sval);
  133. attrValue = slapi_value_get_berval(sval);
  134. if (NULL == attrValue->bv_val || 0 == strlen(attrValue->bv_val)) {
  135. LDAPDebug(LDAP_DEBUG_ANY,
  136. "Warning: malformed index entry %s -- empty index name\n",
  137. slapi_entry_get_dn(e), 0, 0);
  138. return LDAP_OPERATIONS_ERROR;
  139. }
  140. arglist[argc++] = slapi_ch_strdup(attrValue->bv_val);
  141. if (index_name != NULL) {
  142. *index_name = slapi_ch_strdup(attrValue->bv_val);
  143. }
  144. /* Get the list of index types from the entry. */
  145. if (0 == slapi_entry_attr_find(e, "nsIndexType", &attr)) {
  146. tmpBuf[0] = 0;
  147. isFirst = 1;
  148. for (i = slapi_attr_first_value(attr, &sval); i != -1;
  149. i = slapi_attr_next_value(attr, i, &sval)) {
  150. attrValue = slapi_value_get_berval(sval);
  151. if (NULL != attrValue->bv_val && strlen(attrValue->bv_val) > 0) {
  152. if (isFirst) {
  153. ZCAT_SAFE(tmpBuf, "", attrValue->bv_val);
  154. isFirst = 0;
  155. } else {
  156. ZCAT_SAFE(tmpBuf, ",", attrValue->bv_val);
  157. }
  158. }
  159. }
  160. if (0 == tmpBuf[0]) {
  161. LDAPDebug(LDAP_DEBUG_ANY,
  162. "Warning: malformed index entry %s -- empty nsIndexType\n",
  163. slapi_entry_get_dn(e), 0, 0);
  164. slapi_ch_free_string(index_name);
  165. for (i = 0; i < argc; i++) {
  166. slapi_ch_free((void **)&arglist[i]);
  167. }
  168. return LDAP_OPERATIONS_ERROR;
  169. }
  170. arglist[argc++] = slapi_ch_strdup(tmpBuf);
  171. }
  172. tmpBuf[0] = 0;
  173. /* Get the list of matching rules from the entry. */
  174. if (0 == slapi_entry_attr_find(e, "nsMatchingRule", &attr)) {
  175. isFirst = 1;
  176. for (i = slapi_attr_first_value(attr, &sval); i != -1;
  177. i = slapi_attr_next_value(attr, i, &sval)) {
  178. attrValue = slapi_value_get_berval(sval);
  179. if (NULL != attrValue->bv_val && strlen(attrValue->bv_val) > 0) {
  180. if (isFirst) {
  181. ZCAT_SAFE(tmpBuf, "", attrValue->bv_val);
  182. } else {
  183. ZCAT_SAFE(tmpBuf, ",", attrValue->bv_val);
  184. }
  185. }
  186. }
  187. }
  188. /* Get the substr begin length. note: pick the first value. */
  189. if (0 == slapi_entry_attr_find(e, INDEX_ATTR_SUBSTRBEGIN, &attr)) {
  190. i = slapi_attr_first_value(attr, &sval);
  191. if (-1 != i) {
  192. attrValue = slapi_value_get_berval(sval);
  193. if (NULL != attrValue->bv_val && strlen(attrValue->bv_val) > 0) {
  194. if (0 == tmpBuf[0]) {
  195. PR_snprintf(tmpBuf, MAX_TMPBUF, "%s=%s",
  196. INDEX_ATTR_SUBSTRBEGIN, attrValue->bv_val);
  197. } else {
  198. int tmpbuflen = strlen(tmpBuf);
  199. char *p = tmpBuf + tmpbuflen;
  200. PR_snprintf(p, MAX_TMPBUF - tmpbuflen, ",%s=%s",
  201. INDEX_ATTR_SUBSTRBEGIN, attrValue->bv_val);
  202. }
  203. }
  204. }
  205. }
  206. /* Get the substr middle length. note: pick the first value. */
  207. if (0 == slapi_entry_attr_find(e, INDEX_ATTR_SUBSTRMIDDLE, &attr)) {
  208. i = slapi_attr_first_value(attr, &sval);
  209. if (-1 != i) {
  210. attrValue = slapi_value_get_berval(sval);
  211. if (NULL != attrValue->bv_val && strlen(attrValue->bv_val) > 0) {
  212. if (0 == tmpBuf[0]) {
  213. PR_snprintf(tmpBuf, MAX_TMPBUF, "%s=%s",
  214. INDEX_ATTR_SUBSTRMIDDLE, attrValue->bv_val);
  215. } else {
  216. int tmpbuflen = strlen(tmpBuf);
  217. char *p = tmpBuf + tmpbuflen;
  218. PR_snprintf(p, MAX_TMPBUF - tmpbuflen, ",%s=%s",
  219. INDEX_ATTR_SUBSTRMIDDLE, attrValue->bv_val);
  220. }
  221. }
  222. }
  223. }
  224. /* Get the substr end length. note: pick the first value. */
  225. if (0 == slapi_entry_attr_find(e, INDEX_ATTR_SUBSTREND, &attr)) {
  226. i = slapi_attr_first_value(attr, &sval);
  227. if (-1 != i) {
  228. attrValue = slapi_value_get_berval(sval);
  229. if (NULL != attrValue->bv_val && strlen(attrValue->bv_val) > 0) {
  230. if (0 == tmpBuf[0]) {
  231. PR_snprintf(tmpBuf, MAX_TMPBUF, "%s=%s",
  232. INDEX_ATTR_SUBSTREND, attrValue->bv_val);
  233. } else {
  234. int tmpbuflen = strlen(tmpBuf);
  235. char *p = tmpBuf + tmpbuflen;
  236. PR_snprintf(p, MAX_TMPBUF - tmpbuflen, ",%s=%s",
  237. INDEX_ATTR_SUBSTREND, attrValue->bv_val);
  238. }
  239. }
  240. }
  241. }
  242. if (0 != tmpBuf[0]) {
  243. arglist[argc++] = slapi_ch_strdup(tmpBuf);
  244. }
  245. arglist[argc] = NULL;
  246. attr_index_config(inst->inst_be, (char *)trace_string, 0, argc, arglist, 0);
  247. for (i = 0; i < argc; i++) {
  248. slapi_ch_free((void **)&arglist[i]);
  249. }
  250. return LDAP_SUCCESS;
  251. }
  252. /*
  253. * Temp callback that gets called for each index entry when a new
  254. * instance is starting up.
  255. */
  256. int
  257. ldbm_index_init_entry_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  258. {
  259. ldbm_instance *inst = (ldbm_instance *) arg;
  260. returntext[0] = '\0';
  261. *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init",
  262. NULL);
  263. if (*returncode == LDAP_SUCCESS) {
  264. return SLAPI_DSE_CALLBACK_OK;
  265. } else {
  266. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Problem initializing index entry %s\n",
  267. slapi_entry_get_dn(e));
  268. return SLAPI_DSE_CALLBACK_ERROR;
  269. }
  270. }
  271. /*
  272. * Config DSE callback for index additions.
  273. */
  274. int
  275. ldbm_instance_index_config_add_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* eAfter, int *returncode, char *returntext, void *arg)
  276. {
  277. ldbm_instance *inst = (ldbm_instance *) arg;
  278. char *index_name;
  279. returntext[0] = '\0';
  280. *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name);
  281. if (*returncode == LDAP_SUCCESS) {
  282. struct attrinfo *ai = NULL;
  283. /* if the index is a "system" index, we assume it's being added by
  284. * by the server, and it's okay for the index to go online immediately.
  285. * if not, we set the index "offline" so it won't actually be used
  286. * until someone runs db2index on it.
  287. */
  288. if (! ldbm_attribute_always_indexed(index_name)) {
  289. ainfo_get(inst->inst_be, index_name, &ai);
  290. PR_ASSERT(ai != NULL);
  291. ai->ai_indexmask |= INDEX_OFFLINE;
  292. }
  293. slapi_ch_free((void **)&index_name);
  294. return SLAPI_DSE_CALLBACK_OK;
  295. } else {
  296. return SLAPI_DSE_CALLBACK_ERROR;
  297. }
  298. }
  299. /*
  300. * Config DSE callback for index deletes.
  301. */
  302. int
  303. ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
  304. {
  305. ldbm_instance *inst = (ldbm_instance *) arg;
  306. char *arglist[4];
  307. Slapi_Attr *attr;
  308. Slapi_Value *sval;
  309. const struct berval *attrValue;
  310. int argc = 0;
  311. int rc = SLAPI_DSE_CALLBACK_OK;
  312. struct attrinfo *ainfo = NULL;
  313. returntext[0] = '\0';
  314. *returncode = LDAP_SUCCESS;
  315. slapi_entry_attr_find(e, "cn", &attr);
  316. slapi_attr_first_value(attr, &sval);
  317. attrValue = slapi_value_get_berval(sval);
  318. arglist[argc++] = slapi_ch_strdup(attrValue->bv_val);
  319. arglist[argc++] = slapi_ch_strdup("none");
  320. arglist[argc] = NULL;
  321. attr_index_config(inst->inst_be, "From DSE delete", 0, argc, arglist, 0);
  322. slapi_ch_free((void **)&arglist[0]);
  323. slapi_ch_free((void **)&arglist[1]);
  324. ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo);
  325. if (NULL == ainfo) {
  326. *returncode = LDAP_UNAVAILABLE;
  327. rc = SLAPI_DSE_CALLBACK_ERROR;
  328. } else {
  329. if (dblayer_erase_index_file(inst->inst_be, ainfo, 0 /* do chkpt */)) {
  330. *returncode = LDAP_UNWILLING_TO_PERFORM;
  331. rc = SLAPI_DSE_CALLBACK_ERROR;
  332. }
  333. }
  334. return rc;
  335. }
  336. /*
  337. * Config DSE callback for index entry changes.
  338. *
  339. * this function is huge!
  340. */
  341. int
  342. ldbm_instance_index_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry *e,
  343. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  344. {
  345. ldbm_instance *inst = (ldbm_instance *)arg;
  346. Slapi_Attr *attr;
  347. Slapi_Value *sval;
  348. const struct berval *attrValue;
  349. struct attrinfo *ainfo = NULL;
  350. LDAPMod **mods;
  351. char *arglist[4];
  352. char *config_attr;
  353. char *origIndexTypes, *origMatchingRules;
  354. char **origIndexTypesArray = NULL;
  355. char **origMatchingRulesArray = NULL;
  356. char **addIndexTypesArray = NULL;
  357. char **addMatchingRulesArray = NULL;
  358. char **deleteIndexTypesArray = NULL;
  359. char **deleteMatchingRulesArray = NULL;
  360. int i, j;
  361. int dodeletes = 0;
  362. char tmpBuf[MAX_TMPBUF];
  363. returntext[0] = '\0';
  364. *returncode = LDAP_SUCCESS;
  365. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  366. slapi_entry_attr_find(e, "cn", &attr);
  367. slapi_attr_first_value(attr, &sval);
  368. attrValue = slapi_value_get_berval(sval);
  369. ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo);
  370. if (NULL == ainfo) {
  371. return SLAPI_DSE_CALLBACK_ERROR;
  372. }
  373. origIndexTypes = attrinfo2ConfIndexes(ainfo);
  374. origMatchingRules = attrinfo2ConfMatchingRules(ainfo);
  375. origIndexTypesArray = slapi_str2charray(origIndexTypes, ",");
  376. origMatchingRulesArray = slapi_str2charray(origMatchingRules, ",");
  377. for (i = 0; mods[i] != NULL; i++) {
  378. config_attr = (char *)mods[i]->mod_type;
  379. if (strcasecmp(config_attr, "nsIndexType") == 0) {
  380. if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) {
  381. for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) {
  382. charray_add(&addIndexTypesArray,
  383. slapi_ch_strdup(mods[i]->mod_bvalues[j]->bv_val));
  384. }
  385. continue;
  386. }
  387. if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) {
  388. if ((mods[i]->mod_bvalues == NULL) ||
  389. (mods[i]->mod_bvalues[0] == NULL)) {
  390. if (deleteIndexTypesArray) {
  391. charray_free(deleteIndexTypesArray);
  392. }
  393. deleteIndexTypesArray = charray_dup(origIndexTypesArray);
  394. } else {
  395. for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) {
  396. charray_add(&deleteIndexTypesArray,
  397. slapi_ch_strdup(mods[i]->mod_bvalues[j]->bv_val));
  398. }
  399. }
  400. continue;
  401. }
  402. }
  403. if (strcasecmp(config_attr, "nsMatchingRule") == 0) {
  404. if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) {
  405. for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) {
  406. charray_add(&addMatchingRulesArray,
  407. slapi_ch_strdup(mods[i]->mod_bvalues[j]->bv_val));
  408. }
  409. continue;
  410. }
  411. if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) {
  412. if ((mods[i]->mod_bvalues == NULL) ||
  413. (mods[i]->mod_bvalues[0] == NULL)) {
  414. if (deleteMatchingRulesArray) {
  415. charray_free(deleteMatchingRulesArray);
  416. }
  417. deleteMatchingRulesArray = charray_dup(origMatchingRulesArray);
  418. } else {
  419. for (j = 0; mods[i]->mod_bvalues[j] != NULL; j++) {
  420. charray_add(&deleteMatchingRulesArray,
  421. slapi_ch_strdup(mods[i]->mod_bvalues[j]->bv_val));
  422. }
  423. }
  424. continue;
  425. }
  426. }
  427. }
  428. /* create the new set of index types */
  429. if (deleteIndexTypesArray) {
  430. for (i = 0; origIndexTypesArray[i] != NULL; i++) {
  431. if (charray_inlist(deleteIndexTypesArray,
  432. origIndexTypesArray[i])) {
  433. slapi_ch_free((void **)&(origIndexTypesArray[i]));
  434. dodeletes = 1;
  435. if (origIndexTypesArray[i+1] != NULL) {
  436. for (j = i+1; origIndexTypesArray[j] != NULL; j++) {
  437. origIndexTypesArray[j-1] = origIndexTypesArray[j];
  438. }
  439. origIndexTypesArray[j-1] = NULL;
  440. i--;
  441. }
  442. }
  443. }
  444. }
  445. if (addIndexTypesArray) {
  446. for (i = 0; addIndexTypesArray[i] != NULL; i++) {
  447. if (!charray_inlist(origIndexTypesArray, addIndexTypesArray[i])) {
  448. charray_add(&origIndexTypesArray,
  449. slapi_ch_strdup(addIndexTypesArray[i]));
  450. }
  451. }
  452. }
  453. if (deleteMatchingRulesArray) {
  454. for (i = 0; origMatchingRulesArray[i] != NULL; i++) {
  455. if (charray_inlist(deleteMatchingRulesArray,
  456. origMatchingRulesArray[i])) {
  457. slapi_ch_free((void **)&(origMatchingRulesArray[i]));
  458. dodeletes = 1;
  459. if (origMatchingRulesArray[i+1] != NULL) {
  460. for (j = i+1; origMatchingRulesArray[j] != NULL; j++) {
  461. origMatchingRulesArray[j-1] = origMatchingRulesArray[j];
  462. }
  463. origMatchingRulesArray[j-1] = NULL;
  464. i--;
  465. }
  466. }
  467. }
  468. }
  469. if (addMatchingRulesArray) {
  470. for (i = 0; addMatchingRulesArray[i] != NULL; i++) {
  471. if (!charray_inlist(origMatchingRulesArray,
  472. addMatchingRulesArray[i])) {
  473. charray_add(&origMatchingRulesArray,
  474. slapi_ch_strdup(addMatchingRulesArray[i]));
  475. }
  476. }
  477. }
  478. if (dodeletes) {
  479. i = 0;
  480. arglist[i++] = slapi_ch_strdup(attrValue->bv_val);
  481. arglist[i++] = slapi_ch_strdup("none");
  482. arglist[i] = NULL;
  483. attr_index_config(inst->inst_be, "from DSE modify", 0, i, arglist, 0);
  484. /* Free args */
  485. slapi_ch_free((void **)&arglist[0]);
  486. slapi_ch_free((void **)&arglist[1]);
  487. }
  488. i = 0;
  489. arglist[i++] = slapi_ch_strdup(attrValue->bv_val);
  490. if (origIndexTypesArray && origIndexTypesArray[0]) {
  491. tmpBuf[0] = 0;
  492. ZCAT_SAFE(tmpBuf, "", origIndexTypesArray[0]);
  493. for (j = 1; origIndexTypesArray[j] != NULL; j++) {
  494. ZCAT_SAFE(tmpBuf, ",", origIndexTypesArray[j]);
  495. }
  496. arglist[i++] = slapi_ch_strdup(tmpBuf);
  497. } else {
  498. arglist[i++] = slapi_ch_strdup("none");
  499. }
  500. if (origMatchingRulesArray && origMatchingRulesArray[0]) {
  501. tmpBuf[0] = 0;
  502. ZCAT_SAFE(tmpBuf, "", origMatchingRulesArray[0]);
  503. for (j = 1; origMatchingRulesArray[j] != NULL; j++) {
  504. ZCAT_SAFE(tmpBuf, ",", origMatchingRulesArray[j]);
  505. }
  506. arglist[i++] = slapi_ch_strdup(tmpBuf);
  507. }
  508. arglist[i] = NULL;
  509. attr_index_config(inst->inst_be, "from DSE modify", 0, i, arglist, 0);
  510. /* Free args */
  511. for (i=0; arglist[i]; i++) {
  512. slapi_ch_free((void **)&arglist[i]);
  513. }
  514. if(origIndexTypesArray) {
  515. charray_free(origIndexTypesArray);
  516. }
  517. if(origMatchingRulesArray) {
  518. charray_free(origMatchingRulesArray);
  519. }
  520. if(addIndexTypesArray) {
  521. charray_free(addIndexTypesArray);
  522. }
  523. if(deleteIndexTypesArray) {
  524. charray_free(deleteIndexTypesArray);
  525. }
  526. if(addMatchingRulesArray) {
  527. charray_free(addMatchingRulesArray);
  528. }
  529. if(deleteMatchingRulesArray) {
  530. charray_free(deleteMatchingRulesArray);
  531. }
  532. if (origIndexTypes) {
  533. slapi_ch_free ((void **)&origIndexTypes);
  534. }
  535. if (origMatchingRules) {
  536. slapi_ch_free ((void **)&origMatchingRules);
  537. }
  538. return SLAPI_DSE_CALLBACK_OK;
  539. }
  540. /* add index entries to the per-instance DSE (used only from instance.c) */
  541. int ldbm_instance_config_add_index_entry(
  542. ldbm_instance *inst,
  543. int argc,
  544. char **argv,
  545. int flags
  546. )
  547. {
  548. char **attrs = NULL;
  549. char **indexes = NULL;
  550. char **matchingRules = NULL;
  551. char *eBuf;
  552. int i = 0;
  553. int j = 0;
  554. char *basetype = NULL;
  555. char tmpAttrsStr[256];
  556. char tmpIndexesStr[256];
  557. char tmpMatchingRulesStr[1024];
  558. struct ldbminfo *li = inst->inst_li;
  559. if ((argc < 2) || (NULL == argv) || (NULL == argv[0]) ||
  560. (NULL == argv[1])) {
  561. return(-1);
  562. }
  563. PL_strncpyz(tmpAttrsStr,argv[0], sizeof(tmpAttrsStr));
  564. attrs = slapi_str2charray( tmpAttrsStr, "," );
  565. PL_strncpyz(tmpIndexesStr,argv[1], sizeof(tmpIndexesStr));
  566. indexes = slapi_str2charray( tmpIndexesStr, ",");
  567. if(argc > 2) {
  568. PL_strncpyz(tmpMatchingRulesStr,argv[2], sizeof(tmpMatchingRulesStr));
  569. matchingRules = slapi_str2charray( tmpMatchingRulesStr, ",");
  570. }
  571. for(i=0; attrs[i] !=NULL; i++)
  572. {
  573. if('\0' == attrs[i][0]) continue;
  574. basetype = slapi_attr_basetype(attrs[i], NULL, 0);
  575. eBuf = PR_smprintf(
  576. "dn: cn=%s, cn=index, cn=%s, cn=%s, cn=plugins, cn=config\n"
  577. "objectclass:top\n"
  578. "objectclass:nsIndex\n"
  579. "cn:%s\n"
  580. "nsSystemIndex:%s\n",
  581. basetype, inst->inst_name, li->li_plugin->plg_name,
  582. basetype,
  583. (ldbm_attribute_always_indexed(basetype)?"true":"false"));
  584. for(j=0; indexes[j] != NULL; j++)
  585. {
  586. eBuf = PR_sprintf_append(eBuf, "nsIndexType:%s\n", indexes[j]);
  587. }
  588. if((argc>2)&&(argv[2]))
  589. {
  590. for(j=0; matchingRules[j] != NULL; j++)
  591. {
  592. eBuf = PR_sprintf_append(eBuf, "nsMatchingRule:%s\n", matchingRules[j]);
  593. }
  594. }
  595. ldbm_config_add_dse_entry(li, eBuf, flags);
  596. if (eBuf) {
  597. PR_smprintf_free(eBuf);
  598. }
  599. slapi_ch_free((void**)&basetype);
  600. }
  601. if(NULL != attrs) {
  602. charray_free(attrs);
  603. }
  604. if(NULL != indexes) {
  605. charray_free(indexes);
  606. }
  607. if(NULL != matchingRules) {
  608. charray_free(matchingRules);
  609. }
  610. return (0);
  611. }
  612. int
  613. ldbm_instance_index_config_enable_index(ldbm_instance *inst, Slapi_Entry* e)
  614. {
  615. char *index_name;
  616. int rc;
  617. rc=ldbm_index_parse_entry(inst, e, "from DSE add", &index_name);
  618. if (rc == LDAP_SUCCESS) {
  619. struct attrinfo *ai = NULL;
  620. /* Assume the caller knows if it is OK to go online immediatly */
  621. ainfo_get(inst->inst_be, index_name, &ai);
  622. PR_ASSERT(ai != NULL);
  623. ai->ai_indexmask &= ~INDEX_OFFLINE;
  624. slapi_ch_free((void **)&index_name);
  625. }
  626. return rc;
  627. }
  628. /*
  629. ** create the default user-defined indexes
  630. */
  631. int ldbm_instance_create_default_user_indexes(ldbm_instance *inst)
  632. {
  633. /*
  634. ** Search for user-defined default indexes and add them
  635. ** to the backend instance beeing created.
  636. */
  637. Slapi_PBlock *aPb;
  638. Slapi_Entry **entries = NULL;
  639. Slapi_Attr *attr;
  640. Slapi_Value *sval = NULL;
  641. const struct berval *attrValue;
  642. char *argv[ 8 ];
  643. char basedn[BUFSIZ];
  644. char tmpBuf[MAX_TMPBUF];
  645. char tmpBuf2[MAX_TMPBUF];
  646. int argc;
  647. struct ldbminfo *li;
  648. /* write the dse file only on the final index */
  649. int flags = LDBM_INSTANCE_CONFIG_DONT_WRITE;
  650. if (NULL == inst) {
  651. LDAPDebug(LDAP_DEBUG_ANY,
  652. "Warning: can't initialize default user indexes (invalid instance).\n", 0,0,0);
  653. return -1;
  654. }
  655. li = inst->inst_li;
  656. strcpy(tmpBuf,"");
  657. /* Construct the base dn of the subtree that holds the default user indexes. */
  658. PR_snprintf(basedn, BUFSIZ, "cn=default indexes, cn=config, cn=%s, cn=plugins, cn=config",
  659. li->li_plugin->plg_name);
  660. /* Do a search of the subtree containing the index entries */
  661. aPb = slapi_pblock_new();
  662. slapi_search_internal_set_pb(aPb, basedn, LDAP_SCOPE_SUBTREE,
  663. "(objectclass=nsIndex)", NULL, 0 , NULL, NULL, li->li_identity, 0);
  664. slapi_search_internal_pb (aPb);
  665. slapi_pblock_get(aPb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  666. if (entries!=NULL) {
  667. int i,j;
  668. for (i=0; entries[i]!=NULL; i++) {
  669. /* Get the name of the attribute to index which will be the value
  670. * of the cn attribute. */
  671. if (slapi_entry_attr_find(entries[i], "cn", &attr) != 0) {
  672. LDAPDebug(LDAP_DEBUG_ANY,"Warning: malformed index entry %s. Index ignored.\n",
  673. slapi_entry_get_dn(entries[i]), 0, 0);
  674. continue;
  675. }
  676. slapi_attr_first_value(attr, &sval);
  677. attrValue = slapi_value_get_berval(sval);
  678. argv[0] = attrValue->bv_val;
  679. argc=1;
  680. /* Get the list of index types from the entry. */
  681. if (0 == slapi_entry_attr_find(entries[i], "nsIndexType", &attr)) {
  682. for (j = slapi_attr_first_value(attr, &sval); j != -1;
  683. j = slapi_attr_next_value(attr, j, &sval)) {
  684. attrValue = slapi_value_get_berval(sval);
  685. if (0 == j) {
  686. tmpBuf[0] = 0;
  687. ZCAT_SAFE(tmpBuf, "", attrValue->bv_val);
  688. } else {
  689. ZCAT_SAFE(tmpBuf, ",", attrValue->bv_val);
  690. }
  691. }
  692. argv[argc]=tmpBuf;
  693. argc++;
  694. }
  695. /* Get the list of matching rules from the entry. */
  696. if (0 == slapi_entry_attr_find(entries[i], "nsMatchingRule", &attr)) {
  697. for (j = slapi_attr_first_value(attr, &sval); j != -1;
  698. j = slapi_attr_next_value(attr, j, &sval)) {
  699. attrValue = slapi_value_get_berval(sval);
  700. if (0 == j) {
  701. tmpBuf2[0] = 0;
  702. ZCAT_SAFE(tmpBuf2, "", attrValue->bv_val);
  703. } else {
  704. ZCAT_SAFE(tmpBuf2, ",", attrValue->bv_val);
  705. }
  706. }
  707. argv[argc]=tmpBuf2;
  708. argc++;
  709. }
  710. argv[argc]=NULL;
  711. /* Create the index entry in the backend */
  712. if (entries[i+1] == NULL) {
  713. /* write the dse file only on the final index */
  714. flags = 0;
  715. }
  716. ldbm_instance_config_add_index_entry(inst, argc, argv, flags);
  717. /* put the index online */
  718. ldbm_instance_index_config_enable_index(inst, entries[i]);
  719. }
  720. }
  721. slapi_free_search_results_internal(aPb);
  722. slapi_pblock_destroy(aPb);
  723. return 0;
  724. }