index.c 78 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* index.c - routines for dealing with attribute indexes */
  13. #include "back-ldbm.h"
  14. static const char *errmsg = "database index operation failed";
  15. static int is_indexed (const char* indextype, int indexmask, char** index_rules);
  16. static int index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags );
  17. static Slapi_Value **
  18. valuearray_minus_valuearray(
  19. const Slapi_Attr *sattr,
  20. Slapi_Value **a,
  21. Slapi_Value **b
  22. );
  23. const char* indextype_PRESENCE = "pres";
  24. const char* indextype_EQUALITY = "eq";
  25. const char* indextype_APPROX = "approx";
  26. const char* indextype_SUB = "sub";
  27. static char prefix_PRESENCE[2] = {PRES_PREFIX, 0};
  28. static char prefix_EQUALITY[2] = {EQ_PREFIX, 0};
  29. static char prefix_APPROX [2] = {APPROX_PREFIX, 0};
  30. static char prefix_SUB [2] = {SUB_PREFIX, 0};
  31. /* Yes, prefix_PRESENCE and prefix_SUB are identical.
  32. * It works because SUB is always followed by a key value,
  33. * but PRESENCE never is. Too slick by half.
  34. */
  35. /* Structures for index key buffering magic used by import code */
  36. struct _index_buffer_bin {
  37. DBT key;
  38. IDList *value;
  39. };
  40. typedef struct _index_buffer_bin index_buffer_bin;
  41. struct _index_buffer_handle {
  42. int flags;
  43. size_t buffer_size;
  44. size_t idl_size;
  45. size_t max_key_length;
  46. index_buffer_bin *bins;
  47. unsigned char high_key_byte_range;
  48. unsigned char low_key_byte_range;
  49. unsigned char special_byte_a;
  50. unsigned char special_byte_b;
  51. size_t byte_range;
  52. /* Statistics */
  53. int inserts;
  54. int keys;
  55. };
  56. typedef struct _index_buffer_handle index_buffer_handle;
  57. #define INDEX_BUFFER_FLAG_SERIALIZE 1
  58. #define INDEX_BUFFER_FLAG_STATS 2
  59. /* Index buffering functions */
  60. static int
  61. index_buffer_init_internal(size_t idl_size,
  62. unsigned char high_key_byte_range, unsigned char low_key_byte_range,
  63. size_t max_key_length,unsigned char special_byte_a, unsigned char special_byte_b,
  64. int flags,void **h)
  65. {
  66. size_t bin_count = 0;
  67. /* Allocate the handle */
  68. index_buffer_bin *bins = NULL;
  69. size_t i = 0;
  70. size_t byte_range = 0;
  71. int rc = 0;
  72. index_buffer_handle *handle = (index_buffer_handle *) slapi_ch_calloc(1,sizeof(index_buffer_handle));
  73. if (NULL == handle) {
  74. rc = -1;
  75. goto error;
  76. }
  77. handle->idl_size = idl_size;
  78. handle->flags = flags;
  79. handle->high_key_byte_range = high_key_byte_range;
  80. handle->low_key_byte_range = low_key_byte_range;
  81. handle->special_byte_a = special_byte_a;
  82. handle->special_byte_b = special_byte_b;
  83. handle->max_key_length = max_key_length;
  84. byte_range = (high_key_byte_range - low_key_byte_range) + 3 + 10;
  85. handle->byte_range = byte_range;
  86. /* Allocate the bins */
  87. bin_count = 1;
  88. for (i = 0 ; i < max_key_length - 2; i++) {
  89. bin_count *= byte_range;
  90. }
  91. handle->buffer_size = bin_count;
  92. bins = (index_buffer_bin *)slapi_ch_calloc(bin_count, sizeof(index_buffer_bin));
  93. if (NULL == bins) {
  94. rc = -1;
  95. goto error;
  96. }
  97. handle->bins = bins;
  98. *h = (void*) handle;
  99. goto done;
  100. error:
  101. slapi_ch_free((void**)&handle);
  102. done:
  103. return rc;
  104. }
  105. int index_buffer_init(size_t size,int flags,void **h)
  106. {
  107. return index_buffer_init_internal(size,'z','a',5,'^','$',flags,h);
  108. }
  109. static int
  110. index_put_idl(index_buffer_bin *bin,backend *be, DB_TXN *txn,struct attrinfo *a)
  111. {
  112. int ret = 0;
  113. DB *db = NULL;
  114. int need_to_freed_new_idl = 0;
  115. IDList *old_idl = NULL;
  116. IDList *new_idl = NULL;
  117. if ( (ret = dblayer_get_index_file( be, a, &db, DBOPEN_CREATE )) != 0 ) {
  118. return ret;
  119. }
  120. if (bin->key.data && bin->value) {
  121. /* Need to read the IDL at the key, if present, and form the union with what we have */
  122. ret = NEW_IDL_NOOP; /* this flag is for new idl only;
  123. * but this func is called only from index_buffer,
  124. * which is enabled only for old idl.
  125. */
  126. old_idl = idl_fetch(be,db,&bin->key,txn,a,&ret);
  127. if ( (0 != ret) && (DB_NOTFOUND != ret)) {
  128. goto error;
  129. }
  130. if ( (old_idl != NULL) && !ALLIDS(old_idl)) {
  131. /* We need to merge in our block with what was there */
  132. new_idl = idl_union(be,old_idl,bin->value);
  133. need_to_freed_new_idl = 1;
  134. } else {
  135. /* Nothing there previously, we store just what we have */
  136. new_idl = bin->value;
  137. }
  138. /* Then write back the result, but only if the existing idl wasn't ALLIDS */
  139. if (!old_idl || (old_idl && !ALLIDS(old_idl))) {
  140. ret = idl_store_block(be,db,&bin->key,new_idl,txn,a);
  141. }
  142. if (0 != ret) {
  143. goto error;
  144. }
  145. slapi_ch_free( &(bin->key.data) );
  146. idl_free(&(bin->value));
  147. /* If we're already at allids, store an allids block to prevent needless accumulation of blocks */
  148. if (old_idl && ALLIDS(old_idl)) {
  149. bin->value = idl_allids(be);
  150. } else {
  151. bin->value = NULL;
  152. }
  153. }
  154. error:
  155. if (old_idl) {
  156. idl_free(&old_idl);
  157. }
  158. if (new_idl && need_to_freed_new_idl) {
  159. idl_free(&new_idl);
  160. }
  161. dblayer_release_index_file( be, a, db );
  162. return ret;
  163. }
  164. /* The caller MUST check for DB_RUNRECOVERY being returned */
  165. int
  166. index_buffer_flush(void *h,backend *be, DB_TXN *txn,struct attrinfo *a)
  167. {
  168. index_buffer_handle *handle = (index_buffer_handle *) h;
  169. index_buffer_bin *bin = NULL;
  170. int ret = 0;
  171. size_t i = 0;
  172. DB *db = NULL;
  173. PR_ASSERT(h);
  174. /* Note to the wary: here we do NOT create the index file up front */
  175. /* This is becuase there may be no buffers to flush, and the goal is to
  176. * never create the index file (merging gets confused by this, among other things */
  177. /* Walk along the bins, writing them to the database */
  178. for (i = 0; i < handle->buffer_size; i++) {
  179. bin = &(handle->bins[i]);
  180. if (bin->key.data && bin->value) {
  181. if (NULL == db) {
  182. if ( (ret = dblayer_get_index_file( be, a, &db, DBOPEN_CREATE )) != 0 ) {
  183. return ret;
  184. }
  185. }
  186. ret = index_put_idl(bin,be,txn,a);
  187. if (0 != ret) {
  188. goto error;
  189. }
  190. }
  191. }
  192. error:
  193. if (NULL != db) {
  194. dblayer_release_index_file( be, a, db );
  195. }
  196. return ret;
  197. }
  198. int
  199. index_buffer_terminate(void *h)
  200. {
  201. index_buffer_handle *handle = (index_buffer_handle *) h;
  202. index_buffer_bin *bin = NULL;
  203. size_t i = 0;
  204. PR_ASSERT(h);
  205. /* Free all the buffers */
  206. /* First walk down the bins, freeing the IDLs and the bins they're in */
  207. for (i = 0; i < handle->buffer_size; i++) {
  208. bin = &(handle->bins[i]);
  209. if (bin->value) {
  210. idl_free(&(bin->value));
  211. bin->value = NULL;
  212. }
  213. slapi_ch_free(&(bin->key.data));
  214. }
  215. slapi_ch_free((void **)&(handle->bins));
  216. /* Now free the handle */
  217. slapi_ch_free((void **)&handle);
  218. return 0;
  219. }
  220. /* This function returns -1 or -2 for local errors, and DB_ errors as well. */
  221. static int
  222. index_buffer_insert(void *h, DBT *key, ID id,backend *be, DB_TXN *txn,struct attrinfo *a)
  223. {
  224. index_buffer_handle *handle = (index_buffer_handle *) h;
  225. index_buffer_bin *bin = NULL;
  226. size_t index = 0;
  227. int idl_ret = 0;
  228. unsigned char x = 0;
  229. unsigned int i = 0;
  230. int ret = 0;
  231. PR_ASSERT(h);
  232. /* Check key length for validity */
  233. if (key->size > handle->max_key_length) {
  234. return -2;
  235. }
  236. /* discard the first character, as long as its the substring prefix */
  237. if ((unsigned char)((char*)key->data)[0] != SUB_PREFIX) {
  238. return -2;
  239. }
  240. /* Compute the bin index from the key */
  241. /* Walk along the key data, byte by byte */
  242. for (i = 1; i < (key->size - 1); i++) {
  243. /* foreach byte, normalize to the range we accept */
  244. x = (unsigned char) ((char*)key->data)[i];
  245. if ( (x == handle->special_byte_a) || (x == handle->special_byte_b) ) {
  246. if (x == handle->special_byte_a) {
  247. x = handle->high_key_byte_range + 1;
  248. }
  249. if (x == handle->special_byte_b) {
  250. x = handle->high_key_byte_range + 2;
  251. }
  252. } else {
  253. if ( x >= '0' && x <= '9' ) {
  254. x = (x - '0') + handle->high_key_byte_range + 3;
  255. } else {
  256. if (x > handle->high_key_byte_range) {
  257. return -2; /* Out of range */
  258. }
  259. if (x < handle->low_key_byte_range) {
  260. return -2; /* Out of range */
  261. }
  262. }
  263. }
  264. x = x - handle->low_key_byte_range;
  265. index *= handle->byte_range;
  266. index += x;
  267. }
  268. /* Check that the last byte in the key is zero */
  269. if (0 != (unsigned char)((char*)key->data)[i]) {
  270. return -2;
  271. }
  272. PR_ASSERT(index < handle->buffer_size);
  273. /* Get the bin */
  274. bin = &(handle->bins[index]);
  275. /* Is the key already there ? */
  276. retry:
  277. if (!(bin->key).data) {
  278. (bin->key).size = key->size;
  279. (bin->key).data = slapi_ch_malloc(key->size);
  280. if (NULL == bin->key.data) {
  281. return -1;
  282. }
  283. memcpy(bin->key.data,key->data,key->size);
  284. /* Make the IDL */
  285. bin->value = idl_alloc(handle->idl_size);
  286. if (!bin->value) {
  287. return -1;
  288. }
  289. }
  290. idl_ret = idl_append(bin->value, id);
  291. if (0 != idl_ret) {
  292. if (1 == idl_ret) {
  293. /* ID already present */
  294. } else {
  295. /* If we get to here, it means that we've overflowed our IDL */
  296. /* So, we need to write it out to the DB and zero out the pointers */
  297. ret = index_put_idl(bin,be,txn,a);
  298. /* Now we need to append the ID we have at hand */
  299. if (0 == ret) {
  300. goto retry;
  301. }
  302. }
  303. }
  304. return ret;
  305. }
  306. /*
  307. * Add or Delete an entry from the attribute indexes.
  308. * 'flags' is either BE_INDEX_ADD or BE_INDEX_DEL
  309. */
  310. int
  311. index_addordel_entry(
  312. backend *be,
  313. struct backentry *e,
  314. int flags,
  315. back_txn *txn
  316. )
  317. {
  318. char *type = NULL;
  319. Slapi_Value **svals;
  320. int rc, result;
  321. Slapi_Attr *attr;
  322. LDAPDebug( LDAP_DEBUG_TRACE, "=> index_%s_entry( \"%s\", %lu )\n",
  323. (flags & BE_INDEX_ADD) ? "add" : "del",
  324. backentry_get_ndn(e), (u_long)e->ep_id );
  325. /* if we are adding a tombstone entry (see ldbm_add.c) */
  326. if ((flags & BE_INDEX_TOMBSTONE) && (flags & BE_INDEX_ADD))
  327. {
  328. const CSN *tombstone_csn = NULL;
  329. char deletion_csn_str[CSN_STRSIZE];
  330. Slapi_DN parent;
  331. Slapi_DN *sdn = slapi_entry_get_sdn(e->ep_entry);
  332. slapi_sdn_init(&parent);
  333. slapi_sdn_get_parent(sdn, &parent);
  334. /*
  335. * Just index the "nstombstone" attribute value from the objectclass
  336. * attribute, and the nsuniqueid attribute value, and the
  337. * nscpEntryDN value of the deleted entry.
  338. */
  339. result = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE, e->ep_id, flags, txn);
  340. if ( result != 0 ) {
  341. ldbm_nasty(errmsg, 1010, result);
  342. return( result );
  343. }
  344. result = index_addordel_string(be, SLAPI_ATTR_UNIQUEID, slapi_entry_get_uniqueid(e->ep_entry), e->ep_id, flags, txn);
  345. if ( result != 0 ) {
  346. ldbm_nasty(errmsg, 1020, result);
  347. return( result );
  348. }
  349. result = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&parent), e->ep_id, flags, txn);
  350. if ( result != 0 ) {
  351. ldbm_nasty(errmsg, 1021, result);
  352. return( result );
  353. }
  354. if((tombstone_csn = entry_get_deletion_csn(e->ep_entry))){
  355. csn_as_string(tombstone_csn, PR_FALSE, deletion_csn_str);
  356. result = index_addordel_string(be, SLAPI_ATTR_TOMBSTONE_CSN, deletion_csn_str, e->ep_id, flags, txn);
  357. if ( result != 0 ) {
  358. ldbm_nasty(errmsg, 1021, result);
  359. return( result );
  360. }
  361. }
  362. slapi_sdn_done(&parent);
  363. if (entryrdn_get_switch()) { /* subtree-rename: on */
  364. Slapi_Attr* attr;
  365. /* Even if this is a tombstone, we have to add it to entryrdn
  366. * to maintain the full DN
  367. */
  368. result = entryrdn_index_entry(be, e, flags, txn);
  369. if ( result != 0 ) {
  370. ldbm_nasty(errmsg, 1023, result);
  371. return( result );
  372. }
  373. /* To maintain tombstonenumsubordinates,
  374. * parentid is needed for tombstone, as well. */
  375. slapi_entry_attr_find(e->ep_entry, LDBM_PARENTID_STR, &attr);
  376. if (attr) {
  377. svals = attr_get_present_values(attr);
  378. result = index_addordel_values_sv(be, LDBM_PARENTID_STR, svals, NULL,
  379. e->ep_id, flags, txn);
  380. if ( result != 0 ) {
  381. ldbm_nasty(errmsg, 1022, result);
  382. return( result );
  383. }
  384. }
  385. }
  386. }
  387. else
  388. { /* NOT a tombstone or delete a tombstone */
  389. /* add each attribute to the indexes */
  390. rc = 0, result = 0;
  391. int entryrdn_done = 0;
  392. for ( rc = slapi_entry_first_attr( e->ep_entry, &attr ); rc == 0;
  393. rc = slapi_entry_next_attr( e->ep_entry, attr, &attr ) ) {
  394. slapi_attr_get_type( attr, &type );
  395. svals = attr_get_present_values(attr);
  396. if ( !entryrdn_done && (0 == strcmp( type, LDBM_ENTRYDN_STR ))) {
  397. entryrdn_done = 1;
  398. if (entryrdn_get_switch()) { /* subtree-rename: on */
  399. /* skip "entrydn" */
  400. continue;
  401. } else {
  402. /* entrydn is case-normalized */
  403. slapi_values_set_flags(svals,
  404. SLAPI_ATTR_FLAG_NORMALIZED_CIS);
  405. }
  406. }
  407. result = index_addordel_values_sv( be, type, svals, NULL,
  408. e->ep_id, flags, txn );
  409. if ( result != 0 ) {
  410. ldbm_nasty(errmsg, 1030, result);
  411. return( result );
  412. }
  413. }
  414. if (!entryrdn_get_noancestorid()) {
  415. /* update ancestorid index . . . */
  416. /* . . . only if we are not deleting a tombstone entry -
  417. * tombstone entries are not in the ancestor id index -
  418. * see bug 603279
  419. */
  420. if (!((flags & BE_INDEX_TOMBSTONE) && (flags & BE_INDEX_DEL))) {
  421. result = ldbm_ancestorid_index_entry(be, e, flags, txn);
  422. if ( result != 0 ) {
  423. return( result );
  424. }
  425. }
  426. }
  427. if (entryrdn_get_switch()) { /* subtree-rename: on */
  428. result = entryrdn_index_entry(be, e, flags, txn);
  429. if ( result != 0 ) {
  430. ldbm_nasty(errmsg, 1031, result);
  431. return( result );
  432. }
  433. }
  434. }
  435. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_%s_entry%s %d\n",
  436. (flags & BE_INDEX_ADD) ? "add" : "del",
  437. (flags & BE_INDEX_TOMBSTONE) ? " (tombstone)" : "", result );
  438. return( result );
  439. }
  440. /*
  441. * Add ID to attribute indexes for which Add/Replace/Delete modifications exist
  442. * [olde is the OLD entry, before modifications]
  443. * [newe is the NEW entry, after modifications]
  444. * the old entry is used for REPLACE; the new for DELETE */
  445. int
  446. index_add_mods(
  447. backend *be,
  448. LDAPMod **mods,
  449. struct backentry *olde,
  450. struct backentry *newe,
  451. back_txn *txn
  452. )
  453. {
  454. int rc = 0;
  455. int i, j;
  456. ID id = olde->ep_id;
  457. int flags = 0;
  458. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  459. char *basetype = NULL;
  460. char *tmp = NULL;
  461. Slapi_Attr *curr_attr = NULL;
  462. struct attrinfo *ai = NULL;
  463. Slapi_ValueSet *all_vals = NULL;
  464. Slapi_ValueSet *mod_vals = NULL;
  465. Slapi_Value **evals = NULL; /* values that still exist after a
  466. * delete.
  467. */
  468. Slapi_Value **mods_valueArray = NULL; /* values that are specified in this
  469. * operation.
  470. */
  471. Slapi_Value **deleted_valueArray = NULL; /* values whose index entries
  472. * should be deleted.
  473. */
  474. for ( i = 0; mods && mods[i] != NULL; i++ ) {
  475. /* Get base attribute type */
  476. basetype = buf;
  477. tmp = slapi_attr_basetype(mods[i]->mod_type, buf, sizeof(buf));
  478. if(tmp != NULL) {
  479. basetype = tmp; /* basetype was malloc'd */
  480. }
  481. ainfo_get( be, basetype, &ai );
  482. if ( ai == NULL || ai->ai_indexmask == 0 || ai->ai_indexmask == INDEX_OFFLINE ) {
  483. /* this attribute is not being indexed, skip it. */
  484. goto error;
  485. }
  486. /* Get a list of all remaining values for the base type
  487. * and any present subtypes.
  488. */
  489. all_vals = slapi_valueset_new();
  490. for (curr_attr = newe->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  491. if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
  492. slapi_valueset_join_attr_valueset(curr_attr, all_vals, &curr_attr->a_present_values);
  493. }
  494. }
  495. evals = valueset_get_valuearray(all_vals);
  496. /* Get a list of all values specified in the operation.
  497. */
  498. if ( mods[i]->mod_bvalues != NULL ) {
  499. valuearray_init_bervalarray(mods[i]->mod_bvalues, &mods_valueArray);
  500. }
  501. switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) {
  502. case LDAP_MOD_REPLACE:
  503. flags = BE_INDEX_DEL;
  504. /* Get a list of all values being deleted.
  505. */
  506. mod_vals = slapi_valueset_new();
  507. for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  508. if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
  509. slapi_valueset_join_attr_valueset(curr_attr, mod_vals, &curr_attr->a_present_values);
  510. }
  511. }
  512. deleted_valueArray = valueset_get_valuearray(mod_vals);
  513. /* If subtypes exist, don't remove the presence
  514. * index.
  515. */
  516. if ( evals != NULL && deleted_valueArray != NULL) {
  517. /* evals will contain the new value that is being
  518. * added as part of the replace operation if one
  519. * was specified. We must remove this value from
  520. * evals to know if any subtypes are present.
  521. */
  522. slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr );
  523. if ( mods_valueArray != NULL ) {
  524. for ( j = 0; mods_valueArray[j] != NULL; j++ ) {
  525. Slapi_Value *rval = valueset_remove_value(curr_attr, all_vals, mods_valueArray[j]);
  526. slapi_value_free( &rval );
  527. }
  528. }
  529. /* Search evals for the values being deleted. If
  530. * they don't exist, delete the equality index.
  531. */
  532. for ( j = 0; deleted_valueArray[j] != NULL; j++ ) {
  533. if ( !slapi_valueset_find(curr_attr, all_vals, deleted_valueArray[j])) {
  534. if (!(flags & BE_INDEX_EQUALITY)) {
  535. flags |= BE_INDEX_EQUALITY;
  536. }
  537. } else {
  538. Slapi_Value *rval = valueset_remove_value(curr_attr, mod_vals, deleted_valueArray[j]);
  539. slapi_value_free( &rval );
  540. j--;
  541. /* indicates there was some conflict */
  542. mods[i]->mod_op |= LDAP_MOD_IGNORE;
  543. }
  544. }
  545. } else {
  546. flags |= BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  547. }
  548. /* We need to first remove the old values from the
  549. * index, if any. */
  550. if (deleted_valueArray) {
  551. rc = index_addordel_values_sv( be, mods[i]->mod_type,
  552. deleted_valueArray, evals, id,
  553. flags, txn );
  554. if (rc) {
  555. ldbm_nasty(errmsg, 1041, rc);
  556. goto error;
  557. }
  558. }
  559. /* Free valuearray */
  560. slapi_valueset_free(mod_vals);
  561. mod_vals = NULL;
  562. case LDAP_MOD_ADD:
  563. if ( mods_valueArray == NULL ) {
  564. rc = 0;
  565. } else {
  566. /* Verify if the value is in newe.
  567. * If it is in, we will add the attr value to the index file. */
  568. curr_attr = NULL;
  569. slapi_entry_attr_find(newe->ep_entry,
  570. mods[i]->mod_type, &curr_attr);
  571. if (curr_attr) { /* found the type */
  572. for (j = 0; mods_valueArray[j] != NULL; j++) {
  573. /* mods_valueArray[j] is in curr_attr ==> return 0 */
  574. if ( !slapi_valueset_find(curr_attr, &curr_attr->a_present_values,
  575. mods_valueArray[j])) {
  576. /* The value is NOT in newe, remove it. */
  577. Slapi_Value *rval;
  578. rval = valuearray_remove_value(curr_attr,
  579. mods_valueArray,
  580. mods_valueArray[j]);
  581. slapi_value_free( &rval );
  582. /* indicates there was some conflict */
  583. mods[i]->mod_op |= LDAP_MOD_IGNORE;
  584. }
  585. }
  586. if(mods_valueArray[0]){
  587. rc = index_addordel_values_sv( be, mods[i]->mod_type,
  588. mods_valueArray, NULL,
  589. id, BE_INDEX_ADD, txn );
  590. } else {
  591. rc = 0;
  592. }
  593. if (rc) {
  594. ldbm_nasty(errmsg, 1042, rc);
  595. goto error;
  596. }
  597. }
  598. }
  599. break;
  600. case LDAP_MOD_DELETE:
  601. if ( (mods[i]->mod_bvalues == NULL) ||
  602. (mods[i]->mod_bvalues[0] == NULL) ) {
  603. rc = 0;
  604. flags = BE_INDEX_DEL;
  605. /* Get a list of all values that are being
  606. * deleted.
  607. */
  608. mod_vals = slapi_valueset_new();
  609. for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
  610. if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
  611. slapi_valueset_join_attr_valueset(curr_attr, mod_vals, &curr_attr->a_present_values);
  612. }
  613. }
  614. deleted_valueArray = valueset_get_valuearray(mod_vals);
  615. /* If subtypes exist, don't remove the
  616. * presence index.
  617. */
  618. if (evals != NULL) {
  619. for (curr_attr = newe->ep_entry->e_attrs; (curr_attr != NULL);
  620. curr_attr = curr_attr->a_next) {
  621. if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
  622. /* Check if the any values being deleted
  623. * also exist in a subtype.
  624. */
  625. for (j = 0; deleted_valueArray && deleted_valueArray[j]; j++) {
  626. if ( !slapi_valueset_find(curr_attr, all_vals, deleted_valueArray[j])) {
  627. /* If the equality flag isn't already set, set it */
  628. if (!(flags & BE_INDEX_EQUALITY)) {
  629. flags |= BE_INDEX_EQUALITY;
  630. }
  631. } else {
  632. /* Remove duplicate value from the mod list */
  633. Slapi_Value *rval = valueset_remove_value(curr_attr, mod_vals, deleted_valueArray[j]);
  634. slapi_value_free( &rval );
  635. j--;
  636. }
  637. }
  638. }
  639. }
  640. } else {
  641. flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  642. }
  643. /* Update the index, if necessary */
  644. if (deleted_valueArray) {
  645. rc = index_addordel_values_sv( be, mods[i]->mod_type,
  646. deleted_valueArray, evals, id,
  647. flags, txn );
  648. if (rc) {
  649. ldbm_nasty(errmsg, 1043, rc);
  650. goto error;
  651. }
  652. }
  653. slapi_valueset_free(mod_vals);
  654. mod_vals = NULL;
  655. } else {
  656. /* determine if the presence key should be
  657. * removed (are we removing the last value
  658. * for this attribute?)
  659. */
  660. if (evals == NULL || evals[0] == NULL) {
  661. /* The new entry newe does not have the attribute at all
  662. * including the one with subtypes. Thus it's safe to
  663. * remove the presence and equality index.
  664. */
  665. flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  666. } else {
  667. flags = BE_INDEX_DEL;
  668. curr_attr = NULL;
  669. slapi_entry_attr_find(olde->ep_entry,
  670. mods[i]->mod_type,
  671. &curr_attr);
  672. if (curr_attr) {
  673. for (j = 0; mods_valueArray[j] != NULL; j++ ) {
  674. if ( !slapi_valueset_find(curr_attr, all_vals, mods_valueArray[j]) ) {
  675. /*
  676. * If the mod del value is not found in all_vals
  677. * we need to update the equality index as the
  678. * final value(s) have changed
  679. */
  680. if (!(flags & BE_INDEX_EQUALITY)) {
  681. flags |= BE_INDEX_EQUALITY;
  682. }
  683. break;
  684. }
  685. }
  686. }
  687. }
  688. rc = index_addordel_values_sv( be, basetype,
  689. mods_valueArray,
  690. evals, id, flags, txn );
  691. if (rc) {
  692. ldbm_nasty(errmsg, 1044, rc);
  693. goto error;
  694. }
  695. }
  696. rc = 0;
  697. break;
  698. } /* switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) */
  699. error:
  700. /* free memory */
  701. slapi_ch_free((void **)&tmp);
  702. tmp = NULL;
  703. valuearray_free(&mods_valueArray);
  704. mods_valueArray = NULL;
  705. slapi_valueset_free(all_vals);
  706. all_vals = NULL;
  707. slapi_valueset_free(mod_vals);
  708. mod_vals = NULL;
  709. if ( rc != 0 ) {
  710. ldbm_nasty(errmsg, 1040, rc);
  711. return( rc );
  712. }
  713. } /* for ( i = 0; mods[i] != NULL; i++ ) */
  714. return( 0 );
  715. }
  716. /*
  717. * Convert a 'struct berval' into a displayable ASCII string
  718. */
  719. #define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"')
  720. const char*
  721. encode (const struct berval* data, char buf[BUFSIZ])
  722. {
  723. char* s;
  724. char* last;
  725. if (data == NULL || data->bv_len == 0) return "";
  726. last = data->bv_val + data->bv_len - 1;
  727. for (s = data->bv_val; s < last; ++s) {
  728. if ( SPECIAL (*s)) {
  729. char* first = data->bv_val;
  730. char* bufNext = buf;
  731. size_t bufSpace = BUFSIZ - 4;
  732. while (1) {
  733. /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */
  734. if (bufSpace < (size_t)(s - first)) s = first + bufSpace - 1;
  735. if (s != first) {
  736. memcpy (bufNext, first, s - first);
  737. bufNext += (s - first);
  738. bufSpace -= (s - first);
  739. }
  740. do {
  741. *bufNext++ = '\\'; --bufSpace;
  742. if (bufSpace < 2) {
  743. memcpy (bufNext, "..", 2);
  744. bufNext += 2;
  745. goto bail;
  746. }
  747. if (*s == '\\' || *s == '"') {
  748. *bufNext++ = *s; --bufSpace;
  749. } else {
  750. sprintf (bufNext, "%02x", (unsigned)*(unsigned char*)s);
  751. bufNext += 2; bufSpace -= 2;
  752. }
  753. } while (++s <= last && SPECIAL (*s));
  754. if (s > last) break;
  755. first = s;
  756. while ( ! SPECIAL (*s) && s <= last) ++s;
  757. }
  758. bail:
  759. *bufNext = '\0';
  760. /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */
  761. return buf;
  762. }
  763. }
  764. /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */
  765. return data->bv_val;
  766. }
  767. static const char*
  768. encoded (DBT* d, char buf [BUFSIZ])
  769. {
  770. struct berval data;
  771. data.bv_len = d->dsize;
  772. data.bv_val = d->dptr;
  773. return encode (&data, buf);
  774. }
  775. IDList *
  776. index_read(
  777. backend *be,
  778. char *type,
  779. const char *indextype,
  780. const struct berval *val,
  781. back_txn *txn,
  782. int *err
  783. )
  784. {
  785. return index_read_ext(be, type, indextype, val, txn, err, NULL);
  786. }
  787. /*
  788. * Extended version of index_read.
  789. * The unindexed flag can be used to distinguish between a
  790. * return of allids due to the attr not being indexed or
  791. * the value really being allids.
  792. * You can pass in the value of the allidslimit (aka idlistscanlimit)
  793. * with this version of the function
  794. * if the value is 0, it will use the old method of getting the value
  795. * from the attrinfo*.
  796. */
  797. IDList *
  798. index_read_ext_allids(
  799. Slapi_PBlock *pb,
  800. backend *be,
  801. char *type,
  802. const char *indextype,
  803. const struct berval *val,
  804. back_txn *txn,
  805. int *err,
  806. int *unindexed,
  807. int allidslimit
  808. )
  809. {
  810. DB *db = NULL;
  811. DB_TXN *db_txn = NULL;
  812. DBT key = {0};
  813. IDList *idl = NULL;
  814. char *prefix;
  815. char *tmpbuf = NULL;
  816. char buf[BUFSIZ];
  817. char typebuf[ SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH ];
  818. struct attrinfo *ai = NULL;
  819. char *basetmp, *basetype;
  820. int retry_count = 0;
  821. struct berval *encrypted_val = NULL;
  822. int is_and = 0;
  823. unsigned int ai_flags = 0;
  824. *err = 0;
  825. if (unindexed != NULL) *unindexed = 0;
  826. prefix = index_index2prefix( indextype );
  827. if (prefix == NULL) {
  828. LDAPDebug0Args( LDAP_DEBUG_ANY, "index_read_ext: NULL prefix\n" );
  829. return NULL;
  830. }
  831. LDAPDebug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" %s \"%s\" )\n",
  832. type, prefix, encode (val, buf));
  833. basetype = typebuf;
  834. if ( (basetmp = slapi_attr_basetype( type, typebuf, sizeof(typebuf) ))
  835. != NULL ) {
  836. basetype = basetmp;
  837. }
  838. ainfo_get( be, basetype, &ai );
  839. if (ai == NULL) {
  840. index_free_prefix( prefix );
  841. slapi_ch_free_string( &basetmp );
  842. return NULL;
  843. }
  844. LDAPDebug( LDAP_DEBUG_ARGS, " indextype: \"%s\" indexmask: 0x%x\n",
  845. indextype, ai->ai_indexmask, 0 );
  846. /* If entryrdn switch is on AND the type is entrydn AND the prefix is '=',
  847. * use the entryrdn index directly */
  848. if (entryrdn_get_switch() && (*prefix == '=') &&
  849. (0 == PL_strcasecmp(basetype, LDBM_ENTRYDN_STR))) {
  850. int rc = 0;
  851. ID id = 0;
  852. Slapi_DN sdn;
  853. /* We don't need these values... */
  854. index_free_prefix( prefix );
  855. slapi_ch_free_string( &basetmp );
  856. if (NULL == val || NULL == val->bv_val) {
  857. /* entrydn value was not given */
  858. return NULL;
  859. }
  860. slapi_sdn_init_dn_byval(&sdn, val->bv_val);
  861. rc = entryrdn_index_read(be, &sdn, &id, txn);
  862. slapi_sdn_done(&sdn);
  863. if (rc) { /* failure */
  864. return NULL;
  865. } else { /* success */
  866. rc = idl_append_extend(&idl, id);
  867. if (rc) { /* failure */
  868. return NULL;
  869. }
  870. return idl;
  871. }
  872. }
  873. if ( !is_indexed( indextype, ai->ai_indexmask, ai->ai_index_rules ) ) {
  874. idl = idl_allids( be );
  875. if (unindexed != NULL) *unindexed = 1;
  876. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates "
  877. "(allids - not indexed)\n", (u_long)IDL_NIDS(idl), 0, 0 );
  878. index_free_prefix( prefix );
  879. slapi_ch_free_string( &basetmp );
  880. return( idl );
  881. }
  882. if (pb) {
  883. slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and);
  884. }
  885. ai_flags = is_and ? INDEX_ALLIDS_FLAG_AND : 0;
  886. /* the caller can pass in a value of 0 - just ignore those - but if the index
  887. * config sets the allidslimit to 0, this means to skip the index
  888. */
  889. if (index_get_allids( &allidslimit, indextype, ai, val, ai_flags ) &&
  890. (allidslimit == 0)) {
  891. idl = idl_allids( be );
  892. if (unindexed != NULL) *unindexed = 1;
  893. LDAPDebug1Arg( LDAP_DEBUG_BACKLDBM, "<= index_read %lu candidates "
  894. "(do not use index)\n", (u_long)IDL_NIDS(idl) );
  895. LDAPDebug( LDAP_DEBUG_BACKLDBM, "<= index_read index attr %s type %s "
  896. "for value %s does not use index\n", basetype, indextype,
  897. (val && val->bv_val) ? val->bv_val : "ALL" );
  898. index_free_prefix( prefix );
  899. slapi_ch_free_string( &basetmp );
  900. return( idl );
  901. }
  902. if ( (*err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  903. LDAPDebug( LDAP_DEBUG_TRACE,
  904. "<= index_read NULL (index file open for attr %s)\n",
  905. basetype, 0, 0 );
  906. index_free_prefix (prefix);
  907. slapi_ch_free_string( &basetmp );
  908. return( NULL );
  909. }
  910. if ( val != NULL ) {
  911. size_t plen, vlen;
  912. char *realbuf;
  913. int ret = 0;
  914. /* If necessary, encrypt this index key */
  915. ret = attrcrypt_encrypt_index_key(be, ai, val, &encrypted_val);
  916. if (ret) {
  917. LDAPDebug( LDAP_DEBUG_ANY,
  918. "index_read failed to encrypt index key for %s\n",
  919. basetype, 0, 0 );
  920. }
  921. if (encrypted_val) {
  922. val = encrypted_val;
  923. }
  924. plen = strlen( prefix );
  925. vlen = val->bv_len;
  926. realbuf = (plen + vlen < sizeof(buf)) ?
  927. buf : (tmpbuf = slapi_ch_malloc( plen + vlen + 1 ));
  928. memcpy( realbuf, prefix, plen );
  929. memcpy( realbuf+plen, val->bv_val, vlen );
  930. realbuf[plen+vlen] = '\0';
  931. key.data = realbuf;
  932. key.size = key.ulen = plen + vlen + 1;
  933. key.flags = DB_DBT_USERMEM;
  934. } else {
  935. key.data = prefix;
  936. key.size = key.ulen = strlen( prefix ) + 1; /* include 0 terminator */
  937. key.flags = DB_DBT_USERMEM;
  938. }
  939. if (NULL != txn) {
  940. db_txn = txn->back_txn_txn;
  941. }
  942. for (retry_count = 0; retry_count < IDL_FETCH_RETRY_COUNT; retry_count++) {
  943. *err = NEW_IDL_DEFAULT;
  944. PRIntervalTime interval;
  945. idl = idl_fetch_ext( be, db, &key, db_txn, ai, err, allidslimit );
  946. if(*err == DB_LOCK_DEADLOCK) {
  947. ldbm_nasty("index read retrying transaction", 1045, *err);
  948. #ifdef FIX_TXN_DEADLOCKS
  949. #error can only retry here if txn == NULL - otherwise, have to abort and retry txn
  950. #endif
  951. interval = PR_MillisecondsToInterval(slapi_rand() % 100);
  952. DS_Sleep(interval);
  953. continue;
  954. } else {
  955. break;
  956. }
  957. }
  958. if(retry_count == IDL_FETCH_RETRY_COUNT) {
  959. ldbm_nasty("index_read retry count exceeded",1046,*err);
  960. } else if ( *err != 0 && *err != DB_NOTFOUND ) {
  961. ldbm_nasty(errmsg, 1050, *err);
  962. }
  963. slapi_ch_free_string( &basetmp );
  964. slapi_ch_free_string(&tmpbuf);
  965. dblayer_release_index_file( be, ai, db );
  966. index_free_prefix (prefix);
  967. if (encrypted_val) {
  968. ber_bvfree(encrypted_val);
  969. }
  970. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_read %lu candidates\n",
  971. (u_long)IDL_NIDS(idl), 0, 0 );
  972. return( idl );
  973. }
  974. IDList *
  975. index_read_ext(
  976. backend *be,
  977. char *type,
  978. const char *indextype,
  979. const struct berval *val,
  980. back_txn *txn,
  981. int *err,
  982. int *unindexed
  983. )
  984. {
  985. return index_read_ext_allids(NULL, be, type, indextype, val, txn, err, unindexed, 0);
  986. }
  987. /* This function compares two index keys. It is assumed
  988. that the values are already normalized, since they should have
  989. been when the index was created (by int_values2keys).
  990. richm - actually, the current syntax compare functions
  991. always normalize both arguments. We need to add an additional
  992. syntax compare function that does not normalize or takes
  993. an argument like value_cmp to specify to normalize or not.
  994. More fun - this function is used to compare both raw database
  995. keys (e.g. with the prefix '=' or '+' or '*' etc.) and without
  996. (in the case of two equality keys, we want to strip off the
  997. leading '=' to compare the actual values). We only use the
  998. value_compare function if both keys are equality keys with
  999. some data after the equality prefix. In every other case,
  1000. we will just use a standard berval cmp function.
  1001. see also dblayer_bt_compare
  1002. */
  1003. int
  1004. DBTcmp (DBT* L, DBT* R, value_compare_fn_type cmp_fn)
  1005. {
  1006. struct berval Lv;
  1007. struct berval Rv;
  1008. if ((L->data && (L->size>1) && (*((char*)L->data) == EQ_PREFIX)) &&
  1009. (R->data && (R->size>1) && (*((char*)R->data) == EQ_PREFIX))) {
  1010. Lv.bv_val = (char*)L->data+1; Lv.bv_len = (ber_len_t)L->size-1;
  1011. Rv.bv_val = (char*)R->data+1; Rv.bv_len = (ber_len_t)R->size-1;
  1012. /* use specific compare fn, if any */
  1013. cmp_fn = (cmp_fn ? cmp_fn : slapi_berval_cmp);
  1014. } else {
  1015. Lv.bv_val = (char*)L->data; Lv.bv_len = (ber_len_t)L->size;
  1016. Rv.bv_val = (char*)R->data; Rv.bv_len = (ber_len_t)R->size;
  1017. /* just compare raw bervals */
  1018. cmp_fn = slapi_berval_cmp;
  1019. }
  1020. return cmp_fn(&Lv, &Rv);
  1021. }
  1022. /* Steps to the next key without keeping a cursor open */
  1023. /* Returns the new key value in the DBT */
  1024. static int index_range_next_key(DB *db,DBT *key,DB_TXN *db_txn)
  1025. {
  1026. DBC *cursor = NULL;
  1027. DBT data = {0};
  1028. int ret = 0;
  1029. void *saved_key = key->data;
  1030. /* Make cursor */
  1031. retry:
  1032. ret = db->cursor(db,db_txn,&cursor, 0);
  1033. if (0 != ret) {
  1034. return ret;
  1035. }
  1036. /* Seek to the last key */
  1037. data.flags = DB_DBT_MALLOC;
  1038. ret = cursor->c_get(cursor,key,&data,DB_SET); /* both key and data could be allocated */
  1039. /* data allocated here, we don't need it */
  1040. DBT_FREE_PAYLOAD(data);
  1041. if (DB_NOTFOUND == ret) {
  1042. void *old_key_buffer = key->data;
  1043. /* If this happens, it means that we tried to seek to a key which has just been deleted */
  1044. /* So, we seek to the nearest one instead */
  1045. ret = cursor->c_get(cursor,key,&data,DB_SET_RANGE);
  1046. /* a new key and data are allocated here, need to free them both */
  1047. if (old_key_buffer != key->data) {
  1048. DBT_FREE_PAYLOAD(*key);
  1049. }
  1050. DBT_FREE_PAYLOAD(data);
  1051. }
  1052. if (0 != ret) {
  1053. if (DB_LOCK_DEADLOCK == ret)
  1054. {
  1055. /* Deadlock detected, retry the operation */
  1056. cursor->c_close(cursor);
  1057. cursor = NULL;
  1058. key->data = saved_key;
  1059. #ifdef FIX_TXN_DEADLOCKS
  1060. #error if txn != NULL, have to abort and retry the transaction, not just the cursor
  1061. #endif
  1062. goto retry;
  1063. } else
  1064. {
  1065. goto error;
  1066. }
  1067. }
  1068. if (saved_key != key->data) {
  1069. /* key could be allocated in the above c_get */
  1070. DBT_FREE_PAYLOAD(*key);
  1071. }
  1072. /* Seek to the next one
  1073. * [612498] NODUP is needed for new idl to get the next non-duplicated key
  1074. * No effect on old idl since there's no dup there (i.e., DB_NEXT == DB_NEXT_NODUP)
  1075. */
  1076. ret = cursor->c_get(cursor,key,&data,DB_NEXT_NODUP); /* new key and data are allocated, we only need the key */
  1077. DBT_FREE_PAYLOAD(data);
  1078. if (DB_LOCK_DEADLOCK == ret)
  1079. {
  1080. /* Deadlock detected, retry the operation */
  1081. cursor->c_close(cursor);
  1082. cursor = NULL;
  1083. key->data = saved_key;
  1084. #ifdef FIX_TXN_DEADLOCKS
  1085. #error if txn != NULL, have to abort and retry the transaction, not just the cursor
  1086. #endif
  1087. goto retry;
  1088. }
  1089. error:
  1090. /* Close the cursor */
  1091. cursor->c_close(cursor);
  1092. if (saved_key) { /* Need to free the original key passed in */
  1093. if (saved_key == key->data) {
  1094. /* Means that we never allocated a new key */
  1095. ;
  1096. } else {
  1097. slapi_ch_free(&saved_key);
  1098. }
  1099. }
  1100. return ret;
  1101. }
  1102. IDList *
  1103. index_range_read_ext(
  1104. Slapi_PBlock *pb,
  1105. backend *be,
  1106. char *type,
  1107. const char *indextype,
  1108. int operator,
  1109. struct berval *val,
  1110. struct berval *nextval,
  1111. int range,
  1112. back_txn *txn,
  1113. int *err,
  1114. int allidslimit
  1115. )
  1116. {
  1117. struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
  1118. DB *db;
  1119. DB_TXN *db_txn = NULL;
  1120. DBC *dbc = NULL;
  1121. DBT lowerkey = {0};
  1122. DBT upperkey = {0};
  1123. DBT cur_key = {0};
  1124. DBT data = {0} ;
  1125. IDList *idl = NULL;
  1126. char *prefix = NULL;
  1127. char *realbuf, *nextrealbuf;
  1128. size_t reallen, nextreallen;
  1129. size_t plen;
  1130. ID i;
  1131. struct attrinfo *ai = NULL;
  1132. int lookthrough_limit = -1; /* default no limit */
  1133. int is_and = 0;
  1134. int sizelimit = 0;
  1135. time_t curtime, stoptime = 0;
  1136. int timelimit = -1;
  1137. back_search_result_set *sr = NULL;
  1138. int isroot = 0;
  1139. if (!pb) {
  1140. LDAPDebug(LDAP_DEBUG_ANY, "index_range_read: NULL pblock\n",
  1141. 0, 0, 0);
  1142. return NULL;
  1143. }
  1144. *err = 0;
  1145. prefix = index_index2prefix( indextype );
  1146. if (prefix == NULL) {
  1147. LDAPDebug0Args( LDAP_DEBUG_ANY, "index_range_read: NULL prefix\n" );
  1148. return( NULL );
  1149. }
  1150. plen = strlen(prefix);
  1151. slapi_pblock_get(pb, SLAPI_SEARCH_IS_AND, &is_and);
  1152. if (!is_and) {
  1153. slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit);
  1154. }
  1155. slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &timelimit);
  1156. if (timelimit != -1) {
  1157. time_t optime;
  1158. slapi_pblock_get(pb, SLAPI_OPINITIATED_TIME, &optime);
  1159. stoptime = optime + timelimit;
  1160. }
  1161. /*
  1162. * Determine the lookthrough_limit from the PBlock.
  1163. * No limit if there is no search result set and the requestor is root.
  1164. */
  1165. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
  1166. if (sr != NULL) {
  1167. /* the normal case */
  1168. lookthrough_limit = sr->sr_lookthroughlimit;
  1169. }
  1170. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  1171. if (!isroot) {
  1172. if (lookthrough_limit > li->li_rangelookthroughlimit) {
  1173. lookthrough_limit = li->li_rangelookthroughlimit;
  1174. }
  1175. }
  1176. LDAPDebug1Arg(LDAP_DEBUG_TRACE, "index_range_read lookthrough_limit=%d\n",
  1177. lookthrough_limit);
  1178. switch( operator ) {
  1179. case SLAPI_OP_LESS:
  1180. case SLAPI_OP_LESS_OR_EQUAL:
  1181. case SLAPI_OP_GREATER_OR_EQUAL:
  1182. case SLAPI_OP_GREATER:
  1183. break;
  1184. default:
  1185. LDAPDebug( LDAP_DEBUG_ANY,
  1186. "<= index_range_read(%s,%s) NULL (operator %i)\n",
  1187. type, prefix, operator );
  1188. index_free_prefix(prefix);
  1189. return( NULL );
  1190. }
  1191. ainfo_get( be, type, &ai );
  1192. if (ai == NULL) {
  1193. index_free_prefix(prefix);
  1194. return NULL;
  1195. }
  1196. LDAPDebug( LDAP_DEBUG_ARGS, " indextype: \"%s\" indexmask: 0x%x\n",
  1197. indextype, ai->ai_indexmask, 0 );
  1198. if ( !is_indexed( indextype, ai->ai_indexmask, ai->ai_index_rules )) {
  1199. idl = idl_allids( be );
  1200. LDAPDebug( LDAP_DEBUG_TRACE,
  1201. "<= index_range_read(%s,%s) %lu candidates (allids)\n",
  1202. type, prefix, (u_long)IDL_NIDS(idl) );
  1203. index_free_prefix(prefix);
  1204. return( idl );
  1205. }
  1206. if ( (*err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  1207. LDAPDebug( LDAP_DEBUG_ANY,
  1208. "<= index_range_read(%s,%s) NULL (could not open index file)\n",
  1209. type, prefix, 0 );
  1210. index_free_prefix(prefix);
  1211. return( NULL ); /* why not allids? */
  1212. }
  1213. if (NULL != txn) {
  1214. db_txn = txn->back_txn_txn;
  1215. }
  1216. /* get a cursor so we can walk over the table */
  1217. *err = db->cursor(db,db_txn,&dbc,0);
  1218. if (0 != *err ) {
  1219. ldbm_nasty(errmsg, 1060, *err);
  1220. LDAPDebug( LDAP_DEBUG_ANY,
  1221. "<= index_range_read(%s,%s) NULL: db->cursor() == %i\n",
  1222. type, prefix, *err );
  1223. dblayer_release_index_file( be, ai, db );
  1224. index_free_prefix(prefix);
  1225. return( NULL ); /* why not allids? */
  1226. }
  1227. /* set up the starting and ending keys for a range search */
  1228. if ( val != NULL ) { /* compute a key from val */
  1229. const size_t vlen = val->bv_len;
  1230. reallen = plen + vlen + 1;
  1231. realbuf = slapi_ch_malloc( reallen );
  1232. memcpy( realbuf, prefix, plen );
  1233. memcpy( realbuf+plen, val->bv_val, vlen );
  1234. realbuf[plen+vlen] = '\0';
  1235. } else {
  1236. reallen = plen + 1; /* include 0 terminator */
  1237. realbuf = slapi_ch_strdup(prefix);
  1238. }
  1239. if (range != 1) { /* open range search */
  1240. char *tmpbuf = NULL;
  1241. /* this is a search with only one boundary value */
  1242. switch( operator ) {
  1243. case SLAPI_OP_LESS:
  1244. case SLAPI_OP_LESS_OR_EQUAL:
  1245. lowerkey.dptr = slapi_ch_strdup(prefix);
  1246. lowerkey.dsize = plen;
  1247. upperkey.dptr = realbuf;
  1248. upperkey.dsize = reallen;
  1249. break;
  1250. case SLAPI_OP_GREATER_OR_EQUAL:
  1251. case SLAPI_OP_GREATER:
  1252. lowerkey.dptr = realbuf;
  1253. lowerkey.dsize = reallen;
  1254. /* upperkey = a value slightly greater than prefix */
  1255. tmpbuf = slapi_ch_malloc (plen + 1);
  1256. memcpy (tmpbuf, prefix, plen + 1);
  1257. ++(tmpbuf[plen-1]);
  1258. upperkey.dptr = tmpbuf;
  1259. upperkey.dsize = plen;
  1260. tmpbuf = NULL;
  1261. /* ... but not greater than the last key in the index */
  1262. cur_key.flags = DB_DBT_MALLOC;
  1263. data.flags = DB_DBT_MALLOC;
  1264. *err = dbc->c_get(dbc,&cur_key,&data,DB_LAST); /* key and data allocated here, need to free them */
  1265. DBT_FREE_PAYLOAD(data);
  1266. /* Note that cur_key needs to get freed somewhere below */
  1267. if (0 != *err) {
  1268. if (DB_NOTFOUND == *err) {
  1269. /* There are no keys in the index so we should return no candidates. */
  1270. *err = 0;
  1271. idl = NULL;
  1272. slapi_ch_free( (void**)&realbuf);
  1273. dbc->c_close(dbc);
  1274. goto error;
  1275. } else {
  1276. ldbm_nasty(errmsg, 1070, *err);
  1277. LDAPDebug( LDAP_DEBUG_ANY,
  1278. "index_range_read(%s,%s) seek to end of index file err %i\n",
  1279. type, prefix, *err );
  1280. }
  1281. } else if (DBTcmp (&upperkey, &cur_key, ai->ai_key_cmp_fn) > 0) {
  1282. DBT_FREE_PAYLOAD(upperkey);
  1283. upperkey.dptr = NULL; /* x >= a :no need to check upper bound */
  1284. upperkey.dsize = 0;
  1285. }
  1286. break;
  1287. }
  1288. } else { /* closed range search: e.g., (&(x >= a)(x <= b)) */
  1289. /* this is a search with two boundary values (starting and ending) */
  1290. if ( nextval != NULL ) { /* compute a key from nextval */
  1291. const size_t vlen = nextval->bv_len;
  1292. nextreallen = plen + vlen + 1;
  1293. nextrealbuf = slapi_ch_malloc( plen + vlen + 1 );
  1294. memcpy( nextrealbuf, prefix, plen );
  1295. memcpy( nextrealbuf+plen, nextval->bv_val, vlen );
  1296. nextrealbuf[plen+vlen] = '\0';
  1297. } else {
  1298. nextreallen = plen + 1; /* include 0 terminator */
  1299. nextrealbuf = slapi_ch_strdup(prefix);
  1300. }
  1301. /* set up the starting and ending keys for search */
  1302. lowerkey.dptr = realbuf;
  1303. lowerkey.dsize = reallen;
  1304. upperkey.dptr = nextrealbuf;
  1305. upperkey.dsize = nextreallen;
  1306. }
  1307. /* if (LDAP_DEBUG_FILTER) {
  1308. char encbuf [BUFSIZ];
  1309. LDAPDebug( LDAP_DEBUG_FILTER, " lowerkey=%s(%li bytes)\n",
  1310. encoded (&lowerkey, encbuf), (long)lowerkey.dsize, 0 );
  1311. LDAPDebug( LDAP_DEBUG_FILTER, " upperkey=%s(%li bytes)\n",
  1312. encoded (&upperkey, encbuf), (long)upperkey.dsize, 0 );
  1313. } */
  1314. data.flags = DB_DBT_MALLOC;
  1315. lowerkey.flags = DB_DBT_MALLOC;
  1316. {
  1317. void *old_lower_key_data = lowerkey.data;
  1318. *err = dbc->c_get(dbc,&lowerkey,&data,DB_SET_RANGE); /* lowerkey, if allocated and needs freed */
  1319. DBT_FREE_PAYLOAD(data);
  1320. if (old_lower_key_data != lowerkey.data) {
  1321. slapi_ch_free(&old_lower_key_data);
  1322. }
  1323. }
  1324. /* If the seek above fails due to DB_NOTFOUND, this means that there are no keys
  1325. which are >= the target key. This means that we should return no candidates */
  1326. if (0 != *err) {
  1327. /* Free the key we just read above */
  1328. DBT_FREE_PAYLOAD(lowerkey);
  1329. if (DB_NOTFOUND == *err) {
  1330. *err = 0;
  1331. idl = NULL;
  1332. } else {
  1333. idl = idl_allids( be );
  1334. ldbm_nasty(errmsg, 1080, *err);
  1335. LDAPDebug( LDAP_DEBUG_ANY,
  1336. "<= index_range_read(%s,%s) allids (seek to lower key in index file err %i)\n",
  1337. type, prefix, *err );
  1338. }
  1339. dbc->c_close(dbc);
  1340. goto error;
  1341. }
  1342. /* We now close the cursor, since we're about to iterate over many keys */
  1343. *err = dbc->c_close(dbc);
  1344. /* step through the indexed db to retrive IDs within the search range */
  1345. DBT_FREE_PAYLOAD(cur_key);
  1346. cur_key.data = lowerkey.data;
  1347. cur_key.size = lowerkey.size;
  1348. lowerkey.data = NULL; /* Don't need this any more, since the memory will be freed from cur_key */
  1349. if (operator == SLAPI_OP_GREATER) {
  1350. *err = index_range_next_key(db,&cur_key,db_txn);
  1351. }
  1352. if (idl_get_idl_new()) { /* new idl */
  1353. idl = idl_new_range_fetch(be, db, &cur_key, &upperkey, db_txn,
  1354. ai, err, allidslimit, sizelimit, stoptime,
  1355. lookthrough_limit, operator);
  1356. } else { /* old idl */
  1357. int retry_count = 0;
  1358. while (*err == 0 &&
  1359. (upperkey.data &&
  1360. (operator == SLAPI_OP_LESS) ?
  1361. DBTcmp(&cur_key, &upperkey, ai->ai_key_cmp_fn) < 0 :
  1362. DBTcmp(&cur_key, &upperkey, ai->ai_key_cmp_fn) <= 0)) {
  1363. /* exit the loop when we either run off the end of the table,
  1364. * fail to read a key, or read a key that's out of range.
  1365. */
  1366. IDList *tmp;
  1367. /*
  1368. char encbuf [BUFSIZ];
  1369. LDAPDebug( LDAP_DEBUG_FILTER, " cur_key=%s(%li bytes)\n",
  1370. encoded (&cur_key, encbuf), (long)cur_key.dsize, 0 );
  1371. */
  1372. /* lookthrough limit and size limit check */
  1373. if (idl) {
  1374. if ((lookthrough_limit != -1) &&
  1375. (idl->b_nids > (ID)lookthrough_limit)) {
  1376. idl_free(&idl);
  1377. idl = idl_allids( be );
  1378. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  1379. "index_range_read lookthrough_limit exceeded\n");
  1380. *err = LDAP_ADMINLIMIT_EXCEEDED;
  1381. break;
  1382. }
  1383. if ((sizelimit > 0) && (idl->b_nids > (ID)sizelimit)) {
  1384. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  1385. "index_range_read sizelimit exceeded\n");
  1386. *err = LDAP_SIZELIMIT_EXCEEDED;
  1387. break;
  1388. }
  1389. }
  1390. /* check time limit */
  1391. if (timelimit != -1) {
  1392. curtime = current_time();
  1393. if (curtime >= stoptime) {
  1394. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  1395. "index_range_read timelimit exceeded\n");
  1396. *err = LDAP_TIMELIMIT_EXCEEDED;
  1397. break;
  1398. }
  1399. }
  1400. /* Check to see if the operation has been abandoned (also happens
  1401. * when the connection is closed by the client).
  1402. */
  1403. if ( slapi_op_abandoned( pb )) {
  1404. if (NULL != idl) {
  1405. idl_free(&idl);
  1406. idl = NULL;
  1407. }
  1408. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  1409. "index_range_read - operation abandoned\n");
  1410. break; /* clean up happens outside the while() loop */
  1411. }
  1412. /* the cur_key DBT already has the first entry in it when we enter
  1413. * the loop, so we process the entry then step to the next one */
  1414. cur_key.flags = 0;
  1415. for (retry_count = 0;
  1416. retry_count < IDL_FETCH_RETRY_COUNT;
  1417. retry_count++) {
  1418. *err = NEW_IDL_DEFAULT;
  1419. tmp = idl_fetch_ext(be, db, &cur_key, NULL, ai, err, allidslimit);
  1420. if(*err == DB_LOCK_DEADLOCK) {
  1421. ldbm_nasty("index_range_read retrying transaction", 1090, *err);
  1422. #ifdef FIX_TXN_DEADLOCKS
  1423. #error if txn != NULL, have to abort and retry the transaction, not just the fetch
  1424. #endif
  1425. continue;
  1426. } else {
  1427. break;
  1428. }
  1429. }
  1430. if(retry_count == IDL_FETCH_RETRY_COUNT) {
  1431. ldbm_nasty("index_range_read retry count exceeded",1095,*err);
  1432. }
  1433. if (!tmp) {
  1434. if (slapi_is_loglevel_set(LDAP_DEBUG_TRACE)) {
  1435. char encbuf[BUFSIZ];
  1436. LDAPDebug2Args(LDAP_DEBUG_TRACE,
  1437. "index_range_read_ext: cur_key=%s(%li bytes) was deleted - skipping\n",
  1438. encoded(&cur_key, encbuf), (long)cur_key.dsize);
  1439. }
  1440. } else {
  1441. /* idl tmp only contains one id */
  1442. /* append it at the end here; sort idlist at the end */
  1443. if (ALLIDS(tmp)) {
  1444. idl_free(&idl);
  1445. idl = tmp;
  1446. } else {
  1447. ID id;
  1448. for (id = idl_firstid(tmp);
  1449. id != NOID; id = idl_nextid(tmp, id)) {
  1450. *err = idl_append_extend(&idl, id);
  1451. if (*err) {
  1452. ldbm_nasty("index_range_read - failed to generate idlist",
  1453. 1097, *err);
  1454. }
  1455. }
  1456. idl_free(&tmp);
  1457. }
  1458. if (ALLIDS(idl)) {
  1459. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  1460. "index_range_read hit an allids value\n");
  1461. break;
  1462. }
  1463. }
  1464. if (DBT_EQ (&cur_key, &upperkey)) { /* this is the last key */
  1465. break;
  1466. /* Another c_get would return the same key, with no error. */
  1467. }
  1468. data.flags = DB_DBT_MALLOC;
  1469. cur_key.flags = DB_DBT_MALLOC;
  1470. *err = index_range_next_key(db,&cur_key,db_txn);
  1471. /* *err = dbc->c_get(dbc,&cur_key,&data,DB_NEXT); */
  1472. if (*err == DB_NOTFOUND) {
  1473. *err = 0;
  1474. break;
  1475. }
  1476. }
  1477. /* sort idl */
  1478. if (idl && !ALLIDS(idl)) {
  1479. qsort((void *)&idl->b_ids[0], idl->b_nids,
  1480. (size_t)sizeof(ID), idl_sort_cmp);
  1481. }
  1482. }
  1483. if (*err) {
  1484. LDAPDebug1Arg(LDAP_DEBUG_FILTER,
  1485. " dbc->c_get(...DB_NEXT) == %i\n", *err);
  1486. }
  1487. #ifdef LDAP_DEBUG
  1488. /* this is for debugging only */
  1489. if (idl != NULL) {
  1490. if (ALLIDS(idl)) {
  1491. LDAPDebug0Args(LDAP_DEBUG_FILTER, " idl=ALLIDS\n");
  1492. } else {
  1493. LDAPDebug1Arg(LDAP_DEBUG_FILTER,
  1494. " idl->b_nids=%d\n", idl->b_nids);
  1495. LDAPDebug1Arg(LDAP_DEBUG_FILTER,
  1496. " idl->b_nmax=%d\n", idl->b_nmax);
  1497. for (i = 0; i < idl->b_nids; i++) {
  1498. LDAPDebug2Args(LDAP_DEBUG_FILTER,
  1499. " idl->b_ids[%d]=%d\n", i, idl->b_ids[i]);
  1500. }
  1501. }
  1502. }
  1503. #endif
  1504. error:
  1505. index_free_prefix(prefix);
  1506. DBT_FREE_PAYLOAD(cur_key);
  1507. DBT_FREE_PAYLOAD(upperkey);
  1508. dblayer_release_index_file( be, ai, db );
  1509. LDAPDebug( LDAP_DEBUG_TRACE, "<= index_range_read(%s,%s) %lu candidates\n",
  1510. type, prefix, (u_long)IDL_NIDS(idl) );
  1511. return( idl );
  1512. }
  1513. IDList *
  1514. index_range_read(
  1515. Slapi_PBlock *pb,
  1516. backend *be,
  1517. char *type,
  1518. const char *indextype,
  1519. int operator,
  1520. struct berval *val,
  1521. struct berval *nextval,
  1522. int range,
  1523. back_txn *txn,
  1524. int *err
  1525. )
  1526. {
  1527. return index_range_read_ext(pb, be, type, indextype, operator, val, nextval, range, txn, err, 0);
  1528. }
  1529. /* DBDB: this function is never actually called */
  1530. #if 0
  1531. static int
  1532. addordel_values(
  1533. backend *be,
  1534. DB *db,
  1535. char *type,
  1536. const char *indextype,
  1537. struct berval **vals,
  1538. ID id,
  1539. int flags, /* BE_INDEX_ADD, etc */
  1540. back_txn *txn,
  1541. struct attrinfo *a,
  1542. int *idl_disposition,
  1543. void *buffer_handle
  1544. )
  1545. {
  1546. int rc = 0;
  1547. int i = 0;
  1548. DBT key = {0};
  1549. DB_TXN *db_txn = NULL;
  1550. size_t plen, vlen, len;
  1551. char *tmpbuf = NULL;
  1552. size_t tmpbuflen = 0;
  1553. char *realbuf;
  1554. char *prefix;
  1555. LDAPDebug( LDAP_DEBUG_TRACE, "=> %s_values\n",
  1556. (flags & BE_INDEX_ADD) ? "add" : "del", 0, 0);
  1557. prefix = index_index2prefix( indextype );
  1558. if (prefix == NULL) {
  1559. LDAPDebug( LDAP_DEBUG_ANY, "<= %s_values: NULL prefix\n",
  1560. (flags & BE_INDEX_ADD) ? "add" : "del", 0, 0 );
  1561. return( -1 );
  1562. }
  1563. if ( vals == NULL ) {
  1564. key.dptr = prefix;
  1565. key.dsize = strlen( prefix ) + 1; /* include null terminator */
  1566. key.flags = DB_DBT_MALLOC;
  1567. if (NULL != txn) {
  1568. db_txn = txn->back_txn_txn;
  1569. }
  1570. if (flags & BE_INDEX_ADD) {
  1571. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1572. } else {
  1573. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1574. /* check for no such key/id - ok in some cases */
  1575. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1576. rc = 0;
  1577. }
  1578. }
  1579. if ( rc != 0)
  1580. {
  1581. ldbm_nasty(errmsg, 1096, rc);
  1582. }
  1583. index_free_prefix (prefix);
  1584. if (NULL != key.dptr && prefix != key.dptr)
  1585. slapi_ch_free( (void**)&key.dptr );
  1586. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1587. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1588. return( rc );
  1589. }
  1590. plen = strlen( prefix );
  1591. for ( i = 0; vals[i] != NULL; i++ ) {
  1592. vlen = vals[i]->bv_len;
  1593. len = plen + vlen;
  1594. if ( len < tmpbuflen ) {
  1595. realbuf = tmpbuf;
  1596. } else {
  1597. tmpbuf = slapi_ch_realloc( tmpbuf, len + 1 );
  1598. tmpbuflen = len + 1;
  1599. realbuf = tmpbuf;
  1600. }
  1601. memcpy( realbuf, prefix, plen );
  1602. memcpy( realbuf+plen, vals[i]->bv_val, vlen );
  1603. realbuf[len] = '\0';
  1604. key.dptr = realbuf;
  1605. key.size = plen + vlen + 1;
  1606. /* should be okay to use USERMEM here because we know what
  1607. * the key is and it should never return a different value
  1608. * than the one we pass in.
  1609. */
  1610. key.flags = DB_DBT_USERMEM;
  1611. key.ulen = tmpbuflen;
  1612. #ifdef LDAP_DEBUG
  1613. /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) XXX */
  1614. {
  1615. char encbuf[BUFSIZ];
  1616. LDAPDebug (LDAP_DEBUG_TRACE, " %s_value(\"%s\")\n",
  1617. (flags & BE_INDEX_ADD) ? "add" : "del",
  1618. encoded (&key, encbuf), 0);
  1619. }
  1620. #endif
  1621. if (NULL != txn) {
  1622. db_txn = txn->back_txn_txn;
  1623. }
  1624. if ( flags & BE_INDEX_ADD ) {
  1625. if (buffer_handle) {
  1626. rc = index_buffer_insert(buffer_handle,&key,id,be,db_txn,a);
  1627. if (rc == -2) {
  1628. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1629. }
  1630. } else {
  1631. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1632. }
  1633. } else {
  1634. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1635. /* check for no such key/id - ok in some cases */
  1636. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1637. rc = 0;
  1638. }
  1639. }
  1640. if ( rc != 0 ) {
  1641. ldbm_nasty(errmsg, 1100, rc);
  1642. break;
  1643. }
  1644. if ( NULL != key.dptr && realbuf != key.dptr) { /* realloc'ed */
  1645. tmpbuf = key.dptr;
  1646. tmpbuflen = key.size;
  1647. }
  1648. }
  1649. index_free_prefix (prefix);
  1650. if ( tmpbuf != NULL ) {
  1651. slapi_ch_free( (void**)&tmpbuf );
  1652. }
  1653. if ( rc != 0 )
  1654. {
  1655. ldbm_nasty(errmsg, 1110, rc);
  1656. }
  1657. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1658. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1659. return( rc );
  1660. }
  1661. #endif
  1662. static int
  1663. addordel_values_sv(
  1664. backend *be,
  1665. DB *db,
  1666. char *type,
  1667. const char *indextype,
  1668. Slapi_Value **vals,
  1669. ID id,
  1670. int flags, /* BE_INDEX_ADD, etc */
  1671. back_txn *txn,
  1672. struct attrinfo *a,
  1673. int *idl_disposition,
  1674. void *buffer_handle
  1675. )
  1676. {
  1677. int rc = 0;
  1678. int i = 0;
  1679. DBT key = {0};
  1680. DB_TXN *db_txn = NULL;
  1681. size_t plen, vlen, len;
  1682. char *tmpbuf = NULL;
  1683. size_t tmpbuflen = 0;
  1684. char *realbuf;
  1685. char *prefix = NULL;
  1686. const struct berval *bvp;
  1687. struct berval *encrypted_bvp = NULL;
  1688. LDAPDebug( LDAP_DEBUG_TRACE, "=> %s_values\n",
  1689. (flags & BE_INDEX_ADD) ? "add" : "del", 0, 0);
  1690. prefix = index_index2prefix( indextype );
  1691. if (prefix == NULL) {
  1692. LDAPDebug0Args( LDAP_DEBUG_ANY, "addordel_values_sv: NULL prefix\n" );
  1693. return( -1 );
  1694. }
  1695. if ( vals == NULL ) {
  1696. key.dptr = prefix;
  1697. key.dsize = strlen( prefix ) + 1; /* include null terminator */
  1698. /* key could be read in idl_{insert,delete}_key.
  1699. * It must be DB_DBT_MALLOC. It's freed if key.dptr != prefix. */
  1700. key.flags = DB_DBT_MALLOC;
  1701. if (NULL != txn) {
  1702. db_txn = txn->back_txn_txn;
  1703. }
  1704. if (flags & BE_INDEX_ADD) {
  1705. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1706. } else {
  1707. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1708. /* check for no such key/id - ok in some cases */
  1709. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1710. rc = 0;
  1711. }
  1712. }
  1713. if ( rc != 0 ) {
  1714. ldbm_nasty(errmsg, 1120, rc);
  1715. }
  1716. if (NULL != key.dptr && prefix != key.dptr) {
  1717. slapi_ch_free( (void**)&key.dptr );
  1718. }
  1719. index_free_prefix (prefix);
  1720. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1721. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1722. return( rc );
  1723. }
  1724. plen = strlen( prefix );
  1725. for ( i = 0; vals[i] != NULL; i++ ) {
  1726. bvp = slapi_value_get_berval(vals[i]);
  1727. /* Encrypt the index key if necessary */
  1728. {
  1729. if (a->ai_attrcrypt && (0 == (flags & BE_INDEX_DONT_ENCRYPT)))
  1730. {
  1731. rc = attrcrypt_encrypt_index_key(be,a,bvp,&encrypted_bvp);
  1732. if (rc)
  1733. {
  1734. LDAPDebug (LDAP_DEBUG_ANY, "Failed to encrypt index key for %s\n", a->ai_type ,0,0);
  1735. } else {
  1736. bvp = encrypted_bvp;
  1737. }
  1738. }
  1739. }
  1740. vlen = bvp->bv_len;
  1741. len = plen + vlen;
  1742. if ( len < tmpbuflen ) {
  1743. realbuf = tmpbuf;
  1744. } else {
  1745. tmpbuf = slapi_ch_realloc( tmpbuf, len + 1 );
  1746. tmpbuflen = len + 1;
  1747. realbuf = tmpbuf;
  1748. }
  1749. memcpy( realbuf, prefix, plen );
  1750. memcpy( realbuf+plen, bvp->bv_val, vlen );
  1751. realbuf[len] = '\0';
  1752. key.dptr = realbuf;
  1753. key.size = plen + vlen + 1;
  1754. /* Free the encrypted berval if necessary */
  1755. if (encrypted_bvp)
  1756. {
  1757. ber_bvfree(encrypted_bvp);
  1758. encrypted_bvp = NULL;
  1759. }
  1760. /* should be okay to use USERMEM here because we know what
  1761. * the key is and it should never return a different value
  1762. * than the one we pass in.
  1763. */
  1764. key.flags = DB_DBT_USERMEM;
  1765. key.ulen = tmpbuflen;
  1766. #ifdef LDAP_DEBUG
  1767. /* XXX if ( slapd_ldap_debug & LDAP_DEBUG_TRACE ) XXX */
  1768. {
  1769. char encbuf[BUFSIZ];
  1770. LDAPDebug (LDAP_DEBUG_TRACE, " %s_value(\"%s\")\n",
  1771. (flags & BE_INDEX_ADD) ? "add" : "del",
  1772. encoded (&key, encbuf), 0);
  1773. }
  1774. #endif
  1775. if (NULL != txn) {
  1776. db_txn = txn->back_txn_txn;
  1777. }
  1778. if ( flags & BE_INDEX_ADD ) {
  1779. if (buffer_handle) {
  1780. rc = index_buffer_insert(buffer_handle,&key,id,be,db_txn,a);
  1781. if (rc == -2) {
  1782. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1783. }
  1784. } else {
  1785. rc = idl_insert_key( be, db, &key, id, db_txn, a, idl_disposition );
  1786. }
  1787. } else {
  1788. rc = idl_delete_key( be, db, &key, id, db_txn, a );
  1789. /* check for no such key/id - ok in some cases */
  1790. if ( rc == DB_NOTFOUND || rc == -666 ) {
  1791. rc = 0;
  1792. }
  1793. }
  1794. if ( rc != 0 ) {
  1795. ldbm_nasty(errmsg, 1130, rc);
  1796. break;
  1797. }
  1798. if ( NULL != key.dptr && realbuf != key.dptr) { /* realloc'ed */
  1799. tmpbuf = key.dptr;
  1800. tmpbuflen = key.size;
  1801. }
  1802. }
  1803. index_free_prefix (prefix);
  1804. if ( tmpbuf != NULL ) {
  1805. slapi_ch_free( (void**)&tmpbuf );
  1806. }
  1807. if ( rc != 0 )
  1808. {
  1809. ldbm_nasty(errmsg, 1140, rc);
  1810. }
  1811. LDAPDebug( LDAP_DEBUG_TRACE, "<= %s_values %d\n",
  1812. (flags & BE_INDEX_ADD) ? "add" : "del", rc, 0 );
  1813. return( rc );
  1814. }
  1815. int
  1816. index_addordel_string(backend *be, const char *type, const char *s, ID id, int flags, back_txn *txn)
  1817. {
  1818. Slapi_Value *svp[2];
  1819. Slapi_Value sv;
  1820. memset(&sv,0,sizeof(Slapi_Value));
  1821. sv.bv.bv_len= strlen(s);
  1822. sv.bv.bv_val= (void*)s;
  1823. svp[0] = &sv;
  1824. svp[1] = NULL;
  1825. if (flags & BE_INDEX_NORMALIZED)
  1826. slapi_value_set_flags(&sv, BE_INDEX_NORMALIZED);
  1827. return index_addordel_values_ext_sv(be,type,svp,NULL,id,flags,txn,NULL,NULL);
  1828. }
  1829. int
  1830. index_addordel_values_sv(
  1831. backend *be,
  1832. const char *type,
  1833. Slapi_Value **vals,
  1834. Slapi_Value **evals, /* existing values */
  1835. ID id,
  1836. int flags,
  1837. back_txn *txn
  1838. )
  1839. {
  1840. return index_addordel_values_ext_sv(be,type,vals,evals,
  1841. id,flags,txn,NULL,NULL);
  1842. }
  1843. int
  1844. index_addordel_values_ext_sv(
  1845. backend *be,
  1846. const char *type,
  1847. Slapi_Value **vals,
  1848. Slapi_Value **evals,
  1849. ID id,
  1850. int flags,
  1851. back_txn *txn,
  1852. int *idl_disposition,
  1853. void *buffer_handle
  1854. )
  1855. {
  1856. DB *db;
  1857. struct attrinfo *ai = NULL;
  1858. int err = -1;
  1859. Slapi_Value **ivals;
  1860. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  1861. char *basetmp, *basetype;
  1862. LDAPDebug( LDAP_DEBUG_TRACE,
  1863. "=> index_addordel_values_ext_sv( \"%s\", %lu )\n", type, (u_long)id, 0 );
  1864. basetype = buf;
  1865. if ( (basetmp = slapi_attr_basetype( type, buf, sizeof(buf) ))
  1866. != NULL ) {
  1867. basetype = basetmp;
  1868. }
  1869. ainfo_get( be, basetype, &ai );
  1870. if ( ai == NULL || ai->ai_indexmask == 0
  1871. || ai->ai_indexmask == INDEX_OFFLINE ) {
  1872. slapi_ch_free_string( &basetmp );
  1873. return( 0 );
  1874. }
  1875. LDAPDebug( LDAP_DEBUG_ARGS, " index_addordel_values_ext_sv indexmask 0x%x\n",
  1876. ai->ai_indexmask, 0, 0 );
  1877. if ( (err = dblayer_get_index_file( be, ai, &db, DBOPEN_CREATE )) != 0 ) {
  1878. LDAPDebug( LDAP_DEBUG_ANY,
  1879. "<= index_read NULL (could not open index attr %s)\n",
  1880. basetype, 0, 0 );
  1881. slapi_ch_free_string( &basetmp );
  1882. if ( err != 0 ) {
  1883. ldbm_nasty(errmsg, 1210, err);
  1884. }
  1885. goto bad;
  1886. }
  1887. /*
  1888. * presence index entry
  1889. */
  1890. if (( ai->ai_indexmask & INDEX_PRESENCE ) &&
  1891. (flags & (BE_INDEX_ADD|BE_INDEX_PRESENCE))) {
  1892. /* on delete, only remove the presence index if the
  1893. * BE_INDEX_PRESENCE flag is set.
  1894. */
  1895. err = addordel_values_sv( be, db, basetype, indextype_PRESENCE,
  1896. NULL, id, flags, txn, ai, idl_disposition, NULL );
  1897. if ( err != 0 ) {
  1898. ldbm_nasty(errmsg, 1220, err);
  1899. goto bad;
  1900. }
  1901. }
  1902. /*
  1903. * equality index entry
  1904. */
  1905. if (( ai->ai_indexmask & INDEX_EQUALITY ) &&
  1906. (flags & (BE_INDEX_ADD|BE_INDEX_EQUALITY))) {
  1907. /* on delete, only remove the equality index if the
  1908. * BE_INDEX_EQUALITY flag is set.
  1909. */
  1910. slapi_attr_values2keys_sv( &ai->ai_sattr, vals, &ivals, LDAP_FILTER_EQUALITY );
  1911. err = addordel_values_sv( be, db, basetype, indextype_EQUALITY,
  1912. ivals != NULL ? ivals : vals, id, flags, txn, ai, idl_disposition, NULL );
  1913. if ( ivals != NULL ) {
  1914. valuearray_free( &ivals );
  1915. }
  1916. if ( err != 0 ) {
  1917. ldbm_nasty(errmsg, 1230, err);
  1918. goto bad;
  1919. }
  1920. }
  1921. /*
  1922. * approximate index entry
  1923. */
  1924. if ( ai->ai_indexmask & INDEX_APPROX ) {
  1925. slapi_attr_values2keys_sv( &ai->ai_sattr, vals, &ivals, LDAP_FILTER_APPROX );
  1926. if ( ivals != NULL ) {
  1927. err = addordel_values_sv( be, db, basetype,
  1928. indextype_APPROX, ivals, id, flags, txn, ai, idl_disposition, NULL );
  1929. valuearray_free( &ivals );
  1930. if ( err != 0 ) {
  1931. ldbm_nasty(errmsg, 1240, err);
  1932. goto bad;
  1933. }
  1934. }
  1935. }
  1936. /*
  1937. * substrings index entry
  1938. */
  1939. if ( ai->ai_indexmask & INDEX_SUB ) {
  1940. Slapi_Value **esubvals = NULL;
  1941. Slapi_Value **substresult = NULL;
  1942. Slapi_Value **origvals = NULL;
  1943. Slapi_PBlock pipb;
  1944. /* prepare pblock to pass ai_substr_lens */
  1945. pblock_init( &pipb );
  1946. slapi_pblock_set( &pipb, SLAPI_SYNTAX_SUBSTRLENS, ai->ai_substr_lens );
  1947. slapi_attr_values2keys_sv_pb( &ai->ai_sattr, vals, &ivals,
  1948. LDAP_FILTER_SUBSTRINGS, &pipb );
  1949. origvals = ivals;
  1950. /* delete only: if the attribute has multiple values,
  1951. * figure out the substrings that should remain
  1952. * by slapi_attr_values2keys,
  1953. * then get rid of them from the being deleted values
  1954. */
  1955. if ( evals != NULL ) {
  1956. slapi_attr_values2keys_sv_pb( &ai->ai_sattr, evals,
  1957. &esubvals, LDAP_FILTER_SUBSTRINGS, &pipb );
  1958. substresult = valuearray_minus_valuearray( &ai->ai_sattr, ivals, esubvals );
  1959. ivals = substresult;
  1960. valuearray_free( &esubvals );
  1961. }
  1962. if ( ivals != NULL ) {
  1963. err = addordel_values_sv( be, db, basetype, indextype_SUB,
  1964. ivals, id, flags, txn, ai, idl_disposition, buffer_handle );
  1965. if ( ivals != origvals )
  1966. valuearray_free( &origvals );
  1967. valuearray_free( &ivals );
  1968. if ( err != 0 ) {
  1969. ldbm_nasty(errmsg, 1250, err);
  1970. goto bad;
  1971. }
  1972. ivals = NULL;
  1973. }
  1974. }
  1975. /*
  1976. * matching rule index entries
  1977. */
  1978. if ( ai->ai_indexmask & INDEX_RULES )
  1979. {
  1980. Slapi_PBlock* pb = slapi_pblock_new();
  1981. char** oid = ai->ai_index_rules;
  1982. for (; *oid != NULL; ++oid)
  1983. {
  1984. if(create_matchrule_indexer(&pb,*oid,basetype)==0)
  1985. {
  1986. char* officialOID = NULL;
  1987. if (!slapi_pblock_get (pb, SLAPI_PLUGIN_MR_OID, &officialOID) && officialOID != NULL)
  1988. {
  1989. Slapi_Value** keys = NULL;
  1990. matchrule_values_to_keys_sv(pb,vals,&keys);
  1991. /* the matching rule indexer owns keys now */
  1992. if(keys != NULL && keys[0] != NULL)
  1993. {
  1994. /* we've computed keys */
  1995. err = addordel_values_sv (be, db, basetype, officialOID, keys, id, flags, txn, ai, idl_disposition, NULL);
  1996. if ( err != 0 )
  1997. {
  1998. ldbm_nasty(errmsg, 1260, err);
  1999. }
  2000. }
  2001. /*
  2002. * It would improve speed to save the indexer, for future use.
  2003. * But, for simplicity, we destroy it now:
  2004. */
  2005. /* this will also free keys */
  2006. destroy_matchrule_indexer(pb);
  2007. if ( err != 0 ) {
  2008. goto bad;
  2009. }
  2010. }
  2011. }
  2012. }
  2013. slapi_pblock_destroy (pb);
  2014. }
  2015. dblayer_release_index_file( be, ai, db );
  2016. if ( basetmp != NULL ) {
  2017. slapi_ch_free( (void**)&basetmp );
  2018. }
  2019. LDAPDebug (LDAP_DEBUG_TRACE, "<= index_addordel_values_ext_sv\n", 0, 0, 0 );
  2020. return( 0 );
  2021. bad:
  2022. dblayer_release_index_file(be, ai, db);
  2023. return err;
  2024. }
  2025. int
  2026. index_delete_values(
  2027. struct ldbminfo *li,
  2028. char *type,
  2029. struct berval **vals,
  2030. ID id
  2031. )
  2032. {
  2033. return -1;
  2034. }
  2035. static int
  2036. is_indexed (const char* indextype, int indexmask, char** index_rules)
  2037. {
  2038. int indexed;
  2039. if (indextype == indextype_PRESENCE) indexed = INDEX_PRESENCE & indexmask;
  2040. else if (indextype == indextype_EQUALITY) indexed = INDEX_EQUALITY & indexmask;
  2041. else if (indextype == indextype_APPROX) indexed = INDEX_APPROX & indexmask;
  2042. else if (indextype == indextype_SUB) indexed = INDEX_SUB & indexmask;
  2043. else { /* matching rule */
  2044. indexed = 0;
  2045. if (INDEX_RULES & indexmask) {
  2046. char** rule;
  2047. for (rule = index_rules; *rule; ++rule) {
  2048. if ( ! strcmp( *rule, indextype )) {
  2049. indexed = INDEX_RULES;
  2050. break;
  2051. }
  2052. }
  2053. }
  2054. }
  2055. /* if index is currently being generated, pretend it doesn't exist */
  2056. if (indexmask & INDEX_OFFLINE)
  2057. indexed = 0;
  2058. return indexed;
  2059. }
  2060. char*
  2061. index_index2prefix (const char* indextype)
  2062. {
  2063. char* prefix;
  2064. if ( indextype == NULL ) prefix = NULL;
  2065. else if ( indextype == indextype_PRESENCE ) prefix = prefix_PRESENCE;
  2066. else if ( indextype == indextype_EQUALITY ) prefix = prefix_EQUALITY;
  2067. else if ( indextype == indextype_APPROX ) prefix = prefix_APPROX;
  2068. else if ( indextype == indextype_SUB ) prefix = prefix_SUB;
  2069. else { /* indextype is a matching rule name */
  2070. const size_t len = strlen (indextype);
  2071. char* p = slapi_ch_malloc (len + 3);
  2072. p[0] = RULE_PREFIX;
  2073. memcpy( p+1, indextype, len );
  2074. p[len+1] = ':';
  2075. p[len+2] = '\0';
  2076. prefix = p;
  2077. }
  2078. return( prefix );
  2079. }
  2080. void
  2081. index_free_prefix (char* prefix)
  2082. {
  2083. if (prefix == NULL ||
  2084. prefix == prefix_PRESENCE ||
  2085. prefix == prefix_EQUALITY ||
  2086. prefix == prefix_APPROX ||
  2087. prefix == prefix_SUB) {
  2088. /* do nothing */
  2089. } else {
  2090. slapi_ch_free( (void**)&prefix);
  2091. }
  2092. }
  2093. /* helper stuff for valuearray_minus_valuearray */
  2094. typedef struct {
  2095. value_compare_fn_type cmp_fn;
  2096. Slapi_Value *data;
  2097. } SVSORT;
  2098. static int
  2099. svsort_cmp(const void *x, const void *y)
  2100. {
  2101. return ((SVSORT*)x)->cmp_fn(slapi_value_get_berval(((SVSORT*)x)->data),
  2102. slapi_value_get_berval(((SVSORT*)y)->data));
  2103. }
  2104. static int
  2105. bvals_strcasecmp(const struct berval *a, const struct berval *b)
  2106. {
  2107. return strcasecmp(a->bv_val, b->bv_val);
  2108. }
  2109. /* a - b = c */
  2110. /* the returned array of Slapi_Value needs to be freed. */
  2111. static Slapi_Value **
  2112. valuearray_minus_valuearray(
  2113. const Slapi_Attr *sattr,
  2114. Slapi_Value **a,
  2115. Slapi_Value **b
  2116. )
  2117. {
  2118. int rc, i, j, k, acnt, bcnt;
  2119. SVSORT *atmp = NULL, *btmp = NULL;
  2120. Slapi_Value **c;
  2121. value_compare_fn_type cmp_fn;
  2122. /* get berval comparison function */
  2123. attr_get_value_cmp_fn(sattr, &cmp_fn);
  2124. if (cmp_fn == NULL) {
  2125. cmp_fn = (value_compare_fn_type)bvals_strcasecmp;
  2126. }
  2127. /* determine length of a */
  2128. for (acnt = 0; a && a[acnt] != NULL; acnt++);
  2129. /* determine length of b */
  2130. for (bcnt = 0; b && b[bcnt] != NULL; bcnt++);
  2131. /* allocate return array as big as a */
  2132. c = (Slapi_Value**)slapi_ch_calloc(acnt+1, sizeof(Slapi_Value*));
  2133. if (acnt == 0) return c;
  2134. /* sort a */
  2135. atmp = (SVSORT*) slapi_ch_malloc(acnt*sizeof(SVSORT));
  2136. for (i = 0; i < acnt; i++) {
  2137. atmp[i].cmp_fn = cmp_fn;
  2138. atmp[i].data = a[i];
  2139. }
  2140. qsort((void*)atmp, acnt, (size_t)sizeof(SVSORT), svsort_cmp);
  2141. /* sort b */
  2142. if (bcnt > 0) {
  2143. btmp = (SVSORT*) slapi_ch_malloc(bcnt*sizeof(SVSORT));
  2144. for (i = 0; i < bcnt; i++) {
  2145. btmp[i].cmp_fn = cmp_fn;
  2146. btmp[i].data = b[i];
  2147. }
  2148. qsort((void*)btmp, bcnt, (size_t)sizeof(SVSORT), svsort_cmp);
  2149. }
  2150. /* lock step through a and b */
  2151. for (i = 0, j = 0, k = 0; i < acnt && j < bcnt; ) {
  2152. rc = svsort_cmp(&atmp[i], &btmp[j]);
  2153. if (rc == 0) {
  2154. i++;
  2155. } else if (rc < 0) {
  2156. c[k++] = slapi_value_new_value(atmp[i++].data);
  2157. } else {
  2158. j++;
  2159. }
  2160. }
  2161. /* copy what's left from a */
  2162. while (i < acnt) {
  2163. c[k++] = slapi_value_new_value(atmp[i++].data);
  2164. }
  2165. /* clean up */
  2166. slapi_ch_free((void**)&atmp);
  2167. if (btmp) slapi_ch_free((void**)&btmp);
  2168. return c;
  2169. }
  2170. /*
  2171. * Find the most specific match for the given index type, flags, and value, and return the allids value
  2172. * for that match. The priority is as follows, from highest to lowest:
  2173. * * match type, flags, value
  2174. * * match type, value
  2175. * * match type, flags
  2176. * * match type
  2177. * * match flags
  2178. * Note that for value to match, the type must be one that supports values e.g. eq or sub, so that
  2179. * in order for value to match, there must be a type
  2180. * For example, if you have
  2181. * dn: cn=objectclass,...
  2182. * objectclass: nsIndex
  2183. * nsIndexType: eq
  2184. * nsIndexIDListScanLimit: limit=0 type=eq flags=AND value=inetOrgPerson
  2185. * nsIndexIDListScanLimit: limit=1 type=eq value=inetOrgPerson
  2186. * nsIndexIDListScanLimit: limit=2 type=eq flags=AND
  2187. * nsIndexIDListScanLimit: limit=3 type=eq
  2188. * nsIndexIDListScanLimit: limit=4 flags=AND
  2189. * nsIndexIDListScanLimit: limit=5
  2190. * If the search filter is (&(objectclass=inetOrgPerson)(uid=foo)) then the limit=0 because all
  2191. * 3 of type, flags, and value match
  2192. * If the search filter is (objectclass=inetOrgPerson) then the limit=1 because type and value match
  2193. * but flag does not
  2194. * If the search filter is (&(objectclass=posixAccount)(uid=foo)) the the limit=2 because type and
  2195. * flags match
  2196. * If the search filter is (objectclass=posixAccount) then the limit=3 because only the type matches
  2197. * If the search filter is (&(objectclass=*account*)(objectclass=*)) then the limit=4 because only
  2198. * flags match but not the types (sub and pres)
  2199. * If the search filter is (objectclass=*account*) then the limit=5 because only the attribute matches
  2200. * but none of flags, type, or value matches
  2201. */
  2202. #define AI_HAS_VAL 0x04
  2203. #define AI_HAS_TYPE 0x02
  2204. #define AI_HAS_FLAG 0x01
  2205. static int
  2206. index_get_allids( int *allids, const char *indextype, struct attrinfo *ai, const struct berval *val, unsigned int flags )
  2207. {
  2208. int found = 0;
  2209. Slapi_Value sval;
  2210. struct index_idlistsizeinfo *iter; /* iterator */
  2211. int cookie = 0;
  2212. int best_score = 0;
  2213. struct index_idlistsizeinfo *best_match = NULL;
  2214. if (!ai->ai_idlistinfo) {
  2215. return found;
  2216. }
  2217. if (val) { /* val should already be a Slapi_Value, but some paths do not use Slapi_Value */
  2218. sval.bv.bv_val = val->bv_val;
  2219. sval.bv.bv_len = val->bv_len;
  2220. sval.v_csnset = NULL;
  2221. sval.v_flags = SLAPI_ATTR_FLAG_NORMALIZED; /* the value must be a normalized key */
  2222. }
  2223. /* loop through all of the idlistinfo objects to find the best match */
  2224. for (iter = (struct index_idlistsizeinfo *)dl_get_first(ai->ai_idlistinfo, &cookie); iter;
  2225. iter = (struct index_idlistsizeinfo *)dl_get_next(ai->ai_idlistinfo, &cookie)) {
  2226. int iter_score = 0;
  2227. if (iter->ai_indextype != 0) { /* info defines a type which must match */
  2228. if (is_indexed(indextype, iter->ai_indextype, ai->ai_index_rules)) {
  2229. iter_score |= AI_HAS_TYPE;
  2230. } else {
  2231. continue; /* does not match, go to next one */
  2232. }
  2233. }
  2234. if (iter->ai_flags != 0) {
  2235. if (flags & iter->ai_flags) {
  2236. iter_score |= AI_HAS_FLAG;
  2237. } else {
  2238. continue; /* does not match, go to next one */
  2239. }
  2240. }
  2241. if (iter->ai_values != NULL) {
  2242. if ((val != NULL) && slapi_valueset_find(&ai->ai_sattr, iter->ai_values, &sval)) {
  2243. iter_score |= AI_HAS_VAL;
  2244. } else {
  2245. continue; /* does not match, go to next one */
  2246. }
  2247. }
  2248. if (iter_score >= best_score) {
  2249. best_score = iter_score;
  2250. best_match = iter;
  2251. }
  2252. }
  2253. if (best_match) {
  2254. *allids = best_match->ai_idlistsizelimit;
  2255. found = 1; /* found a match */
  2256. }
  2257. return found;
  2258. }