entrywsi.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  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. /* entrywsi.c - routines for dealing with entries... With State Information */
  42. #include "slap.h"
  43. #include "slapi-plugin.h"
  44. static int
  45. entry_present_value_to_deleted_value(Slapi_Attr *a, Slapi_Value *v)
  46. {
  47. Slapi_Value *r= valueset_remove_value(a, &a->a_present_values, v);
  48. if(r!=NULL)
  49. {
  50. slapi_valueset_add_value_ext(&a->a_deleted_values, r, SLAPI_VALUE_FLAG_PASSIN);
  51. }
  52. return LDAP_SUCCESS;
  53. }
  54. static int
  55. entry_present_value_to_zapped_value(Slapi_Attr *a, Slapi_Value *v)
  56. {
  57. if(v!=NULL)
  58. {
  59. Slapi_Value *r= valueset_remove_value(a, &a->a_present_values, v);
  60. if(r!=NULL)
  61. {
  62. slapi_value_free(&r);
  63. }
  64. }
  65. return LDAP_SUCCESS;
  66. }
  67. static int
  68. entry_deleted_value_to_present_value(Slapi_Attr *a, Slapi_Value *v)
  69. {
  70. Slapi_Value *r= valueset_remove_value(a, &a->a_deleted_values, v);
  71. if(r!=NULL)
  72. {
  73. slapi_valueset_add_value_ext(&a->a_present_values, r, SLAPI_VALUE_FLAG_PASSIN);
  74. }
  75. return LDAP_SUCCESS;
  76. }
  77. static int
  78. entry_deleted_value_to_zapped_value(Slapi_Attr *a, Slapi_Value *v)
  79. {
  80. if(v!=NULL)
  81. {
  82. Slapi_Value *r= valueset_remove_value(a, &a->a_deleted_values, v);
  83. if(r!=NULL)
  84. {
  85. slapi_value_free(&r);
  86. }
  87. }
  88. return LDAP_SUCCESS;
  89. }
  90. static int
  91. entry_present_attribute_to_deleted_attribute(Slapi_Entry *e, Slapi_Attr *a)
  92. {
  93. attrlist_remove(&e->e_attrs,a->a_type);
  94. attrlist_add(&e->e_deleted_attrs,a);
  95. return LDAP_SUCCESS;
  96. }
  97. static int
  98. entry_deleted_attribute_to_present_attribute(Slapi_Entry *e, Slapi_Attr *a)
  99. {
  100. attrlist_remove(&e->e_deleted_attrs,a->a_type);
  101. attrlist_add(&e->e_attrs,a);
  102. return LDAP_SUCCESS;
  103. }
  104. /*
  105. * Get the first deleted attribute.
  106. *
  107. * Return 0: Return the type and the CSN of the deleted attribute.
  108. * Return -1: There are no deleted attributes.
  109. */
  110. int
  111. entry_first_deleted_attribute( const Slapi_Entry *e, Slapi_Attr **a)
  112. {
  113. *a= e->e_deleted_attrs;
  114. return( *a ? 0 : -1 );
  115. }
  116. /*
  117. * Get the next deleted attribute.
  118. *
  119. * Return 0: the type and the CSN of the deleted attribute.
  120. * Return -1: no deleted attributes.
  121. */
  122. int
  123. entry_next_deleted_attribute( const Slapi_Entry *e, Slapi_Attr **a)
  124. {
  125. *a= (*a)->a_next;
  126. return( *a ? 0 : -1 );
  127. }
  128. const CSN *
  129. entry_get_maxcsn ( const Slapi_Entry *entry )
  130. {
  131. return entry->e_maxcsn;
  132. }
  133. void
  134. entry_set_maxcsn ( Slapi_Entry *entry, const CSN *csn )
  135. {
  136. if ( NULL == entry->e_maxcsn )
  137. {
  138. entry->e_maxcsn = csn_dup ( csn );
  139. }
  140. else if ( csn_compare ( entry->e_maxcsn, csn ) < 0 )
  141. {
  142. csn_init_by_csn ( entry->e_maxcsn, csn );
  143. }
  144. }
  145. /*
  146. * Get the DN CSN of an entry.
  147. */
  148. const CSN *
  149. entry_get_dncsn(const Slapi_Entry *entry)
  150. {
  151. return csnset_get_last_csn(entry->e_dncsnset);
  152. }
  153. /*
  154. * Get the DN CSN set of an entry.
  155. */
  156. const CSNSet *
  157. entry_get_dncsnset(const Slapi_Entry *entry)
  158. {
  159. return entry->e_dncsnset;
  160. }
  161. /*
  162. * Add a DN CSN to an entry.
  163. */
  164. int
  165. entry_add_dncsn(Slapi_Entry *entry, const CSN *csn)
  166. {
  167. PR_ASSERT(entry!=NULL);
  168. csnset_update_csn(&entry->e_dncsnset, CSN_TYPE_VALUE_DISTINGUISHED, csn);
  169. return 0;
  170. }
  171. /*
  172. * Add a DN CSN to an entry, but uses flags to control the behavior
  173. * Using the ENTRY_DNCSN_INCREASING flag makes sure the csnset is in
  174. * order of increasing csn. csnset_insert_csn may not be very fast, so
  175. * we may have to revisit this if it becomes a performance problem.
  176. * In most cases, storing the csn unsorted is ok since the server
  177. * usually makes sure the csn is already in order. However, when doing
  178. * a str2entry, the order is not preserved unless we sort it.
  179. */
  180. int
  181. entry_add_dncsn_ext(Slapi_Entry *entry, const CSN *csn, PRUint32 flags)
  182. {
  183. PR_ASSERT(entry!=NULL);
  184. csnset_update_csn(&entry->e_dncsnset, CSN_TYPE_VALUE_DISTINGUISHED, csn);
  185. return 0;
  186. }
  187. /*
  188. * Set the CSN for all the present values on the entry.
  189. * This is only intended to be used for new entries
  190. * being added.
  191. */
  192. int
  193. entry_set_csn(Slapi_Entry *entry, const CSN *csn)
  194. {
  195. Slapi_Attr *a;
  196. PR_ASSERT(entry!=NULL);
  197. slapi_entry_first_attr( entry, &a );
  198. while(a!=NULL)
  199. {
  200. /*
  201. * JCM - it'd be more efficient if the str2entry code
  202. * set a flag on the attribute structure.
  203. */
  204. if(strcasecmp(a->a_type, SLAPI_ATTR_UNIQUEID)!=0)
  205. {
  206. attr_set_csn(a,csn);
  207. }
  208. slapi_entry_next_attr( entry, a, &a );
  209. }
  210. return 0;
  211. }
  212. /*
  213. * Set the Distinguished CSN for the RDN components of the entry.
  214. */
  215. void
  216. entry_add_rdn_csn(Slapi_Entry *e, const CSN *csn)
  217. {
  218. char *type;
  219. char *value;
  220. int index;
  221. const Slapi_DN *dn= slapi_entry_get_sdn_const(e);
  222. Slapi_RDN *rdn= slapi_rdn_new_sdn(dn);
  223. index= slapi_rdn_get_first(rdn, &type, &value);
  224. while(index!=-1)
  225. {
  226. Slapi_Attr *a= NULL;
  227. Slapi_Value *v= NULL;
  228. if ((entry_attr_find_wsi(e, type, &a) == ATTRIBUTE_PRESENT) && (a!=NULL))
  229. {
  230. struct berval bv;
  231. bv.bv_len= strlen(value);
  232. bv.bv_val= (void*)value;
  233. if (attr_value_find_wsi(a, &bv, &v) == VALUE_DELETED) {
  234. v = NULL;
  235. }
  236. }
  237. if(v!=NULL)
  238. {
  239. value_update_csn(v,CSN_TYPE_VALUE_DISTINGUISHED,csn);
  240. }
  241. else
  242. {
  243. /* JCM RDN component isn't a present value - this is illegal. */
  244. }
  245. index= slapi_rdn_get_next(rdn, index, &type, &value);
  246. }
  247. slapi_rdn_free(&rdn);
  248. }
  249. CSN*
  250. entry_assign_operation_csn ( Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *parententry )
  251. {
  252. Slapi_Operation *op;
  253. const CSN *basecsn = NULL;
  254. const CSN *parententry_dncsn = NULL;
  255. CSN *opcsn = NULL;
  256. slapi_pblock_get ( pb, SLAPI_OPERATION, &op );
  257. /*
  258. * The replication pre-op would have set op->o_csngen_handler for
  259. * user requests that are against a replica.
  260. */
  261. if ( op->o_csngen_handler )
  262. {
  263. /*
  264. * Sync up the CSN generator so that the new csn is greater
  265. * than the entry's maxcsn and/or the parent's max dncsn.
  266. */
  267. if ( e )
  268. {
  269. basecsn = entry_get_maxcsn ( e );
  270. }
  271. if ( parententry )
  272. {
  273. parententry_dncsn = entry_get_dncsn ( parententry );
  274. if ( csn_compare ( parententry_dncsn, basecsn ) > 0 )
  275. {
  276. basecsn = parententry_dncsn;
  277. }
  278. }
  279. opcsn = op->o_csngen_handler ( pb, basecsn );
  280. if (NULL != opcsn)
  281. {
  282. operation_set_csn (op, opcsn);
  283. }
  284. }
  285. return opcsn;
  286. }
  287. /*
  288. * Purge state information from the entry older than csnUpTo
  289. *
  290. * if csnUpTo is NULL, get rid of all the CSN related info.
  291. * if csnUpTo is non-NULL, purge all info older than csnUpTo
  292. */
  293. void
  294. entry_purge_state_information(Slapi_Entry *e, const CSN *csnUpTo)
  295. {
  296. Slapi_Attr *a=NULL;
  297. PR_ASSERT(e!=NULL);
  298. for(a = e->e_attrs; NULL != a; a = a->a_next)
  299. {
  300. /*
  301. * we are passing in the entry so that we may be able to "optimize"
  302. * the csn related information and roll it up higher to the level
  303. * of entry
  304. */
  305. attr_purge_state_information(e, a, csnUpTo);
  306. }
  307. for(a = e->e_deleted_attrs; NULL != a; a = a->a_next)
  308. {
  309. /*
  310. * we are passing in the entry so that we may be able to "optimize"
  311. * the csn related information and roll it up higher to the level
  312. * of entry
  313. */
  314. attr_purge_state_information(e, a, csnUpTo);
  315. }
  316. csnset_purge(&e->e_dncsnset, csnUpTo);
  317. }
  318. /*
  319. * Look for the attribute on the present and deleted attribute lists.
  320. */
  321. int
  322. entry_attr_find_wsi(Slapi_Entry *e, const char *type, Slapi_Attr **a)
  323. {
  324. int retVal= ATTRIBUTE_NOTFOUND;
  325. PR_ASSERT(e!=NULL);
  326. PR_ASSERT(type!=NULL);
  327. PR_ASSERT(a!=NULL);
  328. /* Look on the present attribute list */
  329. *a= attrlist_find(e->e_attrs,type);
  330. if(*a!=NULL)
  331. {
  332. /* The attribute is present */
  333. retVal= ATTRIBUTE_PRESENT;
  334. }
  335. else
  336. {
  337. /* Maybe the attribue was deleted... */
  338. *a= attrlist_find(e->e_deleted_attrs,type);
  339. if(*a!=NULL)
  340. {
  341. /* The attribute is deleted */
  342. retVal= ATTRIBUTE_DELETED;
  343. }
  344. else
  345. {
  346. /* The attribute was not found */
  347. retVal= ATTRIBUTE_NOTFOUND;
  348. }
  349. }
  350. return retVal;
  351. }
  352. /*
  353. * Add the attribute to the deleted attribute list.
  354. *
  355. * Consumes the attribute.
  356. */
  357. int
  358. entry_add_deleted_attribute_wsi(Slapi_Entry *e, Slapi_Attr *a)
  359. {
  360. PR_ASSERT( e!=NULL );
  361. PR_ASSERT( a!=NULL );
  362. attrlist_add(&e->e_deleted_attrs, a);
  363. return 0;
  364. }
  365. /*
  366. * Add the attribute to the present attribute list.
  367. *
  368. * Consumes the attribute.
  369. */
  370. int
  371. entry_add_present_attribute_wsi(Slapi_Entry *e, Slapi_Attr *a)
  372. {
  373. PR_ASSERT( e!=NULL );
  374. PR_ASSERT( a!=NULL );
  375. attrlist_add(&e->e_attrs, a);
  376. return 0;
  377. }
  378. /*
  379. * Add a list of values to the attribute, whilst maintaining state information.
  380. *
  381. * Preserves LDAP Information Model constraints,
  382. * returning an LDAP result code.
  383. */
  384. static void resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state);
  385. static void resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
  386. static void resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
  387. static void resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state);
  388. static int entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
  389. static int entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
  390. static int
  391. entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
  392. {
  393. int retVal = LDAP_SUCCESS;
  394. Slapi_Attr *a= NULL;
  395. int attr_state= entry_attr_find_wsi(e, type, &a);
  396. if (ATTRIBUTE_NOTFOUND == attr_state)
  397. {
  398. /* Create a new attribute */
  399. a = slapi_attr_new();
  400. slapi_attr_init(a, type);
  401. attrlist_add(&e->e_attrs, a);
  402. }
  403. if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
  404. {
  405. retVal = entry_add_present_values_wsi_single_valued( e, type, bervals, csn, urp, 0 );
  406. }
  407. else
  408. {
  409. retVal = entry_add_present_values_wsi_multi_valued( e, type, bervals, csn, urp, 0 );
  410. }
  411. return retVal;
  412. }
  413. static int
  414. entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
  415. {
  416. int retVal= LDAP_SUCCESS;
  417. Slapi_Value **valuestoadd = NULL;
  418. valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
  419. if(!valuearray_isempty(valuestoadd))
  420. {
  421. Slapi_Attr *a= NULL;
  422. long a_flags_orig;
  423. int attr_state= entry_attr_find_wsi(e, type, &a);
  424. a_flags_orig = a->a_flags;
  425. a->a_flags |= flags;
  426. /* Check if the type of the to-be-added values has DN syntax or not. */
  427. if (slapi_attr_is_dn_syntax_attr(a)) {
  428. valuearray_dn_normalize_value(valuestoadd);
  429. a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
  430. }
  431. if(urp)
  432. {
  433. valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
  434. SLAPI_VALUE_FLAG_IGNOREERROR |
  435. SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
  436. valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
  437. SLAPI_VALUE_FLAG_IGNOREERROR |
  438. SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
  439. valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
  440. slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, valuestoadd, valuearray_count(valuestoadd), SLAPI_VALUE_FLAG_PASSIN, NULL);
  441. slapi_ch_free ( (void **)&valuestoadd );
  442. /*
  443. * Now delete non-RDN values from a->a_present_values; and
  444. * restore possible RDN values from a->a_deleted_values
  445. */
  446. resolve_attribute_state_single_valued(e, a, attr_state);
  447. retVal= LDAP_SUCCESS;
  448. }
  449. else
  450. {
  451. Slapi_Value **deletedvalues= NULL;
  452. switch(attr_state)
  453. {
  454. case ATTRIBUTE_PRESENT:
  455. /* The attribute is already on the present list */
  456. break;
  457. case ATTRIBUTE_DELETED:
  458. /* Move the deleted attribute onto the present list */
  459. entry_deleted_attribute_to_present_attribute(e, a);
  460. break;
  461. case ATTRIBUTE_NOTFOUND:
  462. /* No-op - attribute was initialized & added to entry above */
  463. break;
  464. }
  465. /* Check if any of the values to be added are on the deleted list */
  466. valueset_remove_valuearray(&a->a_deleted_values,
  467. a, valuestoadd,
  468. SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
  469. &deletedvalues); /* JCM Check return code */
  470. if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
  471. {
  472. /* Some of the values to be added were on the deleted list */
  473. Slapi_Value **v= NULL;
  474. Slapi_ValueSet vs;
  475. /* Add each deleted value to the present list */
  476. valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
  477. slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
  478. /* Remove the deleted values from the values to add */
  479. valueset_set_valuearray_passin(&vs,valuestoadd);
  480. valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
  481. valuestoadd= valueset_get_valuearray(&vs);
  482. valuearray_free(&v);
  483. slapi_ch_free((void **)&deletedvalues);
  484. }
  485. valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
  486. retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
  487. }
  488. a->a_flags = a_flags_orig;
  489. }
  490. valuearray_free(&valuestoadd);
  491. return(retVal);
  492. }
  493. static int
  494. entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
  495. {
  496. int retVal= LDAP_SUCCESS;
  497. Slapi_Value **valuestoadd = NULL;
  498. valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
  499. if(!valuearray_isempty(valuestoadd))
  500. {
  501. Slapi_Attr *a = NULL;
  502. long a_flags_orig;
  503. int attr_state = entry_attr_find_wsi(e, type, &a);
  504. a_flags_orig = a->a_flags;
  505. a->a_flags |= flags;
  506. /* Check if the type of the to-be-added values has DN syntax or not. */
  507. if (slapi_attr_is_dn_syntax_attr(a)) {
  508. valuearray_dn_normalize_value(valuestoadd);
  509. a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
  510. }
  511. if(urp)
  512. {
  513. /*
  514. * Consolidate a->a_present_values and the pending values:
  515. * Delete the pending values from a->a_present_values
  516. * and transfer their csnsets to valuestoadd.
  517. */
  518. valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
  519. SLAPI_VALUE_FLAG_IGNOREERROR |
  520. SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
  521. /*
  522. * Consolidate a->a_deleted_values and the pending values
  523. * similarly.
  524. */
  525. valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
  526. SLAPI_VALUE_FLAG_IGNOREERROR |
  527. SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
  528. /* Now add the values in values to add to present or deleted
  529. * values, depending on their csnset */
  530. valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
  531. resolve_attribute_state_to_present_or_deleted(e, a, valuestoadd, attr_state);
  532. slapi_ch_free ( (void **)&valuestoadd );
  533. retVal= LDAP_SUCCESS;
  534. }
  535. else
  536. {
  537. Slapi_Value **deletedvalues= NULL;
  538. switch(attr_state)
  539. {
  540. case ATTRIBUTE_PRESENT:
  541. /* The attribute is already on the present list */
  542. break;
  543. case ATTRIBUTE_DELETED:
  544. /* Move the deleted attribute onto the present list */
  545. entry_deleted_attribute_to_present_attribute(e, a);
  546. break;
  547. case ATTRIBUTE_NOTFOUND:
  548. /* No-op - attribute was initialized & added to entry above */
  549. break;
  550. }
  551. /* Check if any of the values to be added are on the deleted list */
  552. valueset_remove_valuearray(&a->a_deleted_values,
  553. a, valuestoadd,
  554. SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
  555. &deletedvalues); /* JCM Check return code */
  556. if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
  557. {
  558. /* Some of the values to be added were on the deleted list */
  559. Slapi_Value **v= NULL;
  560. Slapi_ValueSet vs;
  561. /* Add each deleted value to the present list */
  562. valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
  563. slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
  564. /* Remove the deleted values from the values to add */
  565. valueset_set_valuearray_passin(&vs,valuestoadd);
  566. valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
  567. valuestoadd= valueset_get_valuearray(&vs);
  568. valuearray_free(&v);
  569. slapi_ch_free((void **)&deletedvalues);
  570. }
  571. valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
  572. retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
  573. }
  574. a->a_flags = a_flags_orig;
  575. }
  576. valuearray_free(&valuestoadd);
  577. return(retVal);
  578. }
  579. /*
  580. * Delete a list of values from an attribute, whilst maintaining state information.
  581. *
  582. * Preserves LDAP Information Model constraints,
  583. * returning an LDAP result code.
  584. */
  585. static int
  586. entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
  587. static int
  588. entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
  589. static int
  590. entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
  591. {
  592. int retVal= LDAP_SUCCESS;
  593. Slapi_Attr *a= NULL;
  594. int attr_state= entry_attr_find_wsi(e, type, &a);
  595. if(attr_state==ATTRIBUTE_PRESENT || (attr_state==ATTRIBUTE_DELETED && urp))
  596. {
  597. if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
  598. retVal = entry_delete_present_values_wsi_single_valued(e, type, vals, csn, urp, mod_op, replacevals);
  599. else
  600. retVal = entry_delete_present_values_wsi_multi_valued(e, type, vals, csn, urp, mod_op, replacevals);
  601. }
  602. else if (attr_state==ATTRIBUTE_DELETED)
  603. {
  604. #if defined(USE_OLD_UNHASHED)
  605. if (is_type_forbidden(type)) {
  606. retVal = LDAP_SUCCESS;
  607. } else {
  608. retVal= LDAP_NO_SUCH_ATTRIBUTE;
  609. }
  610. #else
  611. retVal= LDAP_NO_SUCH_ATTRIBUTE;
  612. #endif
  613. }
  614. else if (attr_state==ATTRIBUTE_NOTFOUND)
  615. {
  616. #if defined(USE_OLD_UNHASHED)
  617. if (is_type_protected(type) || is_type_forbidden(type))
  618. #else
  619. if (is_type_protected(type))
  620. #endif
  621. {
  622. retVal = LDAP_SUCCESS;
  623. } else {
  624. if (!urp) {
  625. LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
  626. type);
  627. }
  628. retVal = LDAP_NO_SUCH_ATTRIBUTE;
  629. }
  630. if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
  631. {
  632. /* Create a new attribute and set the adcsn */
  633. Slapi_Attr *a = slapi_attr_new();
  634. slapi_attr_init(a, type);
  635. attr_set_deletion_csn(a,csn);
  636. entry_add_deleted_attribute_wsi(e, a);
  637. }
  638. }
  639. return retVal;
  640. }
  641. static int
  642. entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
  643. {
  644. int retVal= LDAP_SUCCESS;
  645. Slapi_Attr *a= NULL;
  646. int attr_state= entry_attr_find_wsi(e, type, &a);
  647. /* The attribute is on the present list, or the deleted list and we're doing URP */
  648. if ( vals == NULL || vals[0] == NULL )
  649. {
  650. /* delete the entire attribute */
  651. LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
  652. attr_set_deletion_csn(a,csn);
  653. if(urp)
  654. {
  655. resolve_attribute_state_single_valued(e, a, attr_state);
  656. /* resolve attr state single valued */
  657. /* keep_present = check_attr_single_value_is_distingiuished(&a->a_present_values);
  658. if ( !keep_present) {
  659. slapi_valueset_done(&a->a_present_values);
  660. entry_present_attribute_to_deleted_attribute(e, a);
  661. }
  662. */
  663. }
  664. else
  665. {
  666. slapi_valueset_done(&a->a_present_values);
  667. entry_present_attribute_to_deleted_attribute(e, a);
  668. }
  669. retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
  670. }
  671. else
  672. {
  673. /* delete some specific values */
  674. Slapi_Value **valuestodelete= NULL;
  675. valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
  676. /* Check if the type of the to-be-deleted values has DN syntax
  677. * or not. */
  678. if (slapi_attr_is_dn_syntax_attr(a)) {
  679. valuearray_dn_normalize_value(valuestodelete);
  680. a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
  681. }
  682. if(urp)
  683. {
  684. Slapi_Value **valuesupdated= NULL;
  685. valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
  686. if( valuesupdated && *valuesupdated)
  687. {
  688. attr_set_deletion_csn(a,csn);
  689. }
  690. /* resolve attr state single valued */
  691. valuearray_free(&valuesupdated);
  692. valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
  693. valuearray_free(&valuesupdated);
  694. valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
  695. slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
  696. slapi_ch_free((void **)&valuestodelete);
  697. resolve_attribute_state_single_valued(e, a, attr_state);
  698. retVal= LDAP_SUCCESS;
  699. }
  700. else
  701. {
  702. Slapi_Value **deletedvalues= NULL;
  703. retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
  704. if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
  705. {
  706. valuearray_free(&deletedvalues);
  707. /* The attribute is single valued and the value was successful deleted */
  708. entry_present_attribute_to_deleted_attribute(e, a);
  709. }
  710. else if (retVal != LDAP_SUCCESS)
  711. {
  712. /* Failed
  713. * - Value not found
  714. * - Operations error
  715. */
  716. if ( retVal==LDAP_OPERATIONS_ERROR )
  717. {
  718. LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
  719. "value for attribute type %s found in "
  720. "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
  721. }
  722. }
  723. valuearray_free(&valuestodelete);
  724. }
  725. }
  726. return( retVal );
  727. }
  728. static int
  729. entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
  730. {
  731. int retVal= LDAP_SUCCESS;
  732. Slapi_Attr *a= NULL;
  733. entry_attr_find_wsi(e, type, &a);
  734. /* The attribute is on the present list, or the deleted list and we're doing URP */
  735. if ( vals == NULL || vals[0] == NULL )
  736. {
  737. /* delete the entire attribute */
  738. LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
  739. attr_set_deletion_csn(a,csn);
  740. if(urp)
  741. {
  742. /* there might be values added or specifically deleted later than
  743. * the current attr delete operation. These values need to be
  744. * preserved, all others can be removed, purging should o the job.
  745. */
  746. valueset_purge(&a->a_present_values, csn);
  747. valueset_purge(&a->a_deleted_values, csn);
  748. if(valueset_isempty(&a->a_present_values))
  749. entry_present_attribute_to_deleted_attribute(e, a);
  750. }
  751. else
  752. {
  753. slapi_valueset_done(&a->a_present_values);
  754. slapi_valueset_done(&a->a_deleted_values);
  755. entry_present_attribute_to_deleted_attribute(e, a);
  756. }
  757. retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
  758. }
  759. else
  760. {
  761. /* delete some specific values */
  762. Slapi_Value **valuestodelete= NULL;
  763. valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
  764. /* Check if the type of the to-be-deleted values has DN syntax
  765. * or not. */
  766. if (slapi_attr_is_dn_syntax_attr(a)) {
  767. valuearray_dn_normalize_value(valuestodelete);
  768. a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
  769. }
  770. if(urp)
  771. {
  772. /* check if values to delete are in present values
  773. * if v in present values and VU-csn<csn and v not distinguished move to deleted values
  774. * if v not in present values, check deleted values and update csn, if distinguisehed at csn
  775. * move back to present values
  776. */
  777. Slapi_Value **valuesupdated= NULL;
  778. valueset_update_csn_for_valuearray_ext(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
  779. resolve_attribute_state_present_to_deleted(e, a, valuesupdated);
  780. valuearray_free(&valuesupdated);
  781. valueset_update_csn_for_valuearray_ext(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
  782. resolve_attribute_state_deleted_to_present(e, a, valuesupdated);
  783. valuearray_free(&valuesupdated);
  784. valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
  785. slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
  786. /* all the elements in valuestodelete are passed;
  787. * should free valuestodelete only (don't call valuearray_free)
  788. * [622023] */
  789. slapi_ch_free((void **)&valuestodelete);
  790. retVal= LDAP_SUCCESS;
  791. }
  792. else
  793. {
  794. /* find the values to delete in present values,
  795. * update the csns and add to the deleted values
  796. */
  797. Slapi_Value **deletedvalues= NULL;
  798. retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
  799. if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
  800. {
  801. /* Add each deleted value to the deleted set */
  802. valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
  803. slapi_valueset_add_attr_valuearray_ext (a,
  804. &a->a_deleted_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
  805. slapi_ch_free((void **)&deletedvalues);
  806. if(valueset_isempty(&a->a_present_values))
  807. {
  808. /* There are no present values, so move the
  809. * attribute to the deleted attribute list. */
  810. entry_present_attribute_to_deleted_attribute(e, a);
  811. }
  812. }
  813. else if (retVal != LDAP_SUCCESS)
  814. {
  815. /* Failed
  816. * - Value not found
  817. * - Operations error
  818. */
  819. if ( retVal==LDAP_OPERATIONS_ERROR )
  820. {
  821. LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
  822. "value for attribute type %s found in "
  823. "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
  824. }
  825. }
  826. valuearray_free(&valuestodelete);
  827. }
  828. }
  829. return( retVal );
  830. }
  831. /*
  832. * Replace all the values of an attribute with a list of attribute values.
  833. *
  834. * Preserves LDAP Information Model constraints,
  835. * returning an LDAP result code.
  836. */
  837. static int
  838. entry_replace_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp)
  839. {
  840. /*
  841. * Remove all existing values.
  842. */
  843. entry_delete_present_values_wsi(e, type, NULL /* Delete all values */, csn, urp, LDAP_MOD_REPLACE, vals);
  844. /*
  845. * Add the new values. If there are no new values,
  846. * slapi_entry_add_values() returns LDAP_SUCCESS and so the
  847. * attribute remains deleted (which is the correct outcome).
  848. */
  849. return( entry_add_present_values_wsi( e, type, vals, csn, urp, 0));
  850. }
  851. /*
  852. * Applies the modification to the entry whilst
  853. * maintaining state information.
  854. */
  855. int
  856. entry_apply_mod_wsi(Slapi_Entry *e, const LDAPMod *mod, const CSN *csn, int urp)
  857. {
  858. int retVal= LDAP_SUCCESS;
  859. int i;
  860. struct attrs_in_extension *aiep;
  861. switch ( mod->mod_op & ~LDAP_MOD_BVALUES )
  862. {
  863. case LDAP_MOD_ADD:
  864. LDAPDebug( LDAP_DEBUG_ARGS, " add: %s\n", mod->mod_type, 0, 0 );
  865. retVal = entry_add_present_values_wsi( e, mod->mod_type, mod->mod_bvalues, csn, urp, 0 );
  866. break;
  867. case LDAP_MOD_DELETE:
  868. LDAPDebug( LDAP_DEBUG_ARGS, " delete: %s\n", mod->mod_type, 0, 0 );
  869. retVal = entry_delete_present_values_wsi( e, mod->mod_type, mod->mod_bvalues, csn, urp, mod->mod_op, NULL );
  870. break;
  871. case LDAP_MOD_REPLACE:
  872. LDAPDebug( LDAP_DEBUG_ARGS, " replace: %s\n", mod->mod_type, 0, 0 );
  873. retVal = entry_replace_present_values_wsi( e, mod->mod_type, mod->mod_bvalues, csn, urp );
  874. break;
  875. }
  876. if ( LDAPDebugLevelIsSet( LDAP_DEBUG_ARGS )) {
  877. for ( i = 0;
  878. mod->mod_bvalues != NULL && mod->mod_bvalues[i] != NULL;
  879. i++ ) {
  880. LDAPDebug( LDAP_DEBUG_ARGS, " %s: %s\n",
  881. mod->mod_type, mod->mod_bvalues[i]->bv_val, 0 );
  882. }
  883. LDAPDebug( LDAP_DEBUG_ARGS, " -\n", 0, 0, 0 );
  884. }
  885. /*
  886. * Values to be stored in the extension are also processed considering
  887. * the conflicts above. The psuedo attributes are removed from the
  888. * entry and the values (present value only) are put in the extension.
  889. */
  890. for (aiep = attrs_in_extension; aiep && aiep->ext_type; aiep++) {
  891. if (0 == strcasecmp(mod->mod_type, aiep->ext_type)) {
  892. Slapi_Attr *a;
  893. /* remove the attribute from the attr list */
  894. a = attrlist_remove(&e->e_attrs, mod->mod_type);
  895. if (a && a->a_present_values.va) {
  896. /* a->a_present_values.va is consumed if successful. */
  897. int rc = slapi_pw_set_entry_ext(e, a->a_present_values.va,
  898. SLAPI_EXT_SET_REPLACE);
  899. if (LDAP_SUCCESS == rc) {
  900. /* va is set to entry extension; just release the rest */
  901. a->a_present_values.va = NULL;
  902. }
  903. slapi_attr_free(&a);
  904. } else {
  905. Slapi_Value **ext_vals = NULL;
  906. slapi_pw_get_entry_ext(e, &ext_vals);
  907. if (ext_vals) {
  908. /* slapi_pw_set_entry_ext frees the stored extension */
  909. slapi_pw_set_entry_ext(e, NULL, SLAPI_EXT_SET_REPLACE);
  910. ext_vals = NULL;
  911. }
  912. }
  913. }
  914. }
  915. return retVal;
  916. }
  917. /*
  918. * Applies the set of modifications to the entry whilst
  919. * maintaining state information.
  920. */
  921. int
  922. entry_apply_mods_wsi(Slapi_Entry *e, Slapi_Mods *smods, const CSN *csn, int urp)
  923. {
  924. int retVal= LDAP_SUCCESS;
  925. LDAPMod *mod;
  926. CSN localcsn;
  927. if (csn) {
  928. localcsn = *csn; /* make a copy */
  929. }
  930. LDAPDebug( LDAP_DEBUG_TRACE, "=> entry_apply_mods_wsi\n", 0, 0, 0 );
  931. mod = slapi_mods_get_first_mod(smods);
  932. while(NULL!=mod && retVal==LDAP_SUCCESS)
  933. {
  934. if(csn!=NULL)
  935. {
  936. retVal= entry_apply_mod_wsi(e, mod, &localcsn, urp);
  937. /* use subsequence to guarantee absolute ordering of all of the
  938. mods in a set of mods, if this is a replicated operation,
  939. and the csn doesn't already have a subsequence
  940. if the csn already has a subsequence, assume it was generated
  941. on another replica in the correct order */
  942. if (csn_get_subseqnum(csn) == 0) {
  943. csn_increment_subsequence(&localcsn);
  944. }
  945. }
  946. else
  947. {
  948. retVal= entry_apply_mod(e, mod);
  949. }
  950. mod = slapi_mods_get_next_mod(smods);
  951. }
  952. LDAPDebug( LDAP_DEBUG_TRACE, "<= entry_apply_mods_wsi %d\n", retVal, 0, 0 );
  953. return retVal;
  954. }
  955. /*
  956. * This code implements a computed attribute called 'nscpEntryWSI'.
  957. * By specifically asking for this attribute the client will receive
  958. * an LDIF dump of the entry with all its state information.
  959. *
  960. * JCM - Security... Only for the Directory Manager.
  961. */
  962. static const char *nscpEntryWSI= "nscpEntryWSI";
  963. /*
  964. */
  965. static int
  966. entry_compute_nscpentrywsi(computed_attr_context *c,char* type,Slapi_Entry *e,slapi_compute_output_t outputfn)
  967. {
  968. int rc = 0;
  969. if ( strcasecmp(type, nscpEntryWSI ) == 0)
  970. {
  971. /* If not, we return it as zero */
  972. char *es;
  973. char *s;
  974. char *p;
  975. int len;
  976. Slapi_Attr our_attr;
  977. slapi_attr_init(&our_attr, nscpEntryWSI);
  978. our_attr.a_flags = SLAPI_ATTR_FLAG_OPATTR;
  979. es= slapi_entry2str_with_options(e, &len, SLAPI_DUMP_STATEINFO | SLAPI_DUMP_UNIQUEID | SLAPI_DUMP_NOWRAP);
  980. s= es;
  981. p= ldif_getline( &s );
  982. while(p!=NULL)
  983. {
  984. Slapi_Value *v;
  985. char *t, *d;
  986. /* Strip out the Continuation Markers (JCM - I think that NOWRAP means we don't need to do this any more)*/
  987. for ( t = p, d = p; *t; t++ )
  988. {
  989. if ( *t != 0x01 )
  990. *d++ = *t;
  991. }
  992. *d = '\0';
  993. v= slapi_value_new_string(p);
  994. slapi_attr_add_value(&our_attr,v);
  995. slapi_value_free(&v);
  996. p= ldif_getline( &s );
  997. }
  998. slapi_ch_free((void**)&es);
  999. rc = (*outputfn) (c, &our_attr, e);
  1000. attr_done(&our_attr);
  1001. return (rc);
  1002. }
  1003. return -1; /* I see no ships */
  1004. }
  1005. int
  1006. entry_computed_attr_init()
  1007. {
  1008. slapi_compute_add_evaluator(entry_compute_nscpentrywsi);
  1009. return 0;
  1010. }
  1011. static void
  1012. purge_attribute_state_multi_valued(const Slapi_Attr *a, Slapi_Value *v)
  1013. {
  1014. const CSN *vdcsn= value_get_csn(v,CSN_TYPE_VALUE_DELETED);
  1015. const CSN *vucsn= value_get_csn(v,CSN_TYPE_VALUE_UPDATED);
  1016. if(vdcsn && csn_compare(vdcsn,vucsn)<0)
  1017. {
  1018. value_remove_csn(v,CSN_TYPE_VALUE_DELETED);
  1019. }
  1020. }
  1021. /*
  1022. * utility function for value_distinguished_at_csn...
  1023. */
  1024. static const CSN *
  1025. vdac_sniff_value(Slapi_ValueSet *vs, const Slapi_Value *v, const CSN *csn, const CSN *most_recent_mdcsn)
  1026. {
  1027. const CSN *mdcsn= value_get_csn(v,CSN_TYPE_VALUE_DISTINGUISHED);
  1028. if(mdcsn!=NULL)
  1029. {
  1030. /* This value was/is distinguished... */
  1031. if(csn_compare(csn,most_recent_mdcsn)<0)
  1032. {
  1033. /* ...and was distinguished before the point in time we're interested in... */
  1034. int r= csn_compare(mdcsn,most_recent_mdcsn);
  1035. if(r>0)
  1036. {
  1037. /* ...and is the most recent MDCSN we've seen thus far. */
  1038. slapi_valueset_done(vs);
  1039. slapi_valueset_add_value(vs,v);
  1040. most_recent_mdcsn= mdcsn;
  1041. }
  1042. else if(r==0)
  1043. {
  1044. /* ...and is as recent as the last most recent MDCSN we've seen thus far. */
  1045. /* Must have been a multi-valued RDN */
  1046. slapi_valueset_add_value(vs,v);
  1047. }
  1048. }
  1049. }
  1050. return most_recent_mdcsn;
  1051. }
  1052. /*
  1053. * utility function for value_distinguished_at_csn...
  1054. */
  1055. static const CSN *
  1056. vdac_sniff_attribute(Slapi_ValueSet *vs, Slapi_Attr *a, const CSN *csn, const CSN *most_recent_mdcsn)
  1057. {
  1058. Slapi_Value *v;
  1059. int i= slapi_attr_first_value( a, &v );
  1060. while(i!=-1)
  1061. {
  1062. most_recent_mdcsn= vdac_sniff_value( vs, v, csn, most_recent_mdcsn );
  1063. i= slapi_attr_next_value( a, i, &v );
  1064. }
  1065. i= attr_first_deleted_value( a, &v );
  1066. while(i!=-1)
  1067. {
  1068. most_recent_mdcsn= vdac_sniff_value( vs, v, csn, most_recent_mdcsn );
  1069. i= attr_next_deleted_value( a, i, &v );
  1070. }
  1071. return most_recent_mdcsn;
  1072. }
  1073. /*
  1074. * utility function for value_distinguished_at_csn...
  1075. *
  1076. * Return the set of values that made up the RDN at or before the csn point.
  1077. */
  1078. static const CSN *
  1079. distinguished_values_at_csn(const Slapi_Entry *e, const CSN *csn, Slapi_ValueSet *vs)
  1080. {
  1081. const CSN *most_recent_mdcsn= NULL;
  1082. Slapi_Attr *a;
  1083. int i= slapi_entry_first_attr( e, &a );
  1084. while(i!=-1)
  1085. {
  1086. most_recent_mdcsn= vdac_sniff_attribute( vs, a, csn, most_recent_mdcsn);
  1087. i= slapi_entry_next_attr( e, a, &a );
  1088. }
  1089. i= entry_first_deleted_attribute( e, &a );
  1090. while(i!=-1)
  1091. {
  1092. most_recent_mdcsn= vdac_sniff_attribute( vs, a, csn, most_recent_mdcsn);
  1093. i= entry_next_deleted_attribute( e, &a );
  1094. }
  1095. return most_recent_mdcsn;
  1096. }
  1097. /*
  1098. * Work out if the value was distinguished at time csn.
  1099. */
  1100. static int
  1101. value_distinguished_at_csn(const Slapi_Entry *e, const Slapi_Attr *original_attr, Slapi_Value *original_value, const CSN *csn)
  1102. {
  1103. int r= 0;
  1104. const CSN *mdcsn= value_get_csn(original_value,CSN_TYPE_VALUE_DISTINGUISHED);
  1105. if(mdcsn!=NULL)
  1106. {
  1107. /*
  1108. * Oh bugger. This means that we have to work out what the RDN components
  1109. * were at this point in time. This is non-trivial since we must walk
  1110. * through all the present and deleted attributes and their present and
  1111. * deleted values. Slow :-(
  1112. */
  1113. Slapi_ValueSet *vs= slapi_valueset_new();
  1114. const CSN *most_recent_mdcsn= distinguished_values_at_csn(e, csn, vs);
  1115. /*
  1116. * We now know what the RDN components were at the point in time we're interested in.
  1117. * And the question we need to answer is :-
  1118. * 'Was the provided value one of those RDN components?'
  1119. */
  1120. if(most_recent_mdcsn!=NULL)
  1121. {
  1122. Slapi_Value *v;
  1123. int i= slapi_valueset_first_value( vs, &v );
  1124. while(i!=-1)
  1125. {
  1126. if(slapi_value_compare(original_attr, original_value, v)==0)
  1127. {
  1128. /* This value was distinguished at the time in question. */
  1129. r= 1;
  1130. i= -1;
  1131. }
  1132. else
  1133. {
  1134. i= slapi_valueset_next_value( vs, i, &v );
  1135. }
  1136. }
  1137. }
  1138. slapi_valueset_free(vs);
  1139. }
  1140. else
  1141. {
  1142. /* This value has never been distinguished */
  1143. r= 0;
  1144. }
  1145. return r;
  1146. }
  1147. /* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */
  1148. static void
  1149. resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
  1150. {
  1151. const CSN *vdcsn;
  1152. const CSN *vucsn;
  1153. const CSN *deletedcsn;
  1154. const CSN *adcsn= attr_get_deletion_csn(a);
  1155. int i;
  1156. if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
  1157. for (i=0;valuestoupdate[i]!=NULL;++i) {
  1158. purge_attribute_state_multi_valued(a, valuestoupdate[i]);
  1159. vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
  1160. vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
  1161. deletedcsn= csn_max(vdcsn, adcsn);
  1162. if((csn_compare(vucsn,deletedcsn)>=0) ||
  1163. value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
  1164. {
  1165. entry_deleted_value_to_present_value(a,valuestoupdate[i]);
  1166. }
  1167. valuestoupdate[i]->v_csnset = NULL;
  1168. }
  1169. }
  1170. }
  1171. static void
  1172. resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state)
  1173. {
  1174. const CSN *vdcsn;
  1175. const CSN *vucsn;
  1176. const CSN *deletedcsn;
  1177. const CSN *adcsn= attr_get_deletion_csn(a);
  1178. int i;
  1179. if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
  1180. for (i=0;valuestoupdate[i]!=NULL;++i) {
  1181. purge_attribute_state_multi_valued(a, valuestoupdate[i]);
  1182. vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
  1183. vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
  1184. deletedcsn= csn_max(vdcsn, adcsn);
  1185. if((csn_compare(vucsn,deletedcsn)>=0) ||
  1186. value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
  1187. {
  1188. slapi_valueset_add_value_ext(&a->a_present_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
  1189. } else {
  1190. slapi_valueset_add_value_ext(&a->a_deleted_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
  1191. }
  1192. }
  1193. }
  1194. if(valueset_isempty(&a->a_present_values))
  1195. {
  1196. if(attribute_state==ATTRIBUTE_PRESENT)
  1197. {
  1198. entry_present_attribute_to_deleted_attribute(e, a);
  1199. }
  1200. }
  1201. else
  1202. {
  1203. if(attribute_state==ATTRIBUTE_DELETED)
  1204. {
  1205. entry_deleted_attribute_to_present_attribute(e, a);
  1206. }
  1207. }
  1208. }
  1209. static void
  1210. resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
  1211. {
  1212. const CSN *vdcsn;
  1213. const CSN *vucsn;
  1214. const CSN *deletedcsn;
  1215. const CSN *adcsn= attr_get_deletion_csn(a);
  1216. int i;
  1217. if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
  1218. for (i=0;valuestoupdate[i]!=NULL;++i) {
  1219. /* This call ensures that the value does not contain a deletion_csn
  1220. * which is before the presence_csn or distinguished_csn of the value.
  1221. */
  1222. purge_attribute_state_multi_valued(a, valuestoupdate[i]);
  1223. vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
  1224. vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
  1225. deletedcsn= csn_max(vdcsn, adcsn);
  1226. if(csn_compare(vucsn,deletedcsn)<0)
  1227. {
  1228. if(!value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
  1229. {
  1230. entry_present_value_to_deleted_value(a,valuestoupdate[i]);
  1231. }
  1232. }
  1233. valuestoupdate[i]->v_csnset = NULL;
  1234. }
  1235. }
  1236. }
  1237. static void
  1238. resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
  1239. {
  1240. Slapi_Value *current_value= NULL;
  1241. Slapi_Value *pending_value= NULL;
  1242. Slapi_Value *new_value= NULL;
  1243. const CSN *current_value_vucsn;
  1244. const CSN *pending_value_vucsn;
  1245. const CSN *adcsn;
  1246. int i;
  1247. /*
  1248. * this call makes sure that the attribute does not have a pending_value
  1249. * or deletion_csn which is before the current_value.
  1250. */
  1251. i= slapi_attr_first_value(a,&current_value);
  1252. if(i!=-1)
  1253. {
  1254. slapi_attr_next_value(a,i,&new_value);
  1255. }
  1256. attr_first_deleted_value(a,&pending_value);
  1257. /* purge_attribute_state_single_valued */
  1258. adcsn= attr_get_deletion_csn(a);
  1259. current_value_vucsn= value_get_csn(current_value, CSN_TYPE_VALUE_UPDATED);
  1260. pending_value_vucsn= value_get_csn(pending_value, CSN_TYPE_VALUE_UPDATED);
  1261. if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
  1262. (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
  1263. {
  1264. attr_set_deletion_csn(a,NULL);
  1265. adcsn= NULL;
  1266. }
  1267. if(new_value==NULL)
  1268. {
  1269. /* check if the pending value should become the current value */
  1270. if(pending_value!=NULL)
  1271. {
  1272. if(!value_distinguished_at_csn(e,a,current_value,pending_value_vucsn))
  1273. {
  1274. /* attribute.current_value = attribute.pending_value; */
  1275. /* attribute.pending_value = NULL; */
  1276. entry_present_value_to_zapped_value(a,current_value);
  1277. entry_deleted_value_to_present_value(a,pending_value);
  1278. current_value= pending_value;
  1279. pending_value= NULL;
  1280. current_value_vucsn= pending_value_vucsn;
  1281. pending_value_vucsn= NULL;
  1282. }
  1283. }
  1284. /* check if the current value should be deleted */
  1285. if(current_value!=NULL)
  1286. {
  1287. if(csn_compare(adcsn,current_value_vucsn)>0) /* check if the attribute was deleted after the value was last updated */
  1288. {
  1289. if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn))
  1290. {
  1291. entry_present_value_to_zapped_value(a,current_value);
  1292. current_value= NULL;
  1293. current_value_vucsn= NULL;
  1294. }
  1295. }
  1296. }
  1297. }
  1298. else /* addition of a new value */
  1299. {
  1300. const CSN *new_value_vucsn= value_get_csn(new_value,CSN_TYPE_VALUE_UPDATED);
  1301. if(csn_compare(new_value_vucsn,current_value_vucsn)<0)
  1302. {
  1303. /*
  1304. * if the new value was distinguished at the time the current value was added
  1305. * then the new value should become current
  1306. */
  1307. if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn))
  1308. {
  1309. /* attribute.pending_value = attribute.current_value */
  1310. /* attribute.current_value = new_value */
  1311. if(pending_value==NULL)
  1312. {
  1313. entry_present_value_to_deleted_value(a,current_value);
  1314. }
  1315. else
  1316. {
  1317. entry_present_value_to_zapped_value(a,current_value);
  1318. }
  1319. pending_value= current_value;
  1320. current_value= new_value;
  1321. new_value= NULL;
  1322. pending_value_vucsn= current_value_vucsn;
  1323. current_value_vucsn= new_value_vucsn;
  1324. }
  1325. else
  1326. {
  1327. /* new_value= NULL */
  1328. entry_present_value_to_zapped_value(a, new_value);
  1329. new_value= NULL;
  1330. }
  1331. }
  1332. else /* new value is after the current value */
  1333. {
  1334. if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
  1335. {
  1336. /* attribute.current_value = new_value */
  1337. entry_present_value_to_zapped_value(a, current_value);
  1338. current_value= new_value;
  1339. new_value= NULL;
  1340. current_value_vucsn= new_value_vucsn;
  1341. }
  1342. else /* value is distinguished - check if we should replace the current pending value */
  1343. {
  1344. if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
  1345. {
  1346. /* attribute.pending_value = new_value */
  1347. entry_deleted_value_to_zapped_value(a,pending_value);
  1348. entry_present_value_to_deleted_value(a,new_value);
  1349. pending_value= new_value;
  1350. new_value= NULL;
  1351. pending_value_vucsn= new_value_vucsn;
  1352. }
  1353. }
  1354. }
  1355. }
  1356. /*
  1357. * This call ensures that the attribute does not have a pending_value
  1358. * or a deletion_csn that is earlier than the current_value.
  1359. */
  1360. /* purge_attribute_state_single_valued */
  1361. if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
  1362. (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
  1363. {
  1364. attr_set_deletion_csn(a,NULL);
  1365. adcsn= NULL;
  1366. }
  1367. /* set attribute state */
  1368. if(current_value==NULL)
  1369. {
  1370. if(attribute_state==ATTRIBUTE_PRESENT)
  1371. {
  1372. entry_present_attribute_to_deleted_attribute(e, a);
  1373. }
  1374. }
  1375. else
  1376. {
  1377. if(attribute_state==ATTRIBUTE_DELETED)
  1378. {
  1379. entry_deleted_attribute_to_present_attribute(e, a);
  1380. }
  1381. }
  1382. }