entrywsi.c 45 KB

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