index.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013
  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. /* index.c - routines for dealing with attribute indexes */
  39. #include "back-ldbm.h"
  40. #if ( defined ( OSF1 ))
  41. #undef BUFSIZ
  42. #define BUFSIZ 1024
  43. #endif
  44. static const char *errmsg = "database index operation failed";
  45. static int is_indexed (const char* indextype, int indexmask, char** index_rules);
  46. static char* index2prefix (const char* indextype);
  47. static void free_prefix (char*);
  48. static Slapi_Value **
  49. valuearray_minus_valuearray(
  50. void *plugin,
  51. Slapi_Value **a,
  52. Slapi_Value **b
  53. );
  54. const char* indextype_PRESENCE = "pres";
  55. const char* indextype_EQUALITY = "eq";
  56. const char* indextype_APPROX = "approx";
  57. const char* indextype_SUB = "sub";
  58. static char prefix_PRESENCE[2] = {PRES_PREFIX, 0};
  59. static char prefix_EQUALITY[2] = {EQ_PREFIX, 0};
  60. static char prefix_APPROX [2] = {APPROX_PREFIX, 0};
  61. static char prefix_SUB [2] = {SUB_PREFIX, 0};
  62. /* Yes, prefix_PRESENCE and prefix_SUB are identical.
  63. * It works because SUB is always followed by a key value,
  64. * but PRESENCE never is. Too slick by half.
  65. */
  66. /* Structures for index key buffering magic used by import code */
  67. struct _index_buffer_bin {
  68. DBT key;
  69. IDList *value;
  70. };
  71. typedef struct _index_buffer_bin index_buffer_bin;
  72. struct _index_buffer_handle {
  73. int flags;
  74. size_t buffer_size;
  75. size_t idl_size;
  76. size_t max_key_length;
  77. index_buffer_bin *bins;
  78. unsigned char high_key_byte_range;
  79. unsigned char low_key_byte_range;
  80. unsigned char special_byte_a;
  81. unsigned char special_byte_b;
  82. size_t byte_range;
  83. /* Statistics */
  84. int inserts;
  85. int keys;
  86. };
  87. typedef struct _index_buffer_handle index_buffer_handle;
  88. #define INDEX_BUFFER_FLAG_SERIALIZE 1
  89. #define INDEX_BUFFER_FLAG_STATS 2
  90. /* Index buffering functions */
  91. static int
  92. index_buffer_init_internal(size_t idl_size,
  93. unsigned char high_key_byte_range, unsigned char low_key_byte_range,
  94. size_t max_key_length,unsigned char special_byte_a, unsigned char special_byte_b,
  95. int flags,void **h)
  96. {
  97. size_t bin_count = 0;
  98. /* Allocate the handle */
  99. index_buffer_bin *bins = NULL;
  100. size_t i = 0;
  101. size_t byte_range = 0;
  102. index_buffer_handle *handle = (index_buffer_handle *) slapi_ch_calloc(1,sizeof(index_buffer_handle));
  103. if (NULL == handle) {
  104. return -1;
  105. }
  106. handle->idl_size = idl_size;
  107. handle->flags = flags;
  108. handle->high_key_byte_range = high_key_byte_range;
  109. handle->low_key_byte_range = low_key_byte_range;
  110. handle->special_byte_a = special_byte_a;
  111. handle->special_byte_b = special_byte_b;
  112. handle->max_key_length = max_key_length;
  113. byte_range = (high_key_byte_range - low_key_byte_range) + 3 + 10;
  114. handle->byte_range = byte_range;
  115. /* Allocate the bins */
  116. bin_count = 1;
  117. for (i = 0 ; i < max_key_length - 2; i++) {
  118. bin_count *= byte_range;
  119. }
  120. handle->buffer_size = bin_count;
  121. bins = (index_buffer_bin *)slapi_ch_calloc(bin_count, sizeof(index_buffer_bin));
  122. if (NULL == bins) {
  123. return -1;
  124. }
  125. handle->bins = bins;
  126. *h = (void*) handle;
  127. return 0;
  128. }
  129. int index_buffer_init(size_t size,int flags,void **h)
  130. {
  131. return index_buffer_init_internal(size,'z','a',5,'^','$',flags,h);
  132. }
  133. static int
  134. index_put_idl(index_buffer_bin *bin,backend *be, DB_TXN *txn,struct attrinfo *a)
  135. {
  136. int ret = 0;
  137. DB *db = NULL;
  138. int need_to_freed_new_idl = 0;
  139. IDList *old_idl = NULL;
  140. IDList *new_idl = NULL;
  141. if ( (ret = dblayer_get_index_file( be, a, &db, DBOPEN_CREATE )) != 0 ) {
  142. return ret;
  143. }
  144. if (bin->key.data && bin->value) {
  145. /* Need to read the IDL at the key, if present, and form the union with what we have */
  146. ret = NEW_IDL_NOOP; /* this flag is for new idl only;
  147. * but this func is called only from index_buffer,
  148. * which is enabled only for old idl.
  149. */
  150. old_idl = idl_fetch(be,db,&bin->key,txn,a,&ret);
  151. if ( (0 != ret) && (DB_NOTFOUND != ret)) {
  152. goto error;
  153. }
  154. if ( (old_idl != NULL) && !ALLIDS(old_idl)) {
  155. /* We need to merge in our block with what was there */
  156. new_idl = idl_union(be,old_idl,bin->value);
  157. need_to_freed_new_idl = 1;
  158. } else {
  159. /* Nothing there previously, we store just what we have */
  160. new_idl = bin->value;
  161. }
  162. /* Then write back the result, but only if the existing idl wasn't ALLIDS */
  163. if (!old_idl || (old_idl && !ALLIDS(old_idl))) {
  164. ret = idl_store_block(be,db,&bin->key,new_idl,txn,a);
  165. }
  166. if (0 != ret) {
  167. goto error;
  168. }
  169. slapi_ch_free((void**)&bin->key.data );
  170. idl_free(bin->value);
  171. /* If we're already at allids, store an allids block to prevent needless accumulation of blocks */
  172. if (old_idl && ALLIDS(old_idl)) {
  173. bin->value = idl_allids(be);
  174. } else {
  175. bin->value = NULL;
  176. }
  177. }
  178. error:
  179. if (old_idl) {
  180. idl_free(old_idl);
  181. }
  182. if (new_idl && need_to_freed_new_idl) {
  183. idl_free(new_idl);
  184. }
  185. dblayer_release_index_file( be, a, db );
  186. return ret;
  187. }
  188. /* The caller MUST check for DB_RUNRECOVERY being returned */
  189. int
  190. index_buffer_flush(void *h,backend *be, DB_TXN *txn,struct attrinfo *a)
  191. {
  192. index_buffer_handle *handle = (index_buffer_handle *) h;
  193. index_buffer_bin *bin = NULL;
  194. int ret = 0;
  195. size_t i = 0;
  196. DB *db = NULL;
  197. PR_ASSERT(h);
  198. /* Note to the wary: here we do NOT create the index file up front */
  199. /* This is becuase there may be no buffers to flush, and the goal is to
  200. * never create the index file (merging gets confused by this, among other things */
  201. /* Walk along the bins, writing them to the database */
  202. for (i = 0; i < handle->buffer_size; i++) {
  203. bin = &(handle->bins[i]);
  204. if (bin->key.data && bin->value) {
  205. if (NULL == db) {
  206. if ( (ret = dblayer_get_index_file( be, a, &db, DBOPEN_CREATE )) != 0 ) {
  207. return ret;
  208. }
  209. }
  210. ret = index_put_idl(bin,be,txn,a);
  211. if (0 != ret) {
  212. goto error;
  213. }
  214. }
  215. }
  216. error:
  217. if (NULL != db) {
  218. dblayer_release_index_file( be, a, db );
  219. }
  220. return ret;
  221. }
  222. int
  223. index_buffer_terminate(void *h)
  224. {
  225. index_buffer_handle *handle = (index_buffer_handle *) h;
  226. index_buffer_bin *bin = NULL;
  227. size_t i = 0;
  228. PR_ASSERT(h);
  229. /* Free all the buffers */
  230. /* First walk down the bins, freeing the IDLs and the bins they're in */
  231. for (i = 0; i < handle->buffer_size; i++) {
  232. bin = &(handle->bins[i]);
  233. if (bin->value) {
  234. idl_free(bin->value);
  235. bin->value = NULL;
  236. }
  237. if (bin->key.data) {
  238. free(bin->key.data);
  239. }
  240. }
  241. free(handle->bins);
  242. /* Now free the handle */
  243. free(handle);
  244. return 0;
  245. }
  246. /* This function returns -1 or -2 for local errors, and DB_ errors as well. */
  247. static int
  248. index_buffer_insert(void *h, DBT *key, ID id,backend *be, DB_TXN *txn,struct attrinfo *a)
  249. {
  250. index_buffer_handle *handle = (index_buffer_handle *) h;
  251. index_buffer_bin *bin = NULL;
  252. size_t index = 0;
  253. int idl_ret = 0;
  254. unsigned char x = 0;
  255. unsigned int i = 0;
  256. int ret = 0;
  257. PR_ASSERT(h);
  258. /* Check key length for validity */
  259. if (key->size > handle->max_key_length) {
  260. return -2;
  261. }
  262. /* discard the first character, as long as its the substring prefix */
  263. if ((unsigned char)((char*)key->data)[0] != SUB_PREFIX) {
  264. return -2;
  265. }
  266. /* Compute the bin index from the key */
  267. /* Walk along the key data, byte by byte */
  268. for (i = 1; i < (key->size - 1); i++) {
  269. /* foreach byte, normalize to the range we accept */
  270. x = (unsigned char) ((char*)key->data)[i];
  271. if ( (x == handle->special_byte_a) || (x == handle->special_byte_b) ) {
  272. if (x == handle->special_byte_a) {
  273. x = handle->high_key_byte_range + 1;
  274. }
  275. if (x == handle->special_byte_b) {
  276. x = handle->high_key_byte_range + 2;
  277. }
  278. } else {
  279. if ( x >= '0' && x <= '9' ) {
  280. x = (x - '0') + handle->high_key_byte_range + 3;
  281. } else {
  282. if (x > handle->high_key_byte_range) {
  283. return -2; /* Out of range */
  284. }
  285. if (x < handle->low_key_byte_range) {
  286. return -2; /* Out of range */
  287. }
  288. }
  289. }
  290. x = x - handle->low_key_byte_range;
  291. index *= handle->byte_range;
  292. index += x;
  293. }
  294. /* Check that the last byte in the key is zero */
  295. if (0 != (unsigned char)((char*)key->data)[i]) {
  296. return -2;
  297. }
  298. PR_ASSERT(index < handle->buffer_size);
  299. /* Get the bin */
  300. bin = &(handle->bins[index]);
  301. /* Is the key already there ? */
  302. retry:
  303. if (!(bin->key).data) {
  304. (bin->key).size = key->size;
  305. (bin->key).data = malloc(key->size);
  306. if (NULL == bin->key.data) {
  307. return -1;
  308. }
  309. memcpy(bin->key.data,key->data,key->size);
  310. /* Make the IDL */
  311. bin->value = idl_alloc(handle->idl_size);
  312. if (!bin->value) {
  313. return -1;
  314. }
  315. }
  316. idl_ret = idl_append(bin->value, id);
  317. if (0 != idl_ret) {
  318. if (1 == idl_ret) {
  319. /* ID already present */
  320. } else {
  321. /* If we get to here, it means that we've overflowed our IDL */
  322. /* So, we need to write it out to the DB and zero out the pointers */
  323. ret = index_put_idl(bin,be,txn,a);
  324. /* Now we need to append the ID we have at hand */
  325. if (0 == ret) {
  326. goto retry;
  327. }
  328. }
  329. }
  330. return ret;
  331. }
  332. /*
  333. * Add or Delete an entry from the attribute indexes.
  334. * 'flags' is either BE_INDEX_ADD or BE_INDEX_DEL
  335. */
  336. int
  337. index_addordel_entry(
  338. backend *be,
  339. struct backentry *e,
  340. int flags,
  341. back_txn *txn
  342. )
  343. {
  344. char *type;
  345. Slapi_Value **svals;
  346. int rc, result;
  347. Slapi_Attr *attr;
  348. LDAPDebug( LDAP_DEBUG_TRACE, "=> index_%s_entry( \"%s\", %lu )\n",
  349. (flags & BE_INDEX_ADD) ? "add" : "del",
  350. backentry_get_ndn(e), (u_long)e->ep_id );
  351. /* if we are adding a tombstone entry (see ldbm_add.c) */
  352. if ((flags & BE_INDEX_TOMBSTONE) && (flags & BE_INDEX_ADD))
  353. {
  354. Slapi_DN parent;
  355. Slapi_DN *sdn = slapi_entry_get_sdn(e->ep_entry);
  356. slapi_sdn_init(&parent);
  357. slapi_sdn_get_parent(sdn, &parent);
  358. /*
  359. * Just index the "nstombstone" attribute value from the objectclass
  360. * attribute, and the nsuniqueid attribute value, and the entrydn value of the deleted entry.
  361. */
  362. result = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE, e->ep_id, flags, txn);
  363. if ( result != 0 ) {
  364. ldbm_nasty(errmsg, 1010, result);
  365. return( result );
  366. }
  367. result = index_addordel_string(be, SLAPI_ATTR_UNIQUEID, slapi_entry_get_uniqueid(e->ep_entry), e->ep_id, flags, txn);
  368. if ( result != 0 ) {
  369. ldbm_nasty(errmsg, 1020, result);
  370. return( result );
  371. }
  372. result = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&parent), e->ep_id, flags, txn);
  373. if ( result != 0 ) {
  374. ldbm_nasty(errmsg, 1020, result);
  375. return( result );
  376. }
  377. slapi_sdn_done(&parent);
  378. }
  379. else
  380. {
  381. /* add each attribute to the indexes */
  382. rc = 0, result = 0;
  383. for ( rc = slapi_entry_first_attr( e->ep_entry, &attr ); rc == 0;
  384. rc = slapi_entry_next_attr( e->ep_entry, attr, &attr ) ) {
  385. slapi_attr_get_type( attr, &type );
  386. svals = attr_get_present_values(attr);
  387. result = index_addordel_values_sv( be, type, svals, NULL, e->ep_id,
  388. flags, txn );
  389. if ( result != 0 ) {
  390. ldbm_nasty(errmsg, 1030, result);
  391. return( result );
  392. }
  393. }
  394. /* update ancestorid index . . . */
  395. /* . . . only if we are not deleting a tombstone entry - tombstone entries are not in the ancestor id index - see bug 603279 */
  396. if (!((flags & BE_INDEX_TOMBSTONE) && (flags & BE_INDEX_DEL))) {
  397. result = ldbm_ancestorid_index_entry(be, e, flags, txn);
  398. if ( result != 0 ) {
  399. return( result );
  400. }
  401. }
  402. }
  403. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_%s_entry%s %d\n",
  404. (flags & BE_INDEX_ADD) ? "add" : "del",
  405. (flags & BE_INDEX_TOMBSTONE) ? " (tombstone)" : "", result );
  406. return( result );
  407. }
  408. /*
  409. * Add ID to attribute indexes for which Add/Replace/Delete modifications exist
  410. * [olde is the OLD entry, before modifications]
  411. * [newe is the NEW entry, after modifications]
  412. * the old entry is used for REPLACE; the new for DELETE */
  413. int
  414. index_add_mods(
  415. backend *be,
  416. const LDAPMod **mods,
  417. struct backentry *olde,
  418. struct backentry *newe,
  419. back_txn *txn
  420. )
  421. {
  422. int rc = 0;
  423. int i, j;
  424. ID id = olde->ep_id;
  425. int flags = 0;
  426. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  427. char *basetype = NULL;
  428. char *tmp = NULL;
  429. Slapi_Attr *curr_attr = NULL;
  430. Slapi_ValueSet *all_vals = NULL;
  431. Slapi_ValueSet *mod_vals = NULL;
  432. Slapi_Value **evals = NULL; /* values that still exist after a
  433. * delete.
  434. */
  435. Slapi_Value **mods_valueArray = NULL; /* values that are specified in this
  436. * operation.
  437. */
  438. Slapi_Value **deleted_valueArray = NULL; /* values whose index entries
  439. * should be deleted.
  440. */
  441. for ( i = 0; mods[i] != NULL; i++ ) {
  442. /* Get base attribute type */
  443. basetype = buf;
  444. tmp = slapi_attr_basetype(mods[i]->mod_type, buf, sizeof(buf));
  445. if(tmp != NULL) {
  446. basetype = tmp; /* basetype was malloc'd */
  447. }
  448. /* Get a list of all remaining values for the base type
  449. * and any present subtypes.
  450. */
  451. all_vals = slapi_valueset_new();
  452. for (curr_attr = newe->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  453. if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
  454. valueset_add_valuearray(all_vals, attr_get_present_values(curr_attr));
  455. }
  456. }
  457. evals = valueset_get_valuearray(all_vals);
  458. /* Get a list of all values specified in the operation.
  459. */
  460. if ( mods[i]->mod_bvalues != NULL ) {
  461. valuearray_init_bervalarray(mods[i]->mod_bvalues,
  462. &mods_valueArray);
  463. }
  464. switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) {
  465. case LDAP_MOD_REPLACE:
  466. flags = BE_INDEX_DEL;
  467. /* Get a list of all values being deleted.
  468. */
  469. mod_vals = slapi_valueset_new();
  470. for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  471. if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
  472. valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
  473. }
  474. }
  475. deleted_valueArray = valueset_get_valuearray(mod_vals);
  476. /* If subtypes exist, don't remove the presence
  477. * index.
  478. */
  479. if ( evals != NULL && deleted_valueArray != NULL) {
  480. /* evals will contain the new value that is being
  481. * added as part of the replace operation if one
  482. * was specified. We must remove this value from
  483. * evals to know if any subtypes are present.
  484. */
  485. slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr );
  486. if ( mods_valueArray != NULL ) {
  487. for ( j = 0; mods_valueArray[j] != NULL; j++ ) {
  488. valuearray_remove_value(curr_attr, evals, mods_valueArray[j]);
  489. }
  490. }
  491. /* Search evals for the values being deleted. If
  492. * they don't exist, delete the equality index.
  493. */
  494. for ( j = 0; deleted_valueArray[j] != NULL; j++ ) {
  495. if (valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1) {
  496. if (!(flags & BE_INDEX_EQUALITY)) {
  497. flags |= BE_INDEX_EQUALITY;
  498. }
  499. } else {
  500. /* Remove duplicate value from deleted value array */
  501. valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
  502. j--;
  503. }
  504. }
  505. } else {
  506. flags |= BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  507. }
  508. /* We need to first remove the old values from the
  509. * index. */
  510. index_addordel_values_sv( be, mods[i]->mod_type,
  511. deleted_valueArray, evals, id,
  512. flags, txn );
  513. /* Free valuearray */
  514. slapi_valueset_free(mod_vals);
  515. case LDAP_MOD_ADD:
  516. if ( mods_valueArray == NULL ) {
  517. rc = 0;
  518. } else {
  519. rc = index_addordel_values_sv( be,
  520. mods[i]->mod_type,
  521. mods_valueArray, NULL,
  522. id, BE_INDEX_ADD, txn );
  523. }
  524. break;
  525. case LDAP_MOD_DELETE:
  526. if ( (mods[i]->mod_bvalues == NULL) ||
  527. (mods[i]->mod_bvalues[0] == NULL) ) {
  528. rc = 0;
  529. flags = BE_INDEX_DEL;
  530. /* Get a list of all values that are being
  531. * deleted.
  532. */
  533. mod_vals = slapi_valueset_new();
  534. for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  535. if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
  536. valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
  537. }
  538. }
  539. deleted_valueArray = valueset_get_valuearray(mod_vals);
  540. /* If subtypes exist, don't remove the
  541. * presence index.
  542. */
  543. if (evals != NULL) {
  544. for (curr_attr = newe->ep_entry->e_attrs; (curr_attr != NULL);
  545. curr_attr = curr_attr->a_next) {
  546. if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
  547. /* Check if the any values being deleted
  548. * also exist in a subtype.
  549. */
  550. for ( j=0; deleted_valueArray[j] != NULL; j++) {
  551. if ( valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1 ) {
  552. /* If the equality flag isn't already set, set it */
  553. if (!(flags & BE_INDEX_EQUALITY)) {
  554. flags |= BE_INDEX_EQUALITY;
  555. }
  556. } else {
  557. /* Remove duplicate value from the mod list */
  558. valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
  559. j--;
  560. }
  561. }
  562. }
  563. }
  564. } else {
  565. flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  566. }
  567. /* Update the index */
  568. index_addordel_values_sv( be, mods[i]->mod_type,
  569. deleted_valueArray, evals, id, flags, txn);
  570. slapi_valueset_free(mod_vals);
  571. } else {
  572. /* determine if the presence key should be
  573. * removed (are we removing the last value
  574. * for this attribute?)
  575. */
  576. if (evals == NULL || evals[0] == NULL) {
  577. flags = BE_INDEX_DEL|BE_INDEX_PRESENCE;
  578. } else {
  579. flags = BE_INDEX_DEL;
  580. }
  581. /* If the same value doesn't exist in a subtype, set
  582. * BE_INDEX_EQUALITY flag so the equality index is
  583. * removed.
  584. */
  585. slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr);
  586. if ( valuearray_find(curr_attr, evals, mods_valueArray[i]) == -1 ) {
  587. flags |= BE_INDEX_EQUALITY;
  588. }
  589. rc = index_addordel_values_sv( be, basetype,
  590. mods_valueArray,
  591. evals, id, flags, txn );
  592. }
  593. rc = 0;
  594. break;
  595. }
  596. /* free memory */
  597. slapi_ch_free((void **)&tmp);
  598. valuearray_free(&mods_valueArray);
  599. slapi_valueset_free(all_vals);
  600. if ( rc != 0 ) {
  601. ldbm_nasty(errmsg, 1040, rc);
  602. return( rc );
  603. }
  604. }
  605. return( 0 );
  606. }
  607. /*
  608. * Convert a 'struct berval' into a displayable ASCII string
  609. */
  610. #define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"')
  611. const char*
  612. encode (const struct berval* data, char buf[BUFSIZ])
  613. {
  614. char* s;
  615. char* last;
  616. if (data == NULL || data->bv_len == 0) return "";
  617. last = data->bv_val + data->bv_len - 1;
  618. for (s = data->bv_val; s < last; ++s) {
  619. if ( SPECIAL (*s)) {
  620. char* first = data->bv_val;
  621. char* bufNext = buf;
  622. size_t bufSpace = BUFSIZ - 4;
  623. while (1) {
  624. /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */
  625. if (bufSpace < (size_t)(s - first)) s = first + bufSpace - 1;
  626. if (s != first) {
  627. memcpy (bufNext, first, s - first);
  628. bufNext += (s - first);
  629. bufSpace -= (s - first);
  630. }
  631. do {
  632. *bufNext++ = '\\'; --bufSpace;
  633. if (bufSpace < 2) {
  634. memcpy (bufNext, "..", 2);
  635. bufNext += 2;
  636. goto bail;
  637. }
  638. if (*s == '\\' || *s == '"') {
  639. *bufNext++ = *s; --bufSpace;
  640. } else {
  641. sprintf (bufNext, "%02x", (unsigned)*(unsigned char*)s);
  642. bufNext += 2; bufSpace -= 2;
  643. }
  644. } while (++s <= last && SPECIAL (*s));
  645. if (s > last) break;
  646. first = s;
  647. while ( ! SPECIAL (*s) && s <= last) ++s;
  648. }
  649. bail:
  650. *bufNext = '\0';
  651. /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */
  652. return buf;
  653. }
  654. }
  655. /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */
  656. return data->bv_val;
  657. }
  658. static const char*
  659. encoded (DBT* d, char buf [BUFSIZ])
  660. {
  661. struct berval data;
  662. data.bv_len = d->dsize;
  663. data.bv_val = d->dptr;
  664. return encode (&data, buf);
  665. }
  666. IDList *
  667. index_read(
  668. backend *be,
  669. char *type,
  670. const char *indextype,
  671. const struct berval *val,
  672. back_txn *txn,
  673. int *err
  674. )
  675. {
  676. return index_read_ext(be, type, indextype, val, txn, err, NULL);
  677. }
  678. /*
  679. * Extended version of index_read.
  680. * The unindexed flag can be used to distinguish between a
  681. * return of allids due to the attr not being indexed or
  682. * the value really being allids.
  683. */
  684. IDList *
  685. index_read_ext(
  686. backend *be,
  687. char *type,
  688. const char *indextype,
  689. const struct berval *val,
  690. back_txn *txn,
  691. int *err,
  692. int *unindexed
  693. )
  694. {
  695. DB *db = NULL;
  696. DB_TXN *db_txn = NULL;
  697. DBT key = {0};
  698. IDList *idl;
  699. char *prefix;
  700. char *tmpbuf = NULL;
  701. char buf[BUFSIZ];
  702. char typebuf[ SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH ];
  703. struct attrinfo *ai = NULL;
  704. char *basetmp, *basetype;
  705. int retry_count = 0;
  706. struct berval *encrypted_val = NULL;
  707. *err = 0;
  708. if (unindexed != NULL) *unindexed = 0;
  709. prefix = index2prefix( indextype );
  710. LDAPDebug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" %s \"%s\" )\n",
  711. type, prefix, encode (val, buf));
  712. basetype = typebuf;
  713. if ( (basetmp = slapi_attr_basetype( type, typebuf, sizeof(typebuf) ))
  714. != NULL ) {
  715. basetype = basetmp;
  716. }
  717. ainfo_get( be, basetype, &ai );
  718. if (ai == NULL) {
  719. free_prefix( prefix );
  720. slapi_ch_free_string( &basetmp );
  721. return NULL;
  722. }
  723. LDAPDebug( LDAP_DEBUG_ARGS, " indextype: \"%s\" indexmask: 0x%x\n",
  724. indextype, ai->ai_indexmask, 0 );
  725. if ( !is_indexed( indextype, ai->ai_indexmask, ai->ai_index_rules ) ) {
  726. idl = idl_allids( be );
  727. if (unindexed != NULL) *unindexed = 1;
  728. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates "
  729. "(allids - not indexed)\n", (u_long)IDL_NIDS(idl), 0, 0 );
  730. free_prefix( prefix );
  731. slapi_ch_free_string( &basetmp );
  732. return( idl );
  733. }
  734. if ( (*err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  735. LDAPDebug( LDAP_DEBUG_TRACE,
  736. "<= index_read NULL (index file open for attr %s)\n",
  737. basetype, 0, 0 );
  738. free_prefix (prefix);
  739. slapi_ch_free_string( &basetmp );
  740. return( NULL );
  741. }
  742. slapi_ch_free_string( &basetmp );
  743. if ( val != NULL ) {
  744. size_t plen, vlen;
  745. char *realbuf;
  746. int ret = 0;
  747. /* If necessary, encrypt this index key */
  748. ret = attrcrypt_encrypt_index_key(be, ai, val, &encrypted_val);
  749. if (ret) {
  750. LDAPDebug( LDAP_DEBUG_ANY,
  751. "index_read failed to encrypt index key for %s\n",
  752. basetype, 0, 0 );
  753. }
  754. if (encrypted_val) {
  755. val = encrypted_val;
  756. }
  757. plen = strlen( prefix );
  758. vlen = val->bv_len;
  759. realbuf = (plen + vlen < sizeof(buf)) ?
  760. buf : (tmpbuf = slapi_ch_malloc( plen + vlen + 1 ));
  761. memcpy( realbuf, prefix, plen );
  762. memcpy( realbuf+plen, val->bv_val, vlen );
  763. realbuf[plen+vlen] = '\0';
  764. key.data = realbuf;
  765. key.size = key.ulen = plen + vlen + 1;
  766. key.flags = DB_DBT_USERMEM;
  767. } else {
  768. key.data = prefix;
  769. key.size = key.ulen = strlen( prefix ) + 1; /* include 0 terminator */
  770. key.flags = DB_DBT_USERMEM;
  771. }
  772. if (NULL != txn) {
  773. db_txn = txn->back_txn_txn;
  774. }
  775. for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
  776. *err = NEW_IDL_DEFAULT;
  777. idl = idl_fetch( be, db, &key, db_txn, ai, err );
  778. if(*err == DB_LOCK_DEADLOCK) {
  779. ldbm_nasty("index read retrying transaction", 1045, *err);
  780. continue;
  781. } else {
  782. break;
  783. }
  784. }
  785. if(retry_count == IDL_FETCH_RETRY_COUNT) {
  786. ldbm_nasty("index_read retry count exceeded",1046,*err);
  787. } else if ( *err != 0 && *err != DB_NOTFOUND ) {
  788. ldbm_nasty(errmsg, 1050, *err);
  789. }
  790. slapi_ch_free_string(&tmpbuf);
  791. dblayer_release_index_file( be, ai, db );
  792. free_prefix (prefix);
  793. if (encrypted_val) {
  794. ber_bvfree(encrypted_val);
  795. }
  796. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates\n",
  797. (u_long)IDL_NIDS(idl), 0, 0 );
  798. return( idl );
  799. }
  800. static int
  801. DBTcmp (DBT* L, DBT* R)
  802. {
  803. struct berval Lv;
  804. struct berval Rv;
  805. Lv.bv_val = L->dptr; Lv.bv_len = L->dsize;
  806. Rv.bv_val = R->dptr; Rv.bv_len = R->dsize;
  807. return slapi_berval_cmp (&Lv, &Rv);
  808. }
  809. #define DBT_EQ(L,R) ((L)->dsize == (R)->dsize &&\
  810. ! memcmp ((L)->dptr, (R)->dptr, (L)->dsize))
  811. #define DBT_FREE_PAYLOAD(d) if ((d).data) {free((d).data);(d).data=NULL;}
  812. /* Steps to the next key without keeping a cursor open */
  813. /* Returns the new key value in the DBT */
  814. static int index_range_next_key(DB *db,DBT *key,DB_TXN *db_txn)
  815. {
  816. DBC *cursor = NULL;
  817. DBT data = {0};
  818. int ret = 0;
  819. void *saved_key = key->data;
  820. /* Make cursor */
  821. retry:
  822. ret = db->cursor(db,db_txn,&cursor, 0);
  823. if (0 != ret) {
  824. return ret;
  825. }
  826. /* Seek to the last key */
  827. data.flags = DB_DBT_MALLOC;
  828. ret = cursor->c_get(cursor,key,&data,DB_SET); /* data allocated here, we don't need it */
  829. DBT_FREE_PAYLOAD(data);
  830. if (DB_NOTFOUND == ret) {
  831. void *old_key_buffer = key->data;
  832. /* If this happens, it means that we tried to seek to a key which has just been deleted */
  833. /* So, we seek to the nearest one instead */
  834. ret = cursor->c_get(cursor,key,&data,DB_SET_RANGE);
  835. /* a new key and data are allocated here, need to free them both */
  836. if (old_key_buffer != key->data) {
  837. DBT_FREE_PAYLOAD(*key);
  838. }
  839. DBT_FREE_PAYLOAD(data);
  840. }
  841. if (0 != ret) {
  842. if (DB_LOCK_DEADLOCK == ret)
  843. {
  844. /* Deadlock detected, retry the operation */
  845. cursor->c_close(cursor);
  846. cursor = NULL;
  847. key->data = saved_key;
  848. goto retry;
  849. } else
  850. {
  851. goto error;
  852. }
  853. }
  854. /* Seek to the next one
  855. * [612498] NODUP is needed for new idl to get the next non-duplicated key
  856. * No effect on old idl since there's no dup there (i.e., DB_NEXT == DB_NEXT_NODUP)
  857. */
  858. ret = cursor->c_get(cursor,key,&data,DB_NEXT_NODUP); /* new key and data are allocated, we only need the key */
  859. DBT_FREE_PAYLOAD(data);
  860. if (DB_LOCK_DEADLOCK == ret)
  861. {
  862. /* Deadlock detected, retry the operation */
  863. cursor->c_close(cursor);
  864. cursor = NULL;
  865. key->data = saved_key;
  866. goto retry;
  867. }
  868. error:
  869. /* Close the cursor */
  870. cursor->c_close(cursor);
  871. if (saved_key) { /* Need to free the original key passed in */
  872. if (saved_key == key->data) {
  873. /* Means that we never allocated a new key */
  874. ;
  875. } else {
  876. free(saved_key);
  877. }
  878. }
  879. return ret;
  880. }
  881. IDList *
  882. index_range_read(
  883. Slapi_PBlock *pb,
  884. backend *be,
  885. char *type,
  886. const char *indextype,
  887. int operator,
  888. struct berval *val,
  889. struct berval *nextval,
  890. int range,
  891. back_txn *txn,
  892. int *err
  893. )
  894. {
  895. struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
  896. DB *db;
  897. DB_TXN *db_txn = NULL;
  898. DBC *dbc = NULL;
  899. DBT lowerkey = {0};
  900. DBT upperkey = {0};
  901. DBT cur_key = {0};
  902. DBT data = {0} ;
  903. IDList *idl= NULL;
  904. char *prefix;
  905. char *realbuf, *nextrealbuf;
  906. size_t reallen, nextreallen;
  907. size_t plen;
  908. ID i;
  909. struct attrinfo *ai = NULL;
  910. int lookthrough_limit = -1; /* default no limit */
  911. int retry_count = 0;
  912. int is_and = 0;
  913. int sizelimit = 0;
  914. *err = 0;
  915. plen = strlen( prefix = index2prefix( indextype ));
  916. slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and);
  917. if (!is_and)
  918. {
  919. slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit);
  920. }
  921. /*
  922. * Determine the lookthrough_limit from the PBlock.
  923. * No limit if there is no PBlock supplied or if there is no
  924. * search result set and the requestor is root.
  925. */
  926. if (pb != NULL) {
  927. back_search_result_set *sr = NULL;
  928. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
  929. if (sr != NULL) {
  930. /* the normal case */
  931. lookthrough_limit = sr->sr_lookthroughlimit;
  932. } else {
  933. int isroot = 0;
  934. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  935. if (!isroot) {
  936. lookthrough_limit = li->li_lookthroughlimit;
  937. }
  938. }
  939. }
  940. LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read lookthrough_limit=%d\n",
  941. lookthrough_limit, 0, 0);
  942. switch( operator ) {
  943. case SLAPI_OP_LESS:
  944. case SLAPI_OP_LESS_OR_EQUAL:
  945. case SLAPI_OP_GREATER_OR_EQUAL:
  946. case SLAPI_OP_GREATER:
  947. break;
  948. default:
  949. LDAPDebug( LDAP_DEBUG_ANY,
  950. "<= index_range_read(%s,%s) NULL (operator %i)\n",
  951. type, prefix, operator );
  952. return( NULL );
  953. }
  954. ainfo_get( be, type, &ai );
  955. if (ai == NULL) return NULL;
  956. LDAPDebug( LDAP_DEBUG_ARGS, " indextype: \"%s\" indexmask: 0x%x\n",
  957. indextype, ai->ai_indexmask, 0 );
  958. if ( !is_indexed( indextype, ai->ai_indexmask, ai->ai_index_rules )) {
  959. idl = idl_allids( be );
  960. LDAPDebug( LDAP_DEBUG_TRACE,
  961. "<= index_range_read(%s,%s) %lu candidates (allids)\n",
  962. type, prefix, (u_long)IDL_NIDS(idl) );
  963. return( idl );
  964. }
  965. if ( (*err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  966. LDAPDebug( LDAP_DEBUG_ANY,
  967. "<= index_range_read(%s,%s) NULL (could not open index file)\n",
  968. type, prefix, 0 );
  969. return( NULL ); /* why not allids? */
  970. }
  971. if (NULL != txn) {
  972. db_txn = txn->back_txn_txn;
  973. }
  974. /* get a cursor so we can walk over the table */
  975. *err = db->cursor(db,db_txn,&dbc,0);
  976. if (0 != *err ) {
  977. ldbm_nasty(errmsg, 1060, *err);
  978. LDAPDebug( LDAP_DEBUG_ANY,
  979. "<= index_range_read(%s,%s) NULL: db->cursor() == %i\n",
  980. type, prefix, *err );
  981. dblayer_release_index_file( be, ai, db );
  982. return( NULL ); /* why not allids? */
  983. }
  984. /* set up the starting and ending keys for a range search */
  985. if ( val != NULL ) { /* compute a key from val */
  986. const size_t vlen = val->bv_len;
  987. reallen = plen + vlen + 1;
  988. realbuf = slapi_ch_malloc( reallen );
  989. memcpy( realbuf, prefix, plen );
  990. memcpy( realbuf+plen, val->bv_val, vlen );
  991. realbuf[plen+vlen] = '\0';
  992. } else {
  993. reallen = plen + 1; /* include 0 terminator */
  994. realbuf = slapi_ch_strdup(prefix);
  995. }
  996. if (range != 1) {
  997. char *tmpbuf = NULL;
  998. /* this is a search with only one boundary value */
  999. switch( operator ) {
  1000. case SLAPI_OP_LESS:
  1001. case SLAPI_OP_LESS_OR_EQUAL:
  1002. lowerkey.dptr = slapi_ch_strdup(prefix);
  1003. lowerkey.dsize = plen;
  1004. upperkey.dptr = realbuf;
  1005. upperkey.dsize = reallen;
  1006. break;
  1007. case SLAPI_OP_GREATER_OR_EQUAL:
  1008. case SLAPI_OP_GREATER:
  1009. lowerkey.dptr = realbuf;
  1010. lowerkey.dsize = reallen;
  1011. /* upperkey = a value slightly greater than prefix */
  1012. tmpbuf = slapi_ch_malloc (plen + 1);
  1013. memcpy (tmpbuf, prefix, plen + 1);
  1014. ++(tmpbuf[plen-1]);
  1015. upperkey.dptr = tmpbuf;
  1016. upperkey.dsize = plen;
  1017. tmpbuf = NULL;
  1018. /* ... but not greater than the last key in the index */
  1019. cur_key.flags = DB_DBT_MALLOC;
  1020. data.flags = DB_DBT_MALLOC;
  1021. *err = dbc->c_get(dbc,&cur_key,&data,DB_LAST); /* key and data allocated here, need to free them */
  1022. DBT_FREE_PAYLOAD(data);
  1023. /* Note that cur_key needs to get freed somewhere below */
  1024. if (0 != *err) {
  1025. if (DB_NOTFOUND == *err) {
  1026. /* There are no keys in the index so we should return no candidates. */
  1027. *err = 0;
  1028. idl = NULL;
  1029. slapi_ch_free( (void**)&realbuf);
  1030. dbc->c_close(dbc);
  1031. goto error;
  1032. } else {
  1033. ldbm_nasty(errmsg, 1070, *err);
  1034. LDAPDebug( LDAP_DEBUG_ANY,
  1035. "index_range_read(%s,%s) seek to end of index file err %i\n",
  1036. type, prefix, *err );
  1037. }
  1038. } else if (DBTcmp (&upperkey, &cur_key) > 0) {
  1039. tmpbuf = slapi_ch_realloc (tmpbuf, cur_key.dsize);
  1040. memcpy (tmpbuf, cur_key.dptr, cur_key.dsize);
  1041. DBT_FREE_PAYLOAD(upperkey);
  1042. upperkey.dptr = tmpbuf;
  1043. upperkey.dsize = cur_key.dsize;
  1044. }
  1045. break;
  1046. }
  1047. } else {
  1048. /* this is a search with two boundary values (starting and ending) */
  1049. if ( nextval != NULL ) { /* compute a key from nextval */
  1050. const size_t vlen = nextval->bv_len;
  1051. nextreallen = plen + vlen + 1;
  1052. nextrealbuf = slapi_ch_malloc( plen + vlen + 1 );
  1053. memcpy( nextrealbuf, prefix, plen );
  1054. memcpy( nextrealbuf+plen, nextval->bv_val, vlen );
  1055. nextrealbuf[plen+vlen] = '\0';
  1056. } else {
  1057. nextreallen = plen + 1; /* include 0 terminator */
  1058. nextrealbuf = slapi_ch_strdup(prefix);
  1059. }
  1060. /* set up the starting and ending keys for search */
  1061. switch( operator ) {
  1062. case SLAPI_OP_LESS:
  1063. case SLAPI_OP_LESS_OR_EQUAL:
  1064. lowerkey.dptr = nextrealbuf;
  1065. lowerkey.dsize = nextreallen;
  1066. upperkey.dptr = realbuf;
  1067. upperkey.dsize = reallen;
  1068. break;
  1069. case SLAPI_OP_GREATER_OR_EQUAL:
  1070. case SLAPI_OP_GREATER:
  1071. lowerkey.dptr = realbuf;
  1072. lowerkey.dsize = reallen;
  1073. upperkey.dptr = nextrealbuf;
  1074. upperkey.dsize = nextreallen;
  1075. break;
  1076. }
  1077. }
  1078. /* if (LDAP_DEBUG_FILTER) {
  1079. char encbuf [BUFSIZ];
  1080. LDAPDebug( LDAP_DEBUG_FILTER, " lowerkey=%s(%li bytes)\n",
  1081. encoded (&lowerkey, encbuf), (long)lowerkey.dsize, 0 );
  1082. LDAPDebug( LDAP_DEBUG_FILTER, " upperkey=%s(%li bytes)\n",
  1083. encoded (&upperkey, encbuf), (long)upperkey.dsize, 0 );
  1084. } */
  1085. data.flags = DB_DBT_MALLOC;
  1086. lowerkey.flags = DB_DBT_MALLOC;
  1087. {
  1088. void *old_lower_key_data = lowerkey.data;
  1089. *err = dbc->c_get(dbc,&lowerkey,&data,DB_SET_RANGE); /* lowerkey, if allocated and needs freed */
  1090. DBT_FREE_PAYLOAD(data);
  1091. if (old_lower_key_data != lowerkey.data) {
  1092. free(old_lower_key_data);
  1093. }
  1094. }
  1095. /* If the seek above fails due to DB_NOTFOUND, this means that there are no keys
  1096. which are >= the target key. This means that we should return no candidates */
  1097. if (0 != *err) {
  1098. /* Free the key we just read above */
  1099. DBT_FREE_PAYLOAD(lowerkey);
  1100. if (DB_NOTFOUND == *err) {
  1101. *err = 0;
  1102. idl = NULL;
  1103. } else {
  1104. idl = idl_allids( be );
  1105. ldbm_nasty(errmsg, 1080, *err);
  1106. LDAPDebug( LDAP_DEBUG_ANY,
  1107. "<= index_range_read(%s,%s) allids (seek to lower key in index file err %i)\n",
  1108. type, prefix, *err );
  1109. }
  1110. dbc->c_close(dbc);
  1111. goto error;
  1112. }
  1113. /* We now close the cursor, since we're about to iterate over many keys */
  1114. *err = dbc->c_close(dbc);
  1115. /* step through the indexed db to retrive IDs within the search range */
  1116. DBT_FREE_PAYLOAD(cur_key);
  1117. cur_key.data = lowerkey.data;
  1118. cur_key.size = lowerkey.size;
  1119. lowerkey.data = NULL; /* Don't need this any more, since the memory will be freed from cur_key */
  1120. if (operator == SLAPI_OP_GREATER) {
  1121. *err = index_range_next_key(db,&cur_key,db_txn);
  1122. }
  1123. while (*err == 0 &&
  1124. (operator == SLAPI_OP_LESS) ?
  1125. DBTcmp(&cur_key, &upperkey) < 0 :
  1126. DBTcmp(&cur_key, &upperkey) <= 0) {
  1127. /* exit the loop when we either run off the end of the table,
  1128. * fail to read a key, or read a key that's out of range.
  1129. */
  1130. IDList *tmp, *tmp2;
  1131. /*
  1132. char encbuf [BUFSIZ];
  1133. LDAPDebug( LDAP_DEBUG_FILTER, " cur_key=%s(%li bytes)\n",
  1134. encoded (&cur_key, encbuf), (long)cur_key.dsize, 0 );
  1135. */
  1136. /* Check to see if we've already looked too hard */
  1137. if (idl != NULL && lookthrough_limit != -1 && idl->b_nids > (ID)lookthrough_limit) {
  1138. if (NULL != idl) {
  1139. idl_free(idl);
  1140. }
  1141. idl = idl_allids( be );
  1142. LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read lookthrough_limit exceeded\n",
  1143. 0, 0, 0);
  1144. break;
  1145. }
  1146. if (idl != NULL && sizelimit > 0 && idl->b_nids > (ID)sizelimit)
  1147. {
  1148. LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read sizelimit exceeded\n",
  1149. 0, 0, 0);
  1150. break;
  1151. }
  1152. /* Check to see if the operation has been abandoned (also happens
  1153. * when the connection is closed by the client).
  1154. */
  1155. if ( slapi_op_abandoned( pb )) {
  1156. if (NULL != idl) {
  1157. idl_free(idl);
  1158. idl = NULL;
  1159. }
  1160. LDAPDebug(LDAP_DEBUG_TRACE,
  1161. "index_range_read - operation abandoned\n", 0, 0, 0);
  1162. break; /* clean up happens outside the while() loop */
  1163. }
  1164. /* the cur_key DBT already has the first entry in it when we enter the loop */
  1165. /* so we process the entry then step to the next one */
  1166. cur_key.flags = 0;
  1167. for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
  1168. *err = NEW_IDL_DEFAULT;
  1169. tmp = idl_fetch( be, db, &cur_key, NULL, ai, err );
  1170. if(*err == DB_LOCK_DEADLOCK) {
  1171. ldbm_nasty("index_range_read retrying transaction", 1090, *err);
  1172. continue;
  1173. } else {
  1174. break;
  1175. }
  1176. }
  1177. if(retry_count == IDL_FETCH_RETRY_COUNT) {
  1178. ldbm_nasty("index_range_read retry count exceeded",1095,*err);
  1179. }
  1180. tmp2 = idl_union( be, idl, tmp );
  1181. idl_free( idl );
  1182. idl_free( tmp );
  1183. idl = tmp2;
  1184. if (ALLIDS(idl)) {
  1185. LDAPDebug(LDAP_DEBUG_TRACE, "index_range_read hit an allids value\n",
  1186. 0, 0, 0);
  1187. break;
  1188. }
  1189. if (DBT_EQ (&cur_key, &upperkey)) { /* this is the last key */
  1190. break;
  1191. /* Another c_get would return the same key, with no error. */
  1192. }
  1193. data.flags = DB_DBT_MALLOC;
  1194. cur_key.flags = DB_DBT_MALLOC;
  1195. *err = index_range_next_key(db,&cur_key,db_txn);
  1196. /* *err = dbc->c_get(dbc,&cur_key,&data,DB_NEXT); */
  1197. if (*err == DB_NOTFOUND) {
  1198. *err = 0;
  1199. break;
  1200. }
  1201. }
  1202. if (*err) LDAPDebug( LDAP_DEBUG_FILTER, " dbc->c_get(...DB_NEXT) == %i\n", *err, 0, 0);
  1203. #ifdef LDAP_DEBUG
  1204. /* this is for debugging only */
  1205. if (idl != NULL)
  1206. {
  1207. if (ALLIDS(idl)) {
  1208. LDAPDebug( LDAP_DEBUG_FILTER,
  1209. " idl=ALLIDS\n", 0, 0, 0 );
  1210. } else {
  1211. LDAPDebug( LDAP_DEBUG_FILTER,
  1212. " idl->b_nids=%d\n", idl->b_nids, 0, 0 );
  1213. LDAPDebug( LDAP_DEBUG_FILTER,
  1214. " idl->b_nmax=%d\n", idl->b_nmax, 0, 0 );
  1215. for ( i= 0; i< idl->b_nids; i++)
  1216. {
  1217. LDAPDebug( LDAP_DEBUG_FILTER,
  1218. " idl->b_ids[%d]=%d\n", i, idl->b_ids[i], 0);
  1219. }
  1220. }
  1221. }
  1222. #endif
  1223. error:
  1224. DBT_FREE_PAYLOAD(cur_key);
  1225. DBT_FREE_PAYLOAD(upperkey);
  1226. dblayer_release_index_file( be, ai, db );
  1227. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_range_read(%s,%s) %lu candidates\n",
  1228. type, prefix, (u_long)IDL_NIDS(idl) );
  1229. return( idl );
  1230. }
  1231. /* DBDB: this function is never actually called */
  1232. #if 0
  1233. static int
  1234. addordel_values(
  1235. backend *be,
  1236. DB *db,
  1237. char *type,
  1238. const char *indextype,
  1239. struct berval **vals,
  1240. ID id,
  1241. int flags, /* BE_INDEX_ADD, etc */
  1242. back_txn *txn,
  1243. struct attrinfo *a,
  1244. int *idl_disposition,
  1245. void *buffer_handle
  1246. )
  1247. {
  1248. int rc = 0;
  1249. int i = 0;
  1250. DBT key = {0};
  1251. DB_TXN *db_txn = NULL;
  1252. size_t plen, vlen, len;
  1253. char *tmpbuf = NULL;
  1254. size_t tmpbuflen = 0;
  1255. char *realbuf;
  1256. char *prefix;
  1257. LDAPDebug( LDAP_DEBUG_TRACE, "=> %s_values\n",
  1258. (flags & BE_INDEX_ADD) ? "add" : "del", 0, 0);
  1259. prefix = index2prefix( indextype );
  1260. if ( vals == NULL ) {
  1261. key.dptr = prefix;
  1262. key.dsize = strlen( prefix ) + 1; /* include null terminator */
  1263. key.flags = DB_DBT_MALLOC;
  1264. if (NULL != txn) {
  1265. db_txn = txn->back_txn_txn;
  1266. }
  1267. if (flags & BE_INDEX_ADD) {
  1268. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1269. } else {
  1270. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1271. /* check for no such key/id - ok in some cases */
  1272. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1273. rc = 0;
  1274. }
  1275. }
  1276. if ( rc != 0)
  1277. {
  1278. ldbm_nasty(errmsg, 1090, rc);
  1279. }
  1280. free_prefix (prefix);
  1281. if (NULL != key.dptr && prefix != key.dptr)
  1282. slapi_ch_free( (void**)&key.dptr );
  1283. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1284. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1285. return( rc );
  1286. }
  1287. plen = strlen( prefix );
  1288. for ( i = 0; vals[i] != NULL; i++ ) {
  1289. vlen = vals[i]->bv_len;
  1290. len = plen + vlen;
  1291. if ( len < tmpbuflen ) {
  1292. realbuf = tmpbuf;
  1293. } else {
  1294. tmpbuf = slapi_ch_realloc( tmpbuf, len + 1 );
  1295. tmpbuflen = len + 1;
  1296. realbuf = tmpbuf;
  1297. }
  1298. memcpy( realbuf, prefix, plen );
  1299. memcpy( realbuf+plen, vals[i]->bv_val, vlen );
  1300. realbuf[len] = '\0';
  1301. key.dptr = realbuf;
  1302. key.size = plen + vlen + 1;
  1303. /* should be okay to use USERMEM here because we know what
  1304. * the key is and it should never return a different value
  1305. * than the one we pass in.
  1306. */
  1307. key.flags = DB_DBT_USERMEM;
  1308. key.ulen = tmpbuflen;
  1309. #ifdef LDAP_DEBUG
  1310. /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) XXX */
  1311. {
  1312. char encbuf[BUFSIZ];
  1313. LDAPDebug (LDAP_DEBUG_TRACE, " %s_value(\"%s\")\n",
  1314. (flags & BE_INDEX_ADD) ? "add" : "del",
  1315. encoded (&key, encbuf), 0);
  1316. }
  1317. #endif
  1318. if (NULL != txn) {
  1319. db_txn = txn->back_txn_txn;
  1320. }
  1321. if ( flags & BE_INDEX_ADD ) {
  1322. if (buffer_handle) {
  1323. rc = index_buffer_insert(buffer_handle,&key,id,be,db_txn,a);
  1324. if (rc == -2) {
  1325. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1326. }
  1327. } else {
  1328. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1329. }
  1330. } else {
  1331. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1332. /* check for no such key/id - ok in some cases */
  1333. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1334. rc = 0;
  1335. }
  1336. }
  1337. if ( rc != 0 ) {
  1338. ldbm_nasty(errmsg, 1100, rc);
  1339. break;
  1340. }
  1341. if ( NULL != key.dptr && realbuf != key.dptr) { /* realloc'ed */
  1342. tmpbuf = key.dptr;
  1343. tmpbuflen = key.size;
  1344. }
  1345. }
  1346. free_prefix (prefix);
  1347. if ( tmpbuf != NULL ) {
  1348. slapi_ch_free( (void**)&tmpbuf );
  1349. }
  1350. if ( rc != 0 )
  1351. {
  1352. ldbm_nasty(errmsg, 1110, rc);
  1353. }
  1354. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1355. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1356. return( rc );
  1357. }
  1358. #endif
  1359. static int
  1360. addordel_values_sv(
  1361. backend *be,
  1362. DB *db,
  1363. char *type,
  1364. const char *indextype,
  1365. Slapi_Value **vals,
  1366. ID id,
  1367. int flags, /* BE_INDEX_ADD, etc */
  1368. back_txn *txn,
  1369. struct attrinfo *a,
  1370. int *idl_disposition,
  1371. void *buffer_handle
  1372. )
  1373. {
  1374. int rc = 0;
  1375. int i = 0;
  1376. DBT key = {0};
  1377. DB_TXN *db_txn = NULL;
  1378. size_t plen, vlen, len;
  1379. char *tmpbuf = NULL;
  1380. size_t tmpbuflen = 0;
  1381. char *realbuf;
  1382. char *prefix;
  1383. const struct berval *bvp;
  1384. struct berval *encrypted_bvp = NULL;
  1385. LDAPDebug( LDAP_DEBUG_TRACE, "=> %s_values\n",
  1386. (flags & BE_INDEX_ADD) ? "add" : "del", 0, 0);
  1387. prefix = index2prefix( indextype );
  1388. if ( vals == NULL ) {
  1389. key.dptr = prefix;
  1390. key.dsize = strlen( prefix ) + 1; /* include null terminator */
  1391. key.flags = DB_DBT_MALLOC;
  1392. if (NULL != txn) {
  1393. db_txn = txn->back_txn_txn;
  1394. }
  1395. if (flags & BE_INDEX_ADD) {
  1396. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1397. } else {
  1398. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1399. /* check for no such key/id - ok in some cases */
  1400. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1401. rc = 0;
  1402. }
  1403. }
  1404. if ( rc != 0 )
  1405. {
  1406. ldbm_nasty(errmsg, 1120, rc);
  1407. }
  1408. free_prefix (prefix);
  1409. if (NULL != key.dptr && prefix != key.dptr)
  1410. slapi_ch_free( (void**)&key.dptr );
  1411. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1412. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1413. return( rc );
  1414. }
  1415. plen = strlen( prefix );
  1416. for ( i = 0; vals[i] != NULL; i++ ) {
  1417. bvp = slapi_value_get_berval(vals[i]);
  1418. /* Encrypt the index key if necessary */
  1419. {
  1420. if (a->ai_attrcrypt && (0 == (flags & BE_INDEX_DONT_ENCRYPT)))
  1421. {
  1422. rc = attrcrypt_encrypt_index_key(be,a,bvp,&encrypted_bvp);
  1423. if (rc)
  1424. {
  1425. LDAPDebug (LDAP_DEBUG_ANY, "Failed to encrypt index key for %s\n", a->ai_type ,0,0);
  1426. } else {
  1427. bvp = encrypted_bvp;
  1428. }
  1429. }
  1430. }
  1431. vlen = bvp->bv_len;
  1432. len = plen + vlen;
  1433. if ( len < tmpbuflen ) {
  1434. realbuf = tmpbuf;
  1435. } else {
  1436. tmpbuf = slapi_ch_realloc( tmpbuf, len + 1 );
  1437. tmpbuflen = len + 1;
  1438. realbuf = tmpbuf;
  1439. }
  1440. memcpy( realbuf, prefix, plen );
  1441. memcpy( realbuf+plen, bvp->bv_val, vlen );
  1442. realbuf[len] = '\0';
  1443. key.dptr = realbuf;
  1444. key.size = plen + vlen + 1;
  1445. /* Free the encrypted berval if necessary */
  1446. if (encrypted_bvp)
  1447. {
  1448. ber_bvfree(encrypted_bvp);
  1449. encrypted_bvp = NULL;
  1450. }
  1451. /* should be okay to use USERMEM here because we know what
  1452. * the key is and it should never return a different value
  1453. * than the one we pass in.
  1454. */
  1455. key.flags = DB_DBT_USERMEM;
  1456. key.ulen = tmpbuflen;
  1457. #ifdef LDAP_DEBUG
  1458. /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) XXX */
  1459. {
  1460. char encbuf[BUFSIZ];
  1461. LDAPDebug (LDAP_DEBUG_TRACE, " %s_value(\"%s\")\n",
  1462. (flags & BE_INDEX_ADD) ? "add" : "del",
  1463. encoded (&key, encbuf), 0);
  1464. }
  1465. #endif
  1466. if (NULL != txn) {
  1467. db_txn = txn->back_txn_txn;
  1468. }
  1469. if ( flags & BE_INDEX_ADD ) {
  1470. if (buffer_handle) {
  1471. rc = index_buffer_insert(buffer_handle,&key,id,be,db_txn,a);
  1472. if (rc == -2) {
  1473. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1474. }
  1475. } else {
  1476. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1477. }
  1478. } else {
  1479. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1480. /* check for no such key/id - ok in some cases */
  1481. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1482. rc = 0;
  1483. }
  1484. }
  1485. if ( rc != 0 ) {
  1486. ldbm_nasty(errmsg, 1130, rc);
  1487. break;
  1488. }
  1489. if ( NULL != key.dptr && realbuf != key.dptr) { /* realloc'ed */
  1490. tmpbuf = key.dptr;
  1491. tmpbuflen = key.size;
  1492. }
  1493. }
  1494. free_prefix (prefix);
  1495. if ( tmpbuf != NULL ) {
  1496. slapi_ch_free( (void**)&tmpbuf );
  1497. }
  1498. if ( rc != 0 )
  1499. {
  1500. ldbm_nasty(errmsg, 1140, rc);
  1501. }
  1502. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1503. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1504. return( rc );
  1505. }
  1506. int
  1507. index_addordel_string(backend *be, const char *type, const char *s, ID id, int flags, back_txn *txn)
  1508. {
  1509. Slapi_Value *svp[2];
  1510. Slapi_Value sv;
  1511. memset(&sv,0,sizeof(Slapi_Value));
  1512. sv.bv.bv_len= strlen(s);
  1513. sv.bv.bv_val= (void*)s;
  1514. svp[0] = &sv;
  1515. svp[1] = NULL;
  1516. return index_addordel_values_ext_sv(be,type,svp,NULL,id,flags,txn,NULL,NULL);
  1517. }
  1518. int
  1519. index_addordel_values_sv(
  1520. backend *be,
  1521. const char *type,
  1522. Slapi_Value **vals,
  1523. Slapi_Value **evals, /* existing values */
  1524. ID id,
  1525. int flags,
  1526. back_txn *txn
  1527. )
  1528. {
  1529. return index_addordel_values_ext_sv(be,type,vals,evals,
  1530. id,flags,txn,NULL,NULL);
  1531. }
  1532. int
  1533. index_addordel_values_ext_sv(
  1534. backend *be,
  1535. const char *type,
  1536. Slapi_Value **vals,
  1537. Slapi_Value **evals,
  1538. ID id,
  1539. int flags,
  1540. back_txn *txn,
  1541. int *idl_disposition,
  1542. void *buffer_handle
  1543. )
  1544. {
  1545. DB *db;
  1546. struct attrinfo *ai = NULL;
  1547. int err = -1;
  1548. Slapi_Value **ivals;
  1549. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  1550. char *basetmp, *basetype;
  1551. LDAPDebug( LDAP_DEBUG_TRACE,
  1552. "=> index_addordel_values_ext_sv( \"%s\", %lu )\n", type, (u_long)id, 0 );
  1553. basetype = buf;
  1554. if ( (basetmp = slapi_attr_basetype( type, buf, sizeof(buf) ))
  1555. != NULL ) {
  1556. basetype = basetmp;
  1557. }
  1558. ainfo_get( be, basetype, &ai );
  1559. if ( ai == NULL || ai->ai_indexmask == 0
  1560. || ai->ai_indexmask == INDEX_OFFLINE ) {
  1561. slapi_ch_free_string( &basetmp );
  1562. return( 0 );
  1563. }
  1564. LDAPDebug( LDAP_DEBUG_ARGS, " index_addordel_values_ext_sv indexmask 0x%x\n",
  1565. ai->ai_indexmask, 0, 0 );
  1566. if ( (err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  1567. LDAPDebug( LDAP_DEBUG_ANY,
  1568. "<= index_read NULL (could not open index attr %s)\n",
  1569. basetype, 0, 0 );
  1570. slapi_ch_free_string( &basetmp );
  1571. if ( err != 0 ) {
  1572. ldbm_nasty(errmsg, 1210, err);
  1573. }
  1574. goto bad;
  1575. }
  1576. /*
  1577. * presence index entry
  1578. */
  1579. if (( ai->ai_indexmask & INDEX_PRESENCE ) &&
  1580. (flags & (BE_INDEX_ADD|BE_INDEX_PRESENCE))) {
  1581. /* on delete, only remove the presence index if the
  1582. * BE_INDEX_PRESENCE flag is set.
  1583. */
  1584. err = addordel_values_sv( be, db, basetype, indextype_PRESENCE,
  1585. NULL, id, flags, txn, ai, idl_disposition, NULL );
  1586. if ( err != 0 ) {
  1587. ldbm_nasty(errmsg, 1220, err);
  1588. goto bad;
  1589. }
  1590. }
  1591. /*
  1592. * equality index entry
  1593. */
  1594. if (( ai->ai_indexmask & INDEX_EQUALITY ) &&
  1595. (flags & (BE_INDEX_ADD|BE_INDEX_EQUALITY))) {
  1596. /* on delete, only remove the equality index if the
  1597. * BE_INDEX_EQUALITY flag is set.
  1598. */
  1599. slapi_call_syntax_values2keys_sv( ai->ai_plugin, vals, &ivals,
  1600. LDAP_FILTER_EQUALITY );
  1601. err = addordel_values_sv( be, db, basetype, indextype_EQUALITY,
  1602. ivals != NULL ? ivals : vals, id, flags, txn, ai, idl_disposition, NULL );
  1603. if ( ivals != NULL ) {
  1604. valuearray_free( &ivals );
  1605. }
  1606. if ( err != 0 ) {
  1607. ldbm_nasty(errmsg, 1230, err);
  1608. goto bad;
  1609. }
  1610. }
  1611. /*
  1612. * approximate index entry
  1613. */
  1614. if ( ai->ai_indexmask & INDEX_APPROX ) {
  1615. slapi_call_syntax_values2keys_sv( ai->ai_plugin, vals, &ivals,
  1616. LDAP_FILTER_APPROX );
  1617. if ( ivals != NULL ) {
  1618. err = addordel_values_sv( be, db, basetype,
  1619. indextype_APPROX, ivals, id, flags, txn, ai, idl_disposition, NULL );
  1620. valuearray_free( &ivals );
  1621. if ( err != 0 ) {
  1622. ldbm_nasty(errmsg, 1240, err);
  1623. goto bad;
  1624. }
  1625. }
  1626. }
  1627. /*
  1628. * substrings index entry
  1629. */
  1630. if ( ai->ai_indexmask & INDEX_SUB ) {
  1631. Slapi_Value **esubvals = NULL;
  1632. Slapi_Value **substresult = NULL;
  1633. Slapi_Value **origvals = NULL;
  1634. slapi_call_syntax_values2keys_sv( ai->ai_plugin, vals, &ivals,
  1635. LDAP_FILTER_SUBSTRINGS );
  1636. origvals = ivals;
  1637. /* delete only: if the attribute has multiple values,
  1638. * figure out the substrings that should remain
  1639. * by slapi_call_syntax_values2keys,
  1640. * then get rid of them from the being deleted values
  1641. */
  1642. if ( evals != NULL ) {
  1643. slapi_call_syntax_values2keys_sv( ai->ai_plugin, evals, &esubvals,
  1644. LDAP_FILTER_SUBSTRINGS );
  1645. substresult = valuearray_minus_valuearray( ai->ai_plugin, ivals, esubvals );
  1646. ivals = substresult;
  1647. valuearray_free( &esubvals );
  1648. }
  1649. if ( ivals != NULL ) {
  1650. err = addordel_values_sv( be, db, basetype, indextype_SUB,
  1651. ivals, id, flags, txn, ai, idl_disposition, buffer_handle );
  1652. if ( ivals != origvals )
  1653. valuearray_free( &origvals );
  1654. valuearray_free( &ivals );
  1655. if ( err != 0 ) {
  1656. ldbm_nasty(errmsg, 1250, err);
  1657. goto bad;
  1658. }
  1659. ivals = NULL;
  1660. }
  1661. }
  1662. /*
  1663. * matching rule index entries
  1664. */
  1665. if ( ai->ai_indexmask & INDEX_RULES )
  1666. {
  1667. Slapi_PBlock* pb = slapi_pblock_new();
  1668. char** oid = ai->ai_index_rules;
  1669. for (; *oid != NULL; ++oid)
  1670. {
  1671. if(create_matchrule_indexer(&pb,*oid,basetype)==0)
  1672. {
  1673. char* officialOID = NULL;
  1674. if (!slapi_pblock_get (pb, SLAPI_PLUGIN_MR_OID, &officialOID) && officialOID != NULL)
  1675. {
  1676. Slapi_Value** keys = NULL;
  1677. matchrule_values_to_keys_sv(pb,vals,&keys);
  1678. if(keys != NULL && keys[0] != NULL)
  1679. {
  1680. /* we've computed keys */
  1681. err = addordel_values_sv (be, db, basetype, officialOID, keys, id, flags, txn, ai, idl_disposition, NULL);
  1682. if ( err != 0 )
  1683. {
  1684. ldbm_nasty(errmsg, 1260, err);
  1685. goto bad;
  1686. }
  1687. }
  1688. /*
  1689. * It would improve speed to save the indexer, for future use.
  1690. * But, for simplicity, we destroy it now:
  1691. */
  1692. destroy_matchrule_indexer(pb);
  1693. }
  1694. }
  1695. }
  1696. slapi_pblock_destroy (pb);
  1697. }
  1698. dblayer_release_index_file( be, ai, db );
  1699. if ( basetmp != NULL ) {
  1700. slapi_ch_free( (void**)&basetmp );
  1701. }
  1702. LDAPDebug (LDAP_DEBUG_TRACE, "<= index_addordel_values_ext_sv\n", 0, 0, 0 );
  1703. return( 0 );
  1704. bad:
  1705. dblayer_release_index_file(be, ai, db);
  1706. return err;
  1707. }
  1708. int
  1709. index_delete_values(
  1710. struct ldbminfo *li,
  1711. char *type,
  1712. struct berval **vals,
  1713. ID id
  1714. )
  1715. {
  1716. return -1;
  1717. }
  1718. static int
  1719. is_indexed (const char* indextype, int indexmask, char** index_rules)
  1720. {
  1721. int indexed;
  1722. if (indextype == indextype_PRESENCE) indexed = INDEX_PRESENCE & indexmask;
  1723. else if (indextype == indextype_EQUALITY) indexed = INDEX_EQUALITY & indexmask;
  1724. else if (indextype == indextype_APPROX) indexed = INDEX_APPROX & indexmask;
  1725. else if (indextype == indextype_SUB) indexed = INDEX_SUB & indexmask;
  1726. else { /* matching rule */
  1727. indexed = 0;
  1728. if (INDEX_RULES & indexmask) {
  1729. char** rule;
  1730. for (rule = index_rules; *rule; ++rule) {
  1731. if ( ! strcmp( *rule, indextype )) {
  1732. indexed = INDEX_RULES;
  1733. break;
  1734. }
  1735. }
  1736. }
  1737. }
  1738. /* if index is currently being generated, pretend it doesn't exist */
  1739. if (indexmask & INDEX_OFFLINE)
  1740. indexed = 0;
  1741. return indexed;
  1742. }
  1743. static char*
  1744. index2prefix (const char* indextype)
  1745. {
  1746. char* prefix;
  1747. if ( indextype == indextype_PRESENCE ) prefix = prefix_PRESENCE;
  1748. else if ( indextype == indextype_EQUALITY ) prefix = prefix_EQUALITY;
  1749. else if ( indextype == indextype_APPROX ) prefix = prefix_APPROX;
  1750. else if ( indextype == indextype_SUB ) prefix = prefix_SUB;
  1751. else { /* indextype is a matching rule name */
  1752. const size_t len = strlen (indextype);
  1753. char* p = slapi_ch_malloc (len + 3);
  1754. p[0] = RULE_PREFIX;
  1755. memcpy( p+1, indextype, len );
  1756. p[len+1] = ':';
  1757. p[len+2] = '\0';
  1758. prefix = p;
  1759. }
  1760. return( prefix );
  1761. }
  1762. static void
  1763. free_prefix (char* prefix)
  1764. {
  1765. if (prefix == NULL ||
  1766. prefix == prefix_PRESENCE ||
  1767. prefix == prefix_EQUALITY ||
  1768. prefix == prefix_APPROX ||
  1769. prefix == prefix_SUB) {
  1770. /* do nothing */
  1771. } else {
  1772. slapi_ch_free( (void**)&prefix);
  1773. }
  1774. }
  1775. /* helper stuff for valuearray_minus_valuearray */
  1776. typedef struct {
  1777. value_compare_fn_type cmp_fn;
  1778. Slapi_Value *data;
  1779. } SVSORT;
  1780. static int
  1781. svsort_cmp(const void *x, const void *y)
  1782. {
  1783. return ((SVSORT*)x)->cmp_fn(slapi_value_get_berval(((SVSORT*)x)->data),
  1784. slapi_value_get_berval(((SVSORT*)y)->data));
  1785. }
  1786. static int
  1787. bvals_strcasecmp(const struct berval *a, const struct berval *b)
  1788. {
  1789. return strcasecmp(a->bv_val, b->bv_val);
  1790. }
  1791. /* a - b = c */
  1792. /* the returned array of Slapi_Value needs to be freed. */
  1793. static Slapi_Value **
  1794. valuearray_minus_valuearray(
  1795. void *plugin,
  1796. Slapi_Value **a,
  1797. Slapi_Value **b
  1798. )
  1799. {
  1800. int rc, i, j, k, acnt, bcnt;
  1801. SVSORT *atmp = NULL, *btmp = NULL;
  1802. Slapi_Value **c;
  1803. value_compare_fn_type cmp_fn;
  1804. /* get berval comparison function */
  1805. plugin_call_syntax_get_compare_fn(plugin, &cmp_fn);
  1806. if (cmp_fn == NULL) {
  1807. cmp_fn = (value_compare_fn_type)bvals_strcasecmp;
  1808. }
  1809. /* determine length of a */
  1810. for (acnt = 0; a[acnt] != NULL; acnt++);
  1811. /* determine length of b */
  1812. for (bcnt = 0; b[bcnt] != NULL; bcnt++);
  1813. /* allocate return array as big as a */
  1814. c = (Slapi_Value**)calloc(acnt+1, sizeof(Slapi_Value*));
  1815. if (acnt == 0) return c;
  1816. /* sort a */
  1817. atmp = (SVSORT*) slapi_ch_malloc(acnt*sizeof(SVSORT));
  1818. for (i = 0; i < acnt; i++) {
  1819. atmp[i].cmp_fn = cmp_fn;
  1820. atmp[i].data = a[i];
  1821. }
  1822. qsort((void*)atmp, acnt, (size_t)sizeof(SVSORT), svsort_cmp);
  1823. /* sort b */
  1824. if (bcnt > 0) {
  1825. btmp = (SVSORT*) slapi_ch_malloc(bcnt*sizeof(SVSORT));
  1826. for (i = 0; i < bcnt; i++) {
  1827. btmp[i].cmp_fn = cmp_fn;
  1828. btmp[i].data = b[i];
  1829. }
  1830. qsort((void*)btmp, bcnt, (size_t)sizeof(SVSORT), svsort_cmp);
  1831. }
  1832. /* lock step through a and b */
  1833. for (i = 0, j = 0, k = 0; i < acnt && j < bcnt; ) {
  1834. rc = svsort_cmp(&atmp[i], &btmp[j]);
  1835. if (rc == 0) {
  1836. i++;
  1837. } else if (rc < 0) {
  1838. c[k++] = slapi_value_new_value(atmp[i++].data);
  1839. } else {
  1840. j++;
  1841. }
  1842. }
  1843. /* copy what's left from a */
  1844. while (i < acnt) {
  1845. c[k++] = slapi_value_new_value(atmp[i++].data);
  1846. }
  1847. /* clean up */
  1848. slapi_ch_free((void**)&atmp);
  1849. if (btmp) slapi_ch_free((void**)&btmp);
  1850. return c;
  1851. }