index.c 66 KB

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