419
417
* Preserves LDAP Information Model constraints,
420
418
* returning an LDAP result code.
420
static void resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state);
421
static void resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
422
static void resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
423
static void resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state);
424
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);
425
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);
423
427
entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
429
int retVal = LDAP_SUCCESS;
431
int attr_state= entry_attr_find_wsi(e, type, &a);
432
if (ATTRIBUTE_NOTFOUND == attr_state)
434
/* Create a new attribute */
435
a = slapi_attr_new();
436
slapi_attr_init(a, type);
437
attrlist_add(&e->e_attrs, a);
440
if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
442
retVal = entry_add_present_values_wsi_single_valued( e, type, bervals, csn, urp, 0 );
446
retVal = entry_add_present_values_wsi_multi_valued( e, type, bervals, csn, urp, 0 );
452
entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
425
454
int retVal= LDAP_SUCCESS;
426
Slapi_Value **valuestoadd = NULL;
427
valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
455
Slapi_Value **valuestoadd = NULL;
457
valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
428
458
if(!valuearray_isempty(valuestoadd))
430
460
Slapi_Attr *a= NULL;
431
461
long a_flags_orig;
432
462
int attr_state= entry_attr_find_wsi(e, type, &a);
433
if (ATTRIBUTE_NOTFOUND == attr_state)
435
/* Create a new attribute */
436
a = slapi_attr_new();
437
slapi_attr_init(a, type);
438
attrlist_add(&e->e_attrs, a);
440
a_flags_orig = a->a_flags;
464
a_flags_orig = a->a_flags;
466
/* Check if the type of the to-be-added values has DN syntax or not. */
467
if (slapi_attr_is_dn_syntax_attr(a)) {
468
valuearray_dn_normalize_value(valuestoadd);
469
a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
473
valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
474
SLAPI_VALUE_FLAG_IGNOREERROR |
475
SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
476
valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
477
SLAPI_VALUE_FLAG_IGNOREERROR |
478
SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
479
valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
480
slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, valuestoadd, valuearray_count(valuestoadd), SLAPI_VALUE_FLAG_PASSIN, NULL);
481
slapi_ch_free ( (void **)&valuestoadd );
483
* Now delete non-RDN values from a->a_present_values; and
484
* restore possible RDN values from a->a_deleted_values
486
resolve_attribute_state_single_valued(e, a, attr_state);
487
retVal= LDAP_SUCCESS;
491
Slapi_Value **deletedvalues= NULL;
494
case ATTRIBUTE_PRESENT:
495
/* The attribute is already on the present list */
497
case ATTRIBUTE_DELETED:
498
/* Move the deleted attribute onto the present list */
499
entry_deleted_attribute_to_present_attribute(e, a);
501
case ATTRIBUTE_NOTFOUND:
502
/* No-op - attribute was initialized & added to entry above */
505
/* Check if any of the values to be added are on the deleted list */
506
valueset_remove_valuearray(&a->a_deleted_values,
508
SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
509
&deletedvalues); /* JCM Check return code */
510
if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
512
/* Some of the values to be added were on the deleted list */
513
Slapi_Value **v= NULL;
515
/* Add each deleted value to the present list */
516
valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
517
slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
518
/* Remove the deleted values from the values to add */
519
valueset_set_valuearray_passin(&vs,valuestoadd);
520
valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
521
valuestoadd= valueset_get_valuearray(&vs);
523
slapi_ch_free((void **)&deletedvalues);
525
valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
526
retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
528
a->a_flags = a_flags_orig;
530
valuearray_free(&valuestoadd);
536
entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
538
int retVal= LDAP_SUCCESS;
539
Slapi_Value **valuestoadd = NULL;
541
valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
542
if(!valuearray_isempty(valuestoadd))
544
Slapi_Attr *a = NULL;
546
int attr_state = entry_attr_find_wsi(e, type, &a);
548
a_flags_orig = a->a_flags;
441
549
a->a_flags |= flags;
442
550
/* Check if the type of the to-be-added values has DN syntax or not. */
443
551
if (slapi_attr_is_dn_syntax_attr(a)) {
462
570
SLAPI_VALUE_FLAG_IGNOREERROR |
463
571
SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
465
/* Append the pending values to a->a_present_values */
573
/* Now add the values in values to add to present or deleted
574
* values, depending on their csnset */
466
575
valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
467
valueset_add_valuearray_ext(&a->a_present_values, valuestoadd, SLAPI_VALUE_FLAG_PASSIN);
577
resolve_attribute_state_to_present_or_deleted(e, a, valuestoadd, attr_state);
468
579
slapi_ch_free ( (void **)&valuestoadd );
471
* Now delete non-RDN values from a->a_present_values; and
472
* restore possible RDN values from a->a_deleted_values
474
resolve_attribute_state(e, a, attr_state, 0);
475
581
retVal= LDAP_SUCCESS;
479
585
Slapi_Value **deletedvalues= NULL;
480
587
switch(attr_state)
482
case ATTRIBUTE_PRESENT:
483
/* The attribute is already on the present list */
485
case ATTRIBUTE_DELETED:
486
/* Move the deleted attribute onto the present list */
487
entry_deleted_attribute_to_present_attribute(e, a);
489
case ATTRIBUTE_NOTFOUND:
490
/* No-op - attribute was initialized & added to entry above */
589
case ATTRIBUTE_PRESENT:
590
/* The attribute is already on the present list */
592
case ATTRIBUTE_DELETED:
593
/* Move the deleted attribute onto the present list */
594
entry_deleted_attribute_to_present_attribute(e, a);
596
case ATTRIBUTE_NOTFOUND:
597
/* No-op - attribute was initialized & added to entry above */
493
600
/* Check if any of the values to be added are on the deleted list */
494
601
valueset_remove_valuearray(&a->a_deleted_values,
526
634
* returning an LDAP result code.
637
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);
639
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);
529
641
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)
531
643
int retVal= LDAP_SUCCESS;
532
644
Slapi_Attr *a= NULL;
533
645
int attr_state= entry_attr_find_wsi(e, type, &a);
534
647
if(attr_state==ATTRIBUTE_PRESENT || (attr_state==ATTRIBUTE_DELETED && urp))
649
if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
650
retVal = entry_delete_present_values_wsi_single_valued(e, type, vals, csn, urp, mod_op, replacevals);
652
retVal = entry_delete_present_values_wsi_multi_valued(e, type, vals, csn, urp, mod_op, replacevals);
654
else if (attr_state==ATTRIBUTE_DELETED)
656
#if defined(USE_OLD_UNHASHED)
657
if (is_type_forbidden(type)) {
658
retVal = LDAP_SUCCESS;
660
retVal= LDAP_NO_SUCH_ATTRIBUTE;
663
retVal= LDAP_NO_SUCH_ATTRIBUTE;
666
else if (attr_state==ATTRIBUTE_NOTFOUND)
668
#if defined(USE_OLD_UNHASHED)
669
if (is_type_protected(type) || is_type_forbidden(type))
671
if (is_type_protected(type))
674
retVal = LDAP_SUCCESS;
677
LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
680
retVal = LDAP_NO_SUCH_ATTRIBUTE;
682
if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
684
/* Create a new attribute and set the adcsn */
685
Slapi_Attr *a = slapi_attr_new();
686
slapi_attr_init(a, type);
687
attr_set_deletion_csn(a,csn);
688
entry_add_deleted_attribute_wsi(e, a);
694
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)
696
int retVal= LDAP_SUCCESS;
698
int attr_state= entry_attr_find_wsi(e, type, &a);
699
/* The attribute is on the present list, or the deleted list and we're doing URP */
700
if ( vals == NULL || vals[0] == NULL )
702
/* delete the entire attribute */
703
LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
704
attr_set_deletion_csn(a,csn);
707
resolve_attribute_state_single_valued(e, a, attr_state);
708
/* resolve attr state single valued */
709
/* keep_present = check_attr_single_value_is_distingiuished(&a->a_present_values);
710
if ( !keep_present) {
711
slapi_valueset_done(&a->a_present_values);
712
entry_present_attribute_to_deleted_attribute(e, a);
718
slapi_valueset_done(&a->a_present_values);
719
entry_present_attribute_to_deleted_attribute(e, a);
721
retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
725
/* delete some specific values */
726
Slapi_Value **valuestodelete= NULL;
727
valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
728
/* Check if the type of the to-be-deleted values has DN syntax
730
if (slapi_attr_is_dn_syntax_attr(a)) {
731
valuearray_dn_normalize_value(valuestodelete);
732
a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
736
Slapi_Value **valuesupdated= NULL;
737
valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
738
if( valuesupdated && *valuesupdated)
740
attr_set_deletion_csn(a,csn);
742
/* resolve attr state single valued */
743
valuearray_free(&valuesupdated);
744
valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
745
valuearray_free(&valuesupdated);
746
valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
747
slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
748
slapi_ch_free((void **)&valuestodelete);
749
resolve_attribute_state_single_valued(e, a, attr_state);
750
retVal= LDAP_SUCCESS;
754
Slapi_Value **deletedvalues= NULL;
755
retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
756
if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
758
valuearray_free(&deletedvalues);
759
/* The attribute is single valued and the value was successful deleted */
760
/* but there could have been an add in the same operation, so double check */
761
if (valueset_isempty(&a->a_present_values)) {
762
entry_present_attribute_to_deleted_attribute(e, a);
765
else if (retVal != LDAP_SUCCESS)
771
if ( retVal==LDAP_OPERATIONS_ERROR )
773
LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
774
"value for attribute type %s found in "
775
"entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
778
valuearray_free(&valuestodelete);
784
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)
786
int retVal= LDAP_SUCCESS;
788
int attr_state = entry_attr_find_wsi(e, type, &a);
536
789
/* The attribute is on the present list, or the deleted list and we're doing URP */
537
790
if ( vals == NULL || vals[0] == NULL )
541
794
attr_set_deletion_csn(a,csn);
544
resolve_attribute_state(e, a, attr_state, 1 /* set delete priority */); /* ABSOLVED */
797
/* there might be values added or specifically deleted later than
798
* the current attr delete operation. These values need to be
799
* preserved, all others can be removed, purging should o the job.
801
valueset_purge(&a->a_present_values, csn);
802
valueset_purge(&a->a_deleted_values, csn);
803
if(attr_state==ATTRIBUTE_PRESENT && valueset_isempty(&a->a_present_values))
804
entry_present_attribute_to_deleted_attribute(e, a);
548
if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
550
/* We don't maintain a deleted value list for single valued attributes */
551
valueset_add_valueset(&a->a_deleted_values, &a->a_present_values); /* JCM Would be better to passin the valuestodelete */
553
808
slapi_valueset_done(&a->a_present_values);
809
slapi_valueset_done(&a->a_deleted_values);
554
810
entry_present_attribute_to_deleted_attribute(e, a);
556
812
retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
827
/* check if values to delete are in present values
828
* if v in present values and VU-csn<csn and v not distinguished move to deleted values
829
* if v not in present values, check deleted values and update csn, if distinguisehed at csn
830
* move back to present values
571
834
Slapi_Value **valuesupdated= NULL;
572
valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
573
/* if we removed the last value, we need to mark the attribute as deleted
574
the resolve_attribute_state() code will "resurrect" the attribute if
575
there are present values with a later CSN - otherwise, even though
576
the value will be updated with a VDCSN which is later than the VUCSN,
577
the attribute will not be deleted */
578
if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated &&
581
attr_set_deletion_csn(a,csn);
583
valuearray_free(&valuesupdated);
584
valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
585
valuearray_free(&valuesupdated);
835
valueset_update_csn_for_valuearray_ext(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
836
resolve_attribute_state_present_to_deleted(e, a, valuesupdated);
837
valuearray_free(&valuesupdated);
839
valueset_update_csn_for_valuearray_ext(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
840
resolve_attribute_state_deleted_to_present(e, a, valuesupdated);
841
valuearray_free(&valuesupdated);
586
843
valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
587
valueset_add_valuearray_ext(&a->a_deleted_values, valuestodelete, SLAPI_VALUE_FLAG_PASSIN);
844
slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
845
if(attr_state==ATTRIBUTE_PRESENT && valueset_isempty(&a->a_present_values))
846
entry_present_attribute_to_deleted_attribute(e, a);
588
847
/* all the elements in valuestodelete are passed;
589
848
* should free valuestodelete only (don't call valuearray_free)
591
850
slapi_ch_free((void **)&valuestodelete);
592
resolve_attribute_state(e, a, attr_state, 0);
593
851
retVal= LDAP_SUCCESS;
855
/* find the values to delete in present values,
856
* update the csns and add to the deleted values
597
858
Slapi_Value **deletedvalues= NULL;
598
859
retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
599
860
if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
601
if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
603
/* We don't maintain a deleted value list for single valued attributes */
604
/* Add each deleted value to the deleted set */
605
valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
606
valueset_add_valuearray_ext(&a->a_deleted_values, deletedvalues, SLAPI_VALUE_FLAG_PASSIN);
607
slapi_ch_free((void **)&deletedvalues);
610
valuearray_free(&deletedvalues);
862
/* Add each deleted value to the deleted set */
863
valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
864
slapi_valueset_add_attr_valuearray_ext (a,
865
&a->a_deleted_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
866
slapi_ch_free((void **)&deletedvalues);
612
867
if(valueset_isempty(&a->a_present_values))
614
869
/* There are no present values, so move the
619
874
else if (retVal != LDAP_SUCCESS)
623
877
* - Value not found
624
878
* - Operations error
626
880
if ( retVal==LDAP_OPERATIONS_ERROR )
628
882
LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
629
"value for attribute type %s found in "
630
"entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
883
"value for attribute type %s found in "
884
"entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
633
887
valuearray_free(&valuestodelete);
637
else if (attr_state==ATTRIBUTE_DELETED)
639
/* If the type is in the forbidden attr list (e.g., unhashed password),
640
* we don't return the reason of the failure to the clients. */
641
#if defined(USE_OLD_UNHASHED)
642
if (is_type_forbidden(type)) {
643
retVal = LDAP_SUCCESS;
645
retVal= LDAP_NO_SUCH_ATTRIBUTE;
648
retVal= LDAP_NO_SUCH_ATTRIBUTE;
651
else if (attr_state==ATTRIBUTE_NOTFOUND)
654
* If type is in the protected_attrs_all list, we could ignore the
655
* failure, as the attribute could only exist in the entry in the
656
* memory when the add/mod operation is done, while the retried entry
657
* from the db does not contain the attribute.
658
* So is in the forbidden_attrs list. We don't return the reason
661
#if defined(USE_OLD_UNHASHED)
662
if (is_type_protected(type) || is_type_forbidden(type))
664
if (is_type_protected(type))
667
retVal = LDAP_SUCCESS;
670
/* Only warn if not urping */
671
LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
674
retVal = LDAP_NO_SUCH_ATTRIBUTE;
676
/* NOTE: LDAP says that a MOD REPLACE with no vals of a non-existent
677
attribute is a no-op - MOD REPLACE with some vals will add the attribute */
678
/* if we are doing a replace with actual values, meaning the result
679
of the mod is that the attribute will have some values, we need to create
680
a dummy attribute for entry_add_present_values_wsi to use, and set
681
the deletion csn to the csn of the current operation */
682
/* note that if LDAP_MOD_REPLACE == mod_op then vals is NULL -
683
see entry_replace_present_values_wsi */
684
if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
686
/* Create a new attribute and set the adcsn */
687
Slapi_Attr *a = slapi_attr_new();
688
slapi_attr_init(a, type);
689
attr_set_deletion_csn(a,csn);
690
/* mark the attribute as deleted - it does not really
691
exist yet - the code in entry_add_present_values_wsi
692
will add it back to the present list in the non urp case,
693
or determine if the attribute needs to be added
694
or not in the urp case
696
entry_add_deleted_attribute_wsi(e, a);
699
890
return( retVal );
767
958
for (aiep = attrs_in_extension; aiep && aiep->ext_type; aiep++) {
768
959
if (0 == strcasecmp(mod->mod_type, aiep->ext_type)) {
771
Slapi_Value **ext_vals = NULL;
772
rc = slapi_pw_get_entry_ext(e, &ext_vals);
774
continue; /* skip it. */
962
/* remove the attribute from the attr list */
777
963
a = attrlist_remove(&e->e_attrs, mod->mod_type);
778
964
if (a && a->a_present_values.va) {
779
965
/* a->a_present_values.va is consumed if successful. */
780
rc = slapi_pw_set_entry_ext(e, a->a_present_values.va,
781
SLAPI_EXT_SET_REPLACE);
966
int rc = slapi_pw_set_entry_ext(e, a->a_present_values.va,
967
SLAPI_EXT_SET_REPLACE);
782
968
if (LDAP_SUCCESS == rc) {
783
969
/* va is set to entry extension; just release the rest */
784
970
a->a_present_values.va = NULL;
786
972
slapi_attr_free(&a);
974
Slapi_Value **ext_vals = NULL;
975
slapi_pw_get_entry_ext(e, &ext_vals);
789
977
/* slapi_pw_set_entry_ext frees the stored extension */
790
rc = slapi_pw_set_entry_ext(e, NULL, SLAPI_EXT_SET_REPLACE);
978
slapi_pw_set_entry_ext(e, NULL, SLAPI_EXT_SET_REPLACE);
1047
resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
1050
const CSN *adcsn= attr_get_deletion_csn(a);
1051
Slapi_ValueSet *vs= valueset_dup(&a->a_present_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
1054
/* Loop over the present attribute values */
1055
i= slapi_valueset_first_value( vs, &v );
1060
const CSN *deletedcsn;
1061
/* This call ensures that the value does not contain a deletion_csn
1062
* which is before the presence_csn or distinguished_csn of the value.
1064
purge_attribute_state_multi_valued(a, v);
1065
vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
1066
vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
1067
deletedcsn= csn_max(vdcsn, adcsn);
1069
/* Check if the attribute or value was deleted after the value was
1070
* last updated. If the value update CSN and the deleted CSN are
1071
* the same (meaning they are separate mods from the same exact
1072
* operation), we should only delete the value if delete priority
1073
* is set. Delete priority should only be set when we are deleting
1074
* all value of an attribute. This prevents us from leaving a value
1075
* that was added as a previous mod in the same exact modify
1076
* operation as the subsequent delete.*/
1077
if((csn_compare(vucsn,deletedcsn)<0) ||
1078
(delete_priority && (csn_compare(vucsn,deletedcsn) == 0)))
1080
if(!value_distinguished_at_csn(e, a, v, deletedcsn))
1082
entry_present_value_to_deleted_value(a,v);
1085
i= slapi_valueset_next_value( vs, i, &v );
1087
slapi_valueset_free(vs);
1089
/* Loop over the deleted attribute values */
1090
vs= valueset_dup(&a->a_deleted_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
1091
i= slapi_valueset_first_value( vs, &v );
1096
const CSN *deletedcsn;
1097
/* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */
1098
purge_attribute_state_multi_valued(a, v);
1099
vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
1100
vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
1101
deletedcsn= csn_max(vdcsn, adcsn);
1103
/* check if the attribute or value was deleted after the value was last updated */
1104
/* When a replace operation happens, the entry_replace_present_values_wsi() function
1105
* first calls entry_delete_present_values_wsi with vals == NULL to essentially delete
1106
* the attribute and set the deletion csn. If the urp flag is set (urp in this case
1107
* meaning the operation is a replicated op), entry_delete_present_values_wsi will
1108
* call this function which will move the present values to the deleted values
1109
* (see above - delete_priority will be 1) then the below code will move the
1110
* attribute to the deleted list.
1111
* next, entry_replace_present_values_wsi will call entry_add_present_values_wsi
1112
* to add the values provided in the replace operation. We need to be able to
1113
* "resurrect" these deleted values and resurrect the deleted attribute. In the
1114
* replace case, the deletedcsn will be the same as the vucsn of the values that
1115
* should be present values.
1117
if((csn_compare(vucsn,deletedcsn)>0) ||
1118
((delete_priority == 0) && (csn_compare(vucsn,deletedcsn)==0)) ||
1119
value_distinguished_at_csn(e, a, v, deletedcsn))
1121
entry_deleted_value_to_present_value(a,v);
1123
i= slapi_valueset_next_value( vs, i, &v );
1125
slapi_valueset_free(vs);
1234
/* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */
1236
resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
1240
const CSN *deletedcsn;
1241
const CSN *adcsn= attr_get_deletion_csn(a);
1243
if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
1244
for (i=0;valuestoupdate[i]!=NULL;++i) {
1245
purge_attribute_state_multi_valued(a, valuestoupdate[i]);
1246
vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
1247
vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
1248
deletedcsn= csn_max(vdcsn, adcsn);
1249
if((csn_compare(vucsn,deletedcsn)>=0) ||
1250
value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
1252
entry_deleted_value_to_present_value(a,valuestoupdate[i]);
1254
valuestoupdate[i]->v_csnset = NULL;
1260
resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state)
1264
const CSN *deletedcsn;
1265
const CSN *adcsn= attr_get_deletion_csn(a);
1267
if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
1268
for (i=0;valuestoupdate[i]!=NULL;++i) {
1269
purge_attribute_state_multi_valued(a, valuestoupdate[i]);
1270
vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
1271
vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
1272
deletedcsn= csn_max(vdcsn, adcsn);
1273
if((csn_compare(vucsn,deletedcsn)>=0) ||
1274
value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
1276
slapi_valueset_add_value_ext(&a->a_present_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
1278
slapi_valueset_add_value_ext(&a->a_deleted_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
1127
1282
if(valueset_isempty(&a->a_present_values))
1129
1284
if(attribute_state==ATTRIBUTE_PRESENT)
1299
resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
1303
const CSN *deletedcsn;
1304
const CSN *adcsn= attr_get_deletion_csn(a);
1306
if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
1307
for (i=0;valuestoupdate[i]!=NULL;++i) {
1308
/* This call ensures that the value does not contain a deletion_csn
1309
* which is before the presence_csn or distinguished_csn of the value.
1311
purge_attribute_state_multi_valued(a, valuestoupdate[i]);
1312
vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
1313
vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
1314
deletedcsn= csn_max(vdcsn, adcsn);
1315
if(csn_compare(vucsn,deletedcsn)<0)
1317
if(!value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
1319
entry_present_value_to_deleted_value(a,valuestoupdate[i]);
1322
valuestoupdate[i]->v_csnset = NULL;
1144
1328
resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
1146
1330
Slapi_Value *current_value= NULL;
1161
1346
slapi_attr_next_value(a,i,&new_value);
1163
1348
attr_first_deleted_value(a,&pending_value);
1165
1349
/* purge_attribute_state_single_valued */
1166
1350
adcsn= attr_get_deletion_csn(a);
1167
1351
current_value_vucsn= value_get_csn(current_value, CSN_TYPE_VALUE_UPDATED);
1168
1352
pending_value_vucsn= value_get_csn(pending_value, CSN_TYPE_VALUE_UPDATED);
1169
if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
1170
(pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1353
pending_value_vdcsn= value_get_csn(pending_value, CSN_TYPE_VALUE_DELETED);
1354
if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
1355
(pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1172
1357
attr_set_deletion_csn(a,NULL);
1178
/* check if the pending value should become the current value */
1179
if(pending_value!=NULL)
1361
/* in the case of the following:
1364
* we will have current_value with VUCSN CSN1
1365
* and pending_value with VDCSN CSN2
1366
* and new_value == NULL
1367
* current_value != pending_value
1369
* VUCSN == VDCSN (ignoring subseq)
1370
* even though value1.VDCSN > value2.VUCSN
1371
* value2 should still win because the value is _different_
1373
if (current_value && pending_value && !new_value && !adcsn &&
1374
(0 != slapi_value_compare(a, current_value, pending_value)) &&
1375
(0 == csn_compare_ext(current_value_vucsn, pending_value_vdcsn, CSN_COMPARE_SKIP_SUBSEQ)))
1377
/* just remove the deleted value */
1378
entry_deleted_value_to_zapped_value(a,pending_value);
1379
pending_value = NULL;
1381
else if(new_value==NULL)
1383
/* check if the pending value should become the current value */
1384
if(pending_value!=NULL)
1181
1386
if(!value_distinguished_at_csn(e,a,current_value,pending_value_vucsn))
1183
/* attribute.current_value = attribute.pending_value; */
1184
/* attribute.pending_value = NULL; */
1388
/* attribute.current_value = attribute.pending_value; */
1389
/* attribute.pending_value = NULL; */
1185
1390
entry_present_value_to_zapped_value(a,current_value);
1186
1391
entry_deleted_value_to_present_value(a,pending_value);
1187
1392
current_value= pending_value;
1236
/* new_value= NULL */
1441
/* new_value= NULL */
1237
1442
entry_present_value_to_zapped_value(a, new_value);
1238
1443
new_value= NULL;
1241
else /* new value is after the current value */
1446
else /* new value is after the current value */
1243
if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
1448
if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
1245
/* attribute.current_value = new_value */
1450
/* attribute.current_value = new_value */
1246
1451
entry_present_value_to_zapped_value(a, current_value);
1247
1452
current_value= new_value;
1248
1453
new_value= NULL;
1249
1454
current_value_vucsn= new_value_vucsn;
1251
else /* value is distinguished - check if we should replace the current pending value */
1456
else /* value is distinguished - check if we should replace the current pending value */
1253
if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
1458
if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
1255
/* attribute.pending_value = new_value */
1460
/* attribute.pending_value = new_value */
1256
1461
entry_deleted_value_to_zapped_value(a,pending_value);
1257
1462
entry_present_value_to_deleted_value(a,new_value);
1258
1463
pending_value= new_value;
1259
1464
new_value= NULL;
1260
1465
pending_value_vucsn= new_value_vucsn;
1267
* This call ensures that the attribute does not have a pending_value
1472
* This call ensures that the attribute does not have a pending_value
1268
1473
* or a deletion_csn that is earlier than the current_value.
1270
1475
/* purge_attribute_state_single_valued */
1271
if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
1272
(pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1476
if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
1477
(pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1274
1479
attr_set_deletion_csn(a,NULL);
1278
/* set attribute state */
1279
if(current_value==NULL)
1483
/* set attribute state */
1484
if(current_value==NULL)
1281
1486
if(attribute_state==ATTRIBUTE_PRESENT)
1283
1488
entry_present_attribute_to_deleted_attribute(e, a);
1288
1493
if(attribute_state==ATTRIBUTE_DELETED)
1290
1495
entry_deleted_attribute_to_present_attribute(e, a);
1296
resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
1298
if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
1300
resolve_attribute_state_single_valued(e,a,attribute_state);
1304
resolve_attribute_state_multi_valued(e,a,attribute_state, delete_priority);