valueset.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  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. /* valueset.c - routines for dealing with value sets */
  39. #include "slap.h"
  40. #include "slapi-private.h"
  41. /* <=========================== Berval Array ==========================> */
  42. /*
  43. * vals - The existing values.
  44. * addval - The value to add.
  45. * nvals - The number of existing values.
  46. * maxvals - The number of elements in the existing values array.
  47. */
  48. void
  49. bervalarray_add_berval_fast(
  50. struct berval ***vals,
  51. const struct berval *addval,
  52. int nvals,
  53. int *maxvals
  54. )
  55. {
  56. int need = nvals + 2;
  57. if(need>*maxvals)
  58. {
  59. if (*maxvals==0)
  60. {
  61. *maxvals = 2;
  62. }
  63. while ( *maxvals < need )
  64. {
  65. *maxvals *= 2;
  66. }
  67. if(*vals==NULL)
  68. {
  69. *vals = (struct berval **) slapi_ch_malloc( *maxvals * sizeof(struct berval *));
  70. }
  71. else
  72. {
  73. *vals = (struct berval **) slapi_ch_realloc( (char *) *vals, *maxvals * sizeof(struct berval *));
  74. }
  75. }
  76. (*vals)[nvals] = ber_bvdup( (struct berval *)addval );
  77. (*vals)[nvals+1] = NULL;
  78. }
  79. /* <=========================== Value Array ==========================> */
  80. /*
  81. * vals - The existing values.
  82. * addval - The value to add.
  83. * nvals - The number of existing values.
  84. * maxvals - The number of elements in the existing values array.
  85. */
  86. void
  87. valuearray_add_value_fast(Slapi_Value ***vals,
  88. Slapi_Value *addval,
  89. int nvals,
  90. int *maxvals,
  91. int exact, /* Don't create an array bigger than needed */
  92. int passin) /* The values are being passed in */
  93. {
  94. Slapi_Value *oneval[2];
  95. oneval[0]= addval;
  96. oneval[1]= NULL;
  97. valuearray_add_valuearray_fast(vals,oneval,nvals,1,maxvals,exact,passin);
  98. }
  99. void
  100. valuearray_add_valuearray_fast(Slapi_Value ***vals,
  101. Slapi_Value **addvals,
  102. int nvals,
  103. int naddvals,
  104. int *maxvals,
  105. int exact, /* Don't create an array bigger than needed */
  106. int passin) /* The values are being passed in */
  107. {
  108. int i, j;
  109. int allocate= 0;
  110. int need = nvals + naddvals + 1;
  111. if(exact)
  112. {
  113. /* Create an array exactly the right size. */
  114. if(need>*maxvals)
  115. {
  116. allocate= need;
  117. }
  118. }
  119. else
  120. {
  121. if (*maxvals==0) /* empty; create with 4 by default */
  122. {
  123. allocate= 4;
  124. }
  125. else if (need > *maxvals)
  126. {
  127. /* Exponentially expand the array */
  128. allocate= *maxvals;
  129. while ( allocate < need )
  130. {
  131. allocate *= 2;
  132. }
  133. }
  134. }
  135. if(allocate>0)
  136. {
  137. if(*vals==NULL)
  138. {
  139. *vals = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *));
  140. }
  141. else
  142. {
  143. *vals = (Slapi_Value **) slapi_ch_realloc( (char *) *vals, allocate * sizeof(Slapi_Value *));
  144. }
  145. *maxvals= allocate;
  146. }
  147. for ( i = 0, j = 0; i < naddvals; i++)
  148. {
  149. if ( addvals[i]!=NULL )
  150. {
  151. if(passin)
  152. {
  153. /* We consume the values */
  154. (*vals)[nvals + j] = addvals[i];
  155. }
  156. else
  157. {
  158. /* We copy the values */
  159. (*vals)[nvals + j] = slapi_value_dup(addvals[i]);
  160. }
  161. j++;
  162. }
  163. }
  164. (*vals)[nvals + j] = NULL;
  165. }
  166. void
  167. valuearray_add_value(Slapi_Value ***vals, const Slapi_Value *addval)
  168. {
  169. Slapi_Value *oneval[2];
  170. oneval[0]= (Slapi_Value*)addval;
  171. oneval[1]= NULL;
  172. valuearray_add_valuearray(vals,oneval,0);
  173. }
  174. void
  175. valuearray_add_valuearray(Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags)
  176. {
  177. int valslen;
  178. int addvalslen;
  179. int maxvals;
  180. addvalslen= valuearray_count(addvals);
  181. if(*vals == NULL)
  182. {
  183. valslen= 0;
  184. maxvals= 0;
  185. }
  186. else
  187. {
  188. valslen= valuearray_count(*vals);
  189. maxvals= valslen+1;
  190. }
  191. valuearray_add_valuearray_fast(vals,addvals,valslen,addvalslen,&maxvals,1/*Exact*/,flags & SLAPI_VALUE_FLAG_PASSIN);
  192. }
  193. int
  194. valuearray_count( Slapi_Value **va)
  195. {
  196. int i=0;
  197. if(va!=NULL)
  198. {
  199. while(NULL != va[i]) i++;
  200. }
  201. return(i);
  202. }
  203. int
  204. valuearray_isempty( Slapi_Value **va)
  205. {
  206. return va==NULL || va[0]==NULL;
  207. }
  208. /*
  209. * JCM SLOW FUNCTION
  210. *
  211. * WARNING: Use only if you absolutley need to...
  212. * This function mostly exists to map from the old slapi berval
  213. * based interface to the new Slapi_Value based interfaces.
  214. */
  215. int
  216. valuearray_init_bervalarray(struct berval **bvals, Slapi_Value ***cvals)
  217. {
  218. int n;
  219. for(n=0; bvals != NULL && bvals[n] != NULL; n++);
  220. if(n==0)
  221. {
  222. *cvals = NULL;
  223. }
  224. else
  225. {
  226. int i;
  227. *cvals = (Slapi_Value **) slapi_ch_malloc((n + 1) * sizeof(Slapi_Value *));
  228. for(i=0;i<n;i++)
  229. {
  230. (*cvals)[i] = slapi_value_new_berval(bvals[i]);
  231. }
  232. (*cvals)[i] = NULL;
  233. }
  234. return n;
  235. }
  236. /*
  237. * JCM SLOW FUNCTION
  238. *
  239. * Use only if you absolutley need to...
  240. * This function mostly exists to map from the old slapi berval
  241. * based interface to the new Slapi_Value based interfaces.
  242. */
  243. int
  244. valuearray_get_bervalarray(Slapi_Value **cvals,struct berval ***bvals)
  245. {
  246. int i,n;
  247. n= valuearray_count(cvals);
  248. if (0 == n)
  249. {
  250. *bvals = NULL;
  251. }
  252. else
  253. {
  254. *bvals = (struct berval **)slapi_ch_malloc((n + 1) * sizeof(struct berval *));
  255. for(i=0;i<n;i++)
  256. {
  257. (*bvals)[i] = ber_bvdup(slapi_value_get_berval(cvals[i]));
  258. }
  259. (*bvals)[i] = NULL;
  260. }
  261. return(0);
  262. }
  263. void
  264. valuearray_free(Slapi_Value ***va)
  265. {
  266. if(va!=NULL && *va!=NULL)
  267. {
  268. int i;
  269. for(i=0; (*va)[i]!=NULL; i++)
  270. {
  271. slapi_value_free(&(*va)[i]);
  272. }
  273. slapi_ch_free((void **)va);
  274. *va = NULL;
  275. }
  276. }
  277. int
  278. valuearray_next_value( Slapi_Value **va, int index, Slapi_Value **v)
  279. {
  280. int r= -1;
  281. if(va!=NULL && va[0]!=NULL)
  282. {
  283. r= index+1;
  284. *v= va[r];
  285. if(*v==NULL)
  286. {
  287. r= -1;
  288. }
  289. }
  290. else
  291. {
  292. *v= NULL;
  293. }
  294. return r;
  295. }
  296. int
  297. valuearray_first_value( Slapi_Value **va, Slapi_Value **v )
  298. {
  299. return valuearray_next_value( va, -1, v);
  300. }
  301. /*
  302. * Find the value and return an index number to it.
  303. */
  304. int
  305. valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
  306. {
  307. int i= 0;
  308. int found= -1;
  309. while(found==-1 && va!=NULL && va[i]!=NULL)
  310. {
  311. if(slapi_value_compare( a, v, va[i])==0)
  312. {
  313. found= i;
  314. }
  315. else
  316. {
  317. i++;
  318. }
  319. }
  320. return found;
  321. }
  322. /*
  323. * Shunt up the array to cover the value to remove.
  324. */
  325. void
  326. valuearray_remove_value_atindex(Slapi_Value **va, int index)
  327. {
  328. if(va!=NULL && va[0]!=NULL)
  329. {
  330. int k;
  331. for ( k = index + 1; va[k] != NULL; k++ )
  332. {
  333. va[k - 1] = va[k];
  334. }
  335. va[k - 1] = NULL;
  336. }
  337. }
  338. /*
  339. * Find the value in the array,
  340. * shunt up the array to cover it,
  341. * return a ptr to the value.
  342. */
  343. Slapi_Value *
  344. valuearray_remove_value(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v)
  345. {
  346. Slapi_Value *r= NULL;
  347. int i= 0;
  348. i= valuearray_find(a, va, v);
  349. if(i!=-1)
  350. {
  351. r= va[i];
  352. valuearray_remove_value_atindex(va,i);
  353. }
  354. return r;
  355. }
  356. /*
  357. * Remove any values older than the CSN.
  358. */
  359. int
  360. valuearray_purge(Slapi_Value ***va, const CSN *csn)
  361. {
  362. int numValues=0;
  363. int i=0;
  364. int nextValue=0;
  365. PR_ASSERT(va!=NULL && *va!=NULL);
  366. /* Loop over all the values freeing the old ones. */
  367. for(i=0; (*va)[i]; i++)
  368. {
  369. csnset_purge(&((*va)[i]->v_csnset),csn);
  370. if ((*va)[i]->v_csnset == NULL)
  371. {
  372. slapi_value_free(&(*va)[i]);
  373. (*va)[i] = NULL;
  374. }
  375. }
  376. /* Now compact the value list. */
  377. numValues=i;
  378. nextValue = 0;
  379. i = 0;
  380. for(i=0;i<numValues;i++)
  381. {
  382. while((nextValue < numValues) && (NULL == (*va)[nextValue]))
  383. {
  384. nextValue++;
  385. }
  386. if(nextValue < numValues)
  387. {
  388. (*va)[i] = (*va)[nextValue];
  389. nextValue++;
  390. }
  391. else
  392. {
  393. break;
  394. }
  395. }
  396. (*va)[i] = NULL;
  397. /* All the values were deleted, we can discard the whole array. */
  398. if(NULL == (*va)[0])
  399. {
  400. slapi_ch_free((void**)va);
  401. *va= NULL;
  402. }
  403. return(0);
  404. }
  405. size_t
  406. valuearray_size(Slapi_Value **va)
  407. {
  408. size_t s= 0;
  409. if(va!=NULL && va[0]!=NULL)
  410. {
  411. int i;
  412. for (i = 0; va[i]; i++)
  413. {
  414. s += value_size(va[i]);
  415. }
  416. s += (i + 1) * sizeof(Slapi_Value*);
  417. }
  418. return s;
  419. }
  420. void
  421. valuearray_update_csn(Slapi_Value **va, CSNType t, const CSN *csn)
  422. {
  423. int i;
  424. for (i = 0; va!=NULL && va[i]; i++)
  425. {
  426. value_update_csn(va[i],t,csn);
  427. }
  428. }
  429. /*
  430. * Shunt up the values to cover the empty slots.
  431. *
  432. * "compressed" means "contains no NULL's"
  433. *
  434. * Invariant for the outer loop:
  435. * va[0..i] is compressed &&
  436. * va[n..numvalues] contains just NULL's
  437. *
  438. * Invariant for the inner loop:
  439. * i<j<=k<=n && va[j..k] has been shifted left by (j-i) places &&
  440. * va[k..n] remains to be shifted left by (j-i) places
  441. *
  442. */
  443. void
  444. valuearray_compress(Slapi_Value **va,int numvalues)
  445. {
  446. int i = 0;
  447. int n= numvalues;
  448. while(i<n)
  449. {
  450. if ( va[i] != NULL ) {
  451. i++;
  452. } else {
  453. int k,j;
  454. j = i + 1;
  455. /* Find the length of the next run of NULL's */
  456. while( j<n && va[j] == NULL) { j++; }
  457. /* va[i..j] is all NULL && j<= n */
  458. for ( k = j; k<n; k++ )
  459. {
  460. va[k - (j-i)] = va[k];
  461. va[k] = NULL;
  462. }
  463. /* va[i..n] has been shifted down by j-i places */
  464. n = n - (j-i);
  465. /*
  466. * If va[i] in now non null, then bump i,
  467. * if not then we are done anyway (j==n) so can bump it.
  468. */
  469. i++;
  470. }
  471. }
  472. }
  473. /* <=========================== Value Array Fast ==========================> */
  474. void
  475. valuearrayfast_init(struct valuearrayfast *vaf,Slapi_Value **va)
  476. {
  477. vaf->num= valuearray_count(va);
  478. vaf->max= vaf->num;
  479. vaf->va= va;
  480. }
  481. void
  482. valuearrayfast_done(struct valuearrayfast *vaf)
  483. {
  484. if(vaf->va!=NULL)
  485. {
  486. int i;
  487. for(i=0; i<vaf->num; i++)
  488. {
  489. slapi_value_free(&vaf->va[i]);
  490. }
  491. slapi_ch_free((void **)&vaf->va);
  492. vaf->num= 0;
  493. vaf->max= 0;
  494. }
  495. }
  496. void
  497. valuearrayfast_add_value(struct valuearrayfast *vaf,const Slapi_Value *v)
  498. {
  499. valuearray_add_value_fast(&vaf->va,(Slapi_Value *)v,vaf->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
  500. vaf->num++;
  501. }
  502. void
  503. valuearrayfast_add_value_passin(struct valuearrayfast *vaf,Slapi_Value *v)
  504. {
  505. valuearray_add_value_fast(&vaf->va,v,vaf->num,&vaf->max,0/*Exact*/,1/*PassIn*/);
  506. vaf->num++;
  507. }
  508. void
  509. valuearrayfast_add_valuearrayfast(struct valuearrayfast *vaf,const struct valuearrayfast *vaf_add)
  510. {
  511. valuearray_add_valuearray_fast(&vaf->va,vaf_add->va,vaf->num,vaf_add->num,&vaf->max,0/*Exact*/,0/*!PassIn*/);
  512. vaf->num+= vaf_add->num;
  513. }
  514. /* <=========================== ValueArrayIndexTree =======================> */
  515. static int valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 );
  516. static int valuetree_node_cmp( caddr_t d1, caddr_t d2 );
  517. static int valuetree_node_free( caddr_t data );
  518. /*
  519. * structure used within AVL value trees.
  520. */
  521. typedef struct valuetree_node
  522. {
  523. int index; /* index into the value array */
  524. Slapi_Value *sval; /* the actual value */
  525. } valuetree_node;
  526. /*
  527. * Create or update an AVL tree of values that can be used to speed up value
  528. * lookups. We store the index keys for the values in the AVL tree so
  529. * we can use a trivial comparison function.
  530. *
  531. * Returns:
  532. * LDAP_SUCCESS on success,
  533. * LDAP_TYPE_OR_VALUE_EXISTS if the value already exists,
  534. * LDAP_OPERATIONS_ERROR for some unexpected failure.
  535. *
  536. * Sets *valuetreep to the root of the AVL tree that was created. If a
  537. * non-zero value is returned, the tree is freed if free_on_error is non-zero
  538. * and *valuetreep is set to NULL.
  539. */
  540. int
  541. valuetree_add_valuearray( const char *type, struct slapdplugin *pi, Slapi_Value **va, Avlnode **valuetreep, int *duplicate_index )
  542. {
  543. int rc= LDAP_SUCCESS;
  544. PR_ASSERT(type!=NULL);
  545. PR_ASSERT(pi!=NULL);
  546. PR_ASSERT(valuetreep!=NULL);
  547. if ( duplicate_index ) {
  548. *duplicate_index = -1;
  549. }
  550. if ( !valuearray_isempty(va) )
  551. {
  552. Slapi_Value **keyvals;
  553. /* Convert the value array into key values */
  554. if ( slapi_call_syntax_values2keys_sv( pi, (Slapi_Value**)va, &keyvals, LDAP_FILTER_EQUALITY ) != 0 ) /* jcm cast */
  555. {
  556. LDAPDebug( LDAP_DEBUG_ANY,"slapi_call_syntax_values2keys for attribute %s failed\n", type, 0, 0 );
  557. rc= LDAP_OPERATIONS_ERROR;
  558. }
  559. else
  560. {
  561. int i;
  562. valuetree_node *vaip;
  563. for ( i = 0; rc==LDAP_SUCCESS && va[i] != NULL; ++i )
  564. {
  565. if ( keyvals[i] == NULL )
  566. {
  567. LDAPDebug( LDAP_DEBUG_ANY,"slapi_call_syntax_values2keys for attribute %s did not return enough key values\n", type, 0, 0 );
  568. rc= LDAP_OPERATIONS_ERROR;
  569. }
  570. else
  571. {
  572. vaip = (valuetree_node *)slapi_ch_malloc( sizeof( valuetree_node ));
  573. vaip->index = i;
  574. vaip->sval = keyvals[i];
  575. if (( rc = avl_insert( valuetreep, vaip, valuetree_node_cmp, valuetree_dupvalue_disallow )) != 0 )
  576. {
  577. slapi_ch_free( (void **)&vaip );
  578. /* Value must already be in there */
  579. rc= LDAP_TYPE_OR_VALUE_EXISTS;
  580. if ( duplicate_index ) {
  581. *duplicate_index = i;
  582. }
  583. }
  584. else
  585. {
  586. keyvals[i]= NULL;
  587. }
  588. }
  589. }
  590. valuearray_free( &keyvals );
  591. }
  592. }
  593. if(rc!=0)
  594. {
  595. valuetree_free( valuetreep );
  596. }
  597. return rc;
  598. }
  599. int
  600. valuetree_add_value( const char *type, struct slapdplugin *pi, const Slapi_Value *v, Avlnode **valuetreep)
  601. {
  602. Slapi_Value *va[2];
  603. va[0]= (Slapi_Value*)v;
  604. va[1]= NULL;
  605. return valuetree_add_valuearray( type, pi, va, valuetreep, NULL);
  606. }
  607. /*
  608. *
  609. * Find value "v" using AVL tree "valuetree"
  610. *
  611. * returns LDAP_SUCCESS if "v" was found, LDAP_NO_SUCH_ATTRIBUTE
  612. * if "v" was not found and LDAP_OPERATIONS_ERROR if some unexpected error occurs.
  613. */
  614. static int
  615. valuetree_find( const struct slapi_attr *a, const Slapi_Value *v, Avlnode *valuetree, int *index)
  616. {
  617. const Slapi_Value *oneval[2];
  618. Slapi_Value **keyvals;
  619. valuetree_node *vaip, tmpvain;
  620. PR_ASSERT(a!=NULL);
  621. PR_ASSERT(a->a_plugin!=NULL);
  622. PR_ASSERT(v!=NULL);
  623. PR_ASSERT(valuetree!=NULL);
  624. PR_ASSERT(index!=NULL);
  625. if ( a == NULL || a->a_plugin == NULL || v == NULL || valuetree == NULL )
  626. {
  627. return( LDAP_OPERATIONS_ERROR );
  628. }
  629. keyvals = NULL;
  630. oneval[0] = v;
  631. oneval[1] = NULL;
  632. if ( slapi_call_syntax_values2keys_sv( a->a_plugin, (Slapi_Value**)oneval, &keyvals, LDAP_FILTER_EQUALITY ) != 0 /* jcm cast */
  633. || keyvals == NULL
  634. || keyvals[0] == NULL )
  635. {
  636. LDAPDebug( LDAP_DEBUG_ANY, "valuetree_find_and_replace: "
  637. "slapi_call_syntax_values2keys failed for type %s\n",
  638. a->a_type, 0, 0 );
  639. return( LDAP_OPERATIONS_ERROR );
  640. }
  641. tmpvain.index = 0;
  642. tmpvain.sval = keyvals[0];
  643. vaip = (valuetree_node *)avl_find( valuetree, &tmpvain, valuetree_node_cmp );
  644. if ( keyvals != NULL )
  645. {
  646. valuearray_free( &keyvals );
  647. }
  648. if (vaip == NULL)
  649. {
  650. return( LDAP_NO_SUCH_ATTRIBUTE );
  651. }
  652. else
  653. {
  654. *index= vaip->index;
  655. }
  656. return( LDAP_SUCCESS );
  657. }
  658. static int
  659. valuetree_dupvalue_disallow( caddr_t d1, caddr_t d2 )
  660. {
  661. return( 1 );
  662. }
  663. void
  664. valuetree_free( Avlnode **valuetreep )
  665. {
  666. if ( valuetreep != NULL && *valuetreep != NULL )
  667. {
  668. avl_free( *valuetreep, valuetree_node_free );
  669. *valuetreep = NULL;
  670. }
  671. }
  672. static int
  673. valuetree_node_free( caddr_t data )
  674. {
  675. if ( data!=NULL )
  676. {
  677. valuetree_node *vaip = (valuetree_node *)data;
  678. slapi_value_free(&vaip->sval);
  679. slapi_ch_free( (void **)&data );
  680. }
  681. return( 0 );
  682. }
  683. static int
  684. valuetree_node_cmp( caddr_t d1, caddr_t d2 )
  685. {
  686. const struct berval *bv1, *bv2;
  687. int rc;
  688. bv1 = slapi_value_get_berval(((valuetree_node *)d1)->sval);
  689. bv2 = slapi_value_get_berval(((valuetree_node *)d2)->sval);
  690. if ( bv1->bv_len < bv2->bv_len ) {
  691. rc = -1;
  692. } else if ( bv1->bv_len > bv2->bv_len ) {
  693. rc = 1;
  694. } else {
  695. rc = memcmp( bv1->bv_val, bv2->bv_val, bv1->bv_len );
  696. }
  697. return( rc );
  698. }
  699. /* <=========================== Value Set =======================> */
  700. /*
  701. * JCM: All of these valueset functions are just forwarded to the
  702. * JCM: valuearray functions... waste of time. Inline them!
  703. */
  704. Slapi_ValueSet *
  705. slapi_valueset_new()
  706. {
  707. Slapi_ValueSet *vs = (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
  708. if(vs)
  709. slapi_valueset_init(vs);
  710. return vs;
  711. }
  712. void
  713. slapi_valueset_init(Slapi_ValueSet *vs)
  714. {
  715. if(vs!=NULL)
  716. {
  717. vs->va= NULL;
  718. }
  719. }
  720. void
  721. slapi_valueset_done(Slapi_ValueSet *vs)
  722. {
  723. if(vs!=NULL)
  724. {
  725. if(vs->va!=NULL)
  726. {
  727. valuearray_free(&vs->va);
  728. vs->va= NULL;
  729. }
  730. }
  731. }
  732. void
  733. slapi_valueset_free(Slapi_ValueSet *vs)
  734. {
  735. if(vs!=NULL)
  736. {
  737. slapi_valueset_done(vs);
  738. slapi_ch_free((void **)&vs);
  739. }
  740. }
  741. void
  742. slapi_valueset_set_from_smod(Slapi_ValueSet *vs, Slapi_Mod *smod)
  743. {
  744. Slapi_Value **va= NULL;
  745. valuearray_init_bervalarray(slapi_mod_get_ldapmod_byref(smod)->mod_bvalues, &va);
  746. valueset_set_valuearray_passin(vs, va);
  747. }
  748. void
  749. valueset_set_valuearray_byval(Slapi_ValueSet *vs, Slapi_Value **addvals)
  750. {
  751. slapi_valueset_init(vs);
  752. valueset_add_valuearray(vs,addvals);
  753. }
  754. void
  755. valueset_set_valuearray_passin(Slapi_ValueSet *vs, Slapi_Value **addvals)
  756. {
  757. slapi_valueset_init(vs);
  758. vs->va= addvals;
  759. }
  760. void
  761. slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
  762. {
  763. slapi_valueset_init(vs1);
  764. valueset_add_valueset(vs1,vs2);
  765. }
  766. int
  767. slapi_valueset_first_value( Slapi_ValueSet *vs, Slapi_Value **v )
  768. {
  769. return valuearray_first_value(vs->va,v);
  770. }
  771. int
  772. slapi_valueset_next_value( Slapi_ValueSet *vs, int index, Slapi_Value **v)
  773. {
  774. return valuearray_next_value(vs->va,index,v);
  775. }
  776. int
  777. slapi_valueset_count( const Slapi_ValueSet *vs)
  778. {
  779. int r=0;
  780. if (NULL != vs)
  781. {
  782. if(!valuearray_isempty(vs->va))
  783. {
  784. r= valuearray_count(vs->va);
  785. }
  786. }
  787. return r;
  788. }
  789. int
  790. valueset_isempty( const Slapi_ValueSet *vs)
  791. {
  792. return valuearray_isempty(vs->va);
  793. }
  794. Slapi_Value *
  795. slapi_valueset_find(const Slapi_Attr *a, const Slapi_ValueSet *vs, const Slapi_Value *v)
  796. {
  797. Slapi_Value *r= NULL;
  798. if(!valuearray_isempty(vs->va))
  799. {
  800. int i= valuearray_find(a,vs->va,v);
  801. if(i!=-1)
  802. {
  803. r= vs->va[i];
  804. }
  805. }
  806. return r;
  807. }
  808. /*
  809. * The value is found in the set, removed and returned.
  810. * The caller is responsible for freeing the value.
  811. */
  812. Slapi_Value *
  813. valueset_remove_value(const Slapi_Attr *a, Slapi_ValueSet *vs, const Slapi_Value *v)
  814. {
  815. Slapi_Value *r= NULL;
  816. if(!valuearray_isempty(vs->va))
  817. {
  818. r= valuearray_remove_value(a, vs->va, v);
  819. }
  820. return r;
  821. }
  822. /*
  823. * Remove any values older than the CSN.
  824. */
  825. int
  826. valueset_purge(Slapi_ValueSet *vs, const CSN *csn)
  827. {
  828. int r= 0;
  829. if(!valuearray_isempty(vs->va))
  830. {
  831. r= valuearray_purge(&vs->va, csn);
  832. }
  833. return r;
  834. }
  835. Slapi_Value **
  836. valueset_get_valuearray(const Slapi_ValueSet *vs)
  837. {
  838. return (Slapi_Value**)vs->va;
  839. }
  840. size_t
  841. valueset_size(const Slapi_ValueSet *vs)
  842. {
  843. size_t s= 0;
  844. if(!valuearray_isempty(vs->va))
  845. {
  846. s= valuearray_size(vs->va);
  847. }
  848. return s;
  849. }
  850. /*
  851. * The value array is passed in by value.
  852. */
  853. void
  854. valueset_add_valuearray(Slapi_ValueSet *vs, Slapi_Value **addvals)
  855. {
  856. if(!valuearray_isempty(addvals))
  857. {
  858. valuearray_add_valuearray(&vs->va, addvals, 0);
  859. }
  860. }
  861. void
  862. valueset_add_valuearray_ext(Slapi_ValueSet *vs, Slapi_Value **addvals, PRUint32 flags)
  863. {
  864. if(!valuearray_isempty(addvals))
  865. {
  866. valuearray_add_valuearray(&vs->va, addvals, flags);
  867. }
  868. }
  869. /*
  870. * The value is passed in by value.
  871. */
  872. void
  873. slapi_valueset_add_value(Slapi_ValueSet *vs, const Slapi_Value *addval)
  874. {
  875. valuearray_add_value(&vs->va,addval);
  876. }
  877. void
  878. slapi_valueset_add_value_ext(Slapi_ValueSet *vs, Slapi_Value *addval, unsigned long flags)
  879. {
  880. Slapi_Value *oneval[2];
  881. oneval[0]= (Slapi_Value*)addval;
  882. oneval[1]= NULL;
  883. valuearray_add_valuearray(&vs->va, oneval, flags);
  884. }
  885. /*
  886. * The string is passed in by value.
  887. */
  888. void
  889. valueset_add_string(Slapi_ValueSet *vs, const char *s, CSNType t, const CSN *csn)
  890. {
  891. Slapi_Value v;
  892. value_init(&v,NULL,t,csn);
  893. slapi_value_set_string(&v,s);
  894. valuearray_add_value(&vs->va,&v);
  895. value_done(&v);
  896. }
  897. /*
  898. * The value set is passed in by value.
  899. */
  900. void
  901. valueset_add_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2)
  902. {
  903. if (vs1 && vs2)
  904. valueset_add_valuearray(vs1, vs2->va);
  905. }
  906. void
  907. valueset_remove_string(const Slapi_Attr *a, Slapi_ValueSet *vs, const char *s)
  908. {
  909. Slapi_Value v;
  910. value_init(&v,NULL,CSN_TYPE_NONE,NULL);
  911. slapi_value_set_string(&v,s);
  912. valuearray_remove_value(a,vs->va,&v);
  913. value_done(&v);
  914. }
  915. void
  916. valueset_update_csn(Slapi_ValueSet *vs, CSNType t, const CSN *csn)
  917. {
  918. if(!valuearray_isempty(vs->va))
  919. {
  920. valuearray_update_csn(vs->va,t,csn);
  921. }
  922. }
  923. /*
  924. * If we are adding or deleting SLAPD_MODUTIL_TREE_THRESHHOLD or more
  925. * entries, we use an AVL tree to speed up searching for duplicates or
  926. * values we are trying to delete. This threshhold is somewhat arbitrary;
  927. * we should really take some measurements to determine an optimal number.
  928. */
  929. #define SLAPD_MODUTIL_TREE_THRESHHOLD 5
  930. /*
  931. * Remove an array of values from a value set.
  932. * The removed values are passed back in an array.
  933. *
  934. * Returns
  935. * LDAP_SUCCESS - OK.
  936. * LDAP_NO_SUCH_ATTRIBUTE - A value to be deleted was not in the value set.
  937. * LDAP_OPERATIONS_ERROR - Something very bad happened.
  938. */
  939. int
  940. valueset_remove_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestodelete, int flags, Slapi_Value ***va_out)
  941. {
  942. int rc= LDAP_SUCCESS;
  943. if(!valuearray_isempty(vs->va))
  944. {
  945. int numberofvaluestodelete= valuearray_count(valuestodelete);
  946. struct valuearrayfast vaf_out;
  947. if ( va_out )
  948. {
  949. valuearrayfast_init(&vaf_out,*va_out);
  950. }
  951. /*
  952. * determine whether we should use an AVL tree of values or not
  953. */
  954. if ( numberofvaluestodelete >= SLAPD_MODUTIL_TREE_THRESHHOLD)
  955. {
  956. /*
  957. * Several values to delete: first build an AVL tree that
  958. * holds all of the existing values and use that to find
  959. * the values we want to delete.
  960. */
  961. Avlnode *vtree = NULL;
  962. int numberofexistingvalues= slapi_valueset_count(vs);
  963. rc= valuetree_add_valuearray( a->a_type, a->a_plugin, vs->va, &vtree, NULL );
  964. if ( rc!=LDAP_SUCCESS )
  965. {
  966. /*
  967. * failed while constructing AVL tree of existing
  968. * values... something bad happened.
  969. */
  970. rc= LDAP_OPERATIONS_ERROR;
  971. }
  972. else
  973. {
  974. int i;
  975. /*
  976. * find and mark all the values that are to be deleted
  977. */
  978. for ( i = 0; rc == LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
  979. {
  980. int index= 0;
  981. rc = valuetree_find( a, valuestodelete[i], vtree, &index );
  982. if(rc==LDAP_SUCCESS)
  983. {
  984. if(vs->va[index]!=NULL)
  985. {
  986. /* Move the value to be removed to the out array */
  987. if ( va_out )
  988. {
  989. if (vs->va[index]->v_csnset && (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET))
  990. {
  991. valuestodelete[i]->v_csnset = csnset_dup (vs->va[index]->v_csnset);
  992. }
  993. valuearrayfast_add_value_passin(&vaf_out,vs->va[index]);
  994. vs->va[index] = NULL;
  995. }
  996. else
  997. {
  998. if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
  999. {
  1000. valuestodelete[i]->v_csnset = vs->va[index]->v_csnset;
  1001. vs->va[index]->v_csnset = NULL;
  1002. }
  1003. slapi_value_free ( & vs->va[index] );
  1004. }
  1005. }
  1006. else
  1007. {
  1008. /* We already deleted this value... */
  1009. if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
  1010. {
  1011. /* ...that's an error. */
  1012. rc= LDAP_NO_SUCH_ATTRIBUTE;
  1013. }
  1014. }
  1015. }
  1016. else
  1017. {
  1018. /* Couldn't find the value to be deleted */
  1019. if(rc==LDAP_NO_SUCH_ATTRIBUTE && (flags & SLAPI_VALUE_FLAG_IGNOREERROR ))
  1020. {
  1021. rc= LDAP_SUCCESS;
  1022. }
  1023. }
  1024. }
  1025. valuetree_free( &vtree );
  1026. if ( rc != LDAP_SUCCESS )
  1027. {
  1028. LDAPDebug( LDAP_DEBUG_ANY,"could not find value %d for attr %s (%s)\n", i-1, a->a_type, ldap_err2string( rc ));
  1029. }
  1030. else
  1031. {
  1032. /* Shunt up all the remaining values to cover the deleted ones. */
  1033. valuearray_compress(vs->va,numberofexistingvalues);
  1034. }
  1035. }
  1036. }
  1037. else
  1038. {
  1039. /* We don't have to delete very many values, so we use brute force. */
  1040. int i;
  1041. for ( i = 0; rc==LDAP_SUCCESS && valuestodelete[i] != NULL; ++i )
  1042. {
  1043. Slapi_Value *found= valueset_remove_value(a, vs, valuestodelete[i]);
  1044. if(found!=NULL)
  1045. {
  1046. if ( va_out )
  1047. {
  1048. if (found->v_csnset && (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET))
  1049. {
  1050. valuestodelete[i]->v_csnset = csnset_dup (found->v_csnset);
  1051. }
  1052. valuearrayfast_add_value_passin(&vaf_out,found);
  1053. }
  1054. else
  1055. {
  1056. if (flags & SLAPI_VALUE_FLAG_PRESERVECSNSET)
  1057. {
  1058. valuestodelete[i]->v_csnset = found->v_csnset;
  1059. found->v_csnset = NULL;
  1060. }
  1061. slapi_value_free ( & found );
  1062. }
  1063. }
  1064. else
  1065. {
  1066. if((flags & SLAPI_VALUE_FLAG_IGNOREERROR) == 0)
  1067. {
  1068. LDAPDebug( LDAP_DEBUG_ARGS,"could not find value %d for attr %s\n", i-1, a->a_type, 0 );
  1069. rc= LDAP_NO_SUCH_ATTRIBUTE;
  1070. }
  1071. }
  1072. }
  1073. }
  1074. if ( va_out )
  1075. {
  1076. *va_out= vaf_out.va;
  1077. if(rc!=LDAP_SUCCESS)
  1078. {
  1079. valuearray_free(va_out);
  1080. }
  1081. }
  1082. }
  1083. return rc;
  1084. }
  1085. /*
  1086. * Check if the set of values in the valueset and the valuearray intersect.
  1087. *
  1088. * Returns
  1089. * LDAP_SUCCESS - No intersection.
  1090. * LDAP_NO_SUCH_ATTRIBUTE - There is an intersection.
  1091. * LDAP_OPERATIONS_ERROR - There are duplicate values in the value set already.
  1092. */
  1093. int
  1094. valueset_intersectswith_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **values, int *duplicate_index )
  1095. {
  1096. int rc= LDAP_SUCCESS;
  1097. if ( duplicate_index ) {
  1098. *duplicate_index = -1;
  1099. }
  1100. if(valuearray_isempty(vs->va))
  1101. {
  1102. /* No intersection */
  1103. }
  1104. else
  1105. {
  1106. int numberofvalues= valuearray_count(values);
  1107. /*
  1108. * determine whether we should use an AVL tree of values or not
  1109. */
  1110. if (numberofvalues==0)
  1111. {
  1112. /* No intersection */
  1113. }
  1114. else if ( numberofvalues >= SLAPD_MODUTIL_TREE_THRESHHOLD)
  1115. {
  1116. /*
  1117. * Several values to add: use an AVL tree to detect duplicates.
  1118. */
  1119. Avlnode *vtree = NULL;
  1120. rc= valuetree_add_valuearray( a->a_type, a->a_plugin, vs->va, &vtree, duplicate_index );
  1121. if(rc==LDAP_OPERATIONS_ERROR)
  1122. {
  1123. /* There were already duplicate values in the value set */
  1124. }
  1125. else
  1126. {
  1127. rc= valuetree_add_valuearray( a->a_type, a->a_plugin, values, &vtree, duplicate_index );
  1128. /*
  1129. * Returns LDAP_OPERATIONS_ERROR if something very bad happens.
  1130. * Or LDAP_TYPE_OR_VALUE_EXISTS if a value already exists.
  1131. */
  1132. }
  1133. valuetree_free( &vtree );
  1134. }
  1135. else
  1136. {
  1137. /*
  1138. * Small number of values to add: don't bother constructing
  1139. * an AVL tree, etc. since it probably isn't worth the time.
  1140. *
  1141. * JCM - This is actually quite slow because the comparison function is looked up many times.
  1142. */
  1143. int i;
  1144. for ( i = 0; rc == LDAP_SUCCESS && values[i] != NULL; ++i )
  1145. {
  1146. if(valuearray_find(a, vs->va, values[i])!=-1)
  1147. {
  1148. rc = LDAP_TYPE_OR_VALUE_EXISTS;
  1149. *duplicate_index = i;
  1150. break;
  1151. }
  1152. }
  1153. }
  1154. }
  1155. return rc;
  1156. }
  1157. Slapi_ValueSet *
  1158. valueset_dup(const Slapi_ValueSet *dupee)
  1159. {
  1160. Slapi_ValueSet *duped= (Slapi_ValueSet *)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
  1161. if (NULL!=duped)
  1162. {
  1163. valueset_add_valuearray( duped, dupee->va );
  1164. }
  1165. return duped;
  1166. }
  1167. /* quickly throw away any old contents of this valueset, and stick in the
  1168. * new ones.
  1169. */
  1170. void
  1171. valueset_replace(Slapi_ValueSet *vs, Slapi_Value **vals)
  1172. {
  1173. if(!valuearray_isempty(vs->va))
  1174. {
  1175. slapi_valueset_done(vs);
  1176. }
  1177. vs->va = vals;
  1178. }
  1179. /*
  1180. * Search the value set for each value to be update,
  1181. * and update the value with the CSN provided.
  1182. * Updated values are moved from the valuestoupdate
  1183. * array to the valueupdated array.
  1184. */
  1185. void
  1186. valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slapi_Value **valuestoupdate, CSNType t, const CSN *csn, Slapi_Value ***valuesupdated)
  1187. {
  1188. if(!valuearray_isempty(valuestoupdate) &&
  1189. !valuearray_isempty(vs->va))
  1190. {
  1191. /*
  1192. * determine whether we should use an AVL tree of values or not
  1193. */
  1194. struct valuearrayfast vaf_valuesupdated;
  1195. int numberofvaluestoupdate= valuearray_count(valuestoupdate);
  1196. valuearrayfast_init(&vaf_valuesupdated,*valuesupdated);
  1197. if (numberofvaluestoupdate>=SLAPD_MODUTIL_TREE_THRESHHOLD)
  1198. {
  1199. int i;
  1200. Avlnode *vtree = NULL;
  1201. int rc= valuetree_add_valuearray( a->a_type, a->a_plugin, vs->va, &vtree, NULL );
  1202. PR_ASSERT(rc==LDAP_SUCCESS);
  1203. for (i=0;valuestoupdate[i]!=NULL;++i)
  1204. {
  1205. int index= 0;
  1206. rc = valuetree_find( a, valuestoupdate[i], vtree, &index );
  1207. if(rc==LDAP_SUCCESS)
  1208. {
  1209. value_update_csn(vs->va[index],t,csn);
  1210. valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
  1211. valuestoupdate[i] = NULL;
  1212. }
  1213. }
  1214. valuetree_free(&vtree);
  1215. }
  1216. else
  1217. {
  1218. int i;
  1219. for (i=0;valuestoupdate[i]!=NULL;++i)
  1220. {
  1221. int index= valuearray_find(a, vs->va, valuestoupdate[i]);
  1222. if(index!=-1)
  1223. {
  1224. value_update_csn(vs->va[index],t,csn);
  1225. valuearrayfast_add_value_passin(&vaf_valuesupdated,valuestoupdate[i]);
  1226. valuestoupdate[i]= NULL;
  1227. }
  1228. }
  1229. }
  1230. valuearray_compress(valuestoupdate,numberofvaluestoupdate);
  1231. *valuesupdated= vaf_valuesupdated.va;
  1232. }
  1233. }