index.c 74 KB

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