ITS#9751 Do not drop out of order deletes completely

This commit is contained in:
Ondřej Kuzník 2021-11-17 15:54:22 +00:00 committed by Quanah Gibson-Mount
parent 74ed5163ed
commit 70e6bd6777

View file

@ -2580,6 +2580,7 @@ static Modifications *mods_dup( Operation *op, Modifications *modlist, int match
typedef struct resolve_ctxt {
syncinfo_t *rx_si;
Entry *rx_entry;
Modifications *rx_mods;
} resolve_ctxt;
@ -2624,6 +2625,7 @@ syncrepl_resolve_cb( Operation *op, SlapReply *rs )
Attribute *a = attr_find( rs->sr_entry->e_attrs, ad_reqMod );
if ( a ) {
Modifications *oldmods, *newmods, *m1, *m2, **prev;
Entry *e = rx->rx_entry;
oldmods = rx->rx_mods;
syncrepl_accesslog_mods( rx->rx_si, a->a_vals, &newmods );
for ( m2 = newmods; m2; m2=m2->sml_next ) {
@ -2664,14 +2666,51 @@ drop:
if ( m2->sml_op == LDAP_MOD_ADD ||
m2->sml_op == LDAP_MOD_REPLACE ) {
if ( m1->sml_op == LDAP_MOD_DELETE ) {
if ( !m1->sml_numvals ) goto drop;
compare_vals( m1, m2 );
if ( !m1->sml_numvals )
goto drop;
}
if ( m2->sml_desc->ad_type->sat_atype.at_single_value )
goto drop;
if ( m1->sml_op == LDAP_MOD_DELETE ) {
if ( m2->sml_op == LDAP_MOD_REPLACE ) {
goto drop;
}
if ( !m1->sml_numvals ) {
Modifications *m;
unsigned int size, i;
/*
* ITS#9751 An ADD might supersede parts of
* this delete, but we still need to honour the
* rest. Keep resolving as if it was deleting
* specific values
*/
a = attr_find( e->e_attrs, m1->sml_desc );
if ( !a ) {
goto drop;
}
size = (a->a_numvals+1) * sizeof(struct berval);
if ( a->a_nvals ) size *= 2;
size += sizeof(Modifications);
m = op->o_tmpalloc( size, op->o_tmpmemctx );
*m = *m1;
m->sml_numvals = a->a_numvals;
m->sml_values = (BerVarray)(m+1);
for ( i=0; i < a->a_numvals; i++ )
m->sml_values[i] = a->a_vals[i];
BER_BVZERO( &m->sml_values[i] );
if ( a->a_nvals ) {
m->sml_nvalues = m->sml_values + m->sml_numvals + 1;
for ( i=0; i < a->a_numvals; i++ )
m->sml_nvalues[i] = a->a_nvals[i];
BER_BVZERO( &m->sml_nvalues[i] );
} else {
m->sml_nvalues = NULL;
}
op->o_tmpfree( m1, op->o_tmpmemctx );
*prev = m1 = m;
}
}
compare_vals( m1, m2 );
if ( !m1->sml_numvals )
goto drop;
@ -2689,6 +2728,7 @@ drop:
typedef struct modify_ctxt {
Modifications *mx_orig;
Modifications *mx_free;
Entry *mx_entry;
} modify_ctxt;
static int
@ -2704,6 +2744,9 @@ syncrepl_modify_cb( Operation *op, SlapReply *rs )
mx->mx_free = ml->sml_next;
op->o_tmpfree( ml, op->o_tmpmemctx );
}
if ( mx->mx_entry ) {
entry_free( mx->mx_entry );
}
op->o_callback = sc->sc_next;
op->o_tmpfree( sc, op->o_tmpmemctx );
return SLAP_CB_CONTINUE;
@ -2715,7 +2758,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
OpExtra *oex;
syncinfo_t *si;
Entry *e;
Entry *e, *e_dup;
int rc, match = 0;
Modifications *mod, *newlist;
@ -2769,6 +2812,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
/* no entryCSN? shouldn't happen. assume mod is newer. */
match = 1;
}
e_dup = entry_dup( e );
overlay_entry_release_ov( op, e, 0, on );
} else {
return SLAP_CB_CONTINUE;
@ -2779,6 +2823,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
slap_graduate_commit_csn( op );
/* tell accesslog this was a failure */
rs->sr_err = LDAP_TYPE_OR_VALUE_EXISTS;
entry_free( e_dup );
return LDAP_SUCCESS;
}
@ -2793,7 +2838,8 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
* delete X delete all drop
* delete X delete X drop
* delete X delete Y OK
* delete all add X drop
* delete all add X convert to delete current values,
* drop delete X from it
* delete X add X drop
* delete X add Y OK
* add X delete all drop
@ -2826,6 +2872,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
AttributeAssertion aa[2] = {0};
rx.rx_si = si;
rx.rx_entry = e_dup;
rx.rx_mods = newlist;
cb.sc_private = &rx;
@ -2888,6 +2935,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
op->orm_no_opattrs = 1;
mx->mx_orig = op->orm_modlist;
mx->mx_free = newlist;
mx->mx_entry = e_dup;
for ( ml = newlist; ml; ml=ml->sml_next ) {
if ( ml->sml_flags == SLAP_MOD_INTERNAL ) {
ml->sml_flags = 0;
@ -2902,6 +2950,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
op->orm_modlist = newlist;
op->o_csn = mod->sml_nvalues[0];
}
return SLAP_CB_CONTINUE;
}