From 0155665ab85834fa0595aa53bafc12d7c37cb790 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount <quanah@openldap.org> Date: Tue, 4 Jan 2011 00:43:16 +0000 Subject: [PATCH] ITS#6730 --- CHANGES | 1 + servers/slapd/overlays/refint.c | 107 +++++++++++++++----------------- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/CHANGES b/CHANGES index 02f25b2aa1..50aac39e74 100644 --- a/CHANGES +++ b/CHANGES @@ -50,6 +50,7 @@ OpenLDAP 2.4.24 Engineering Fixed slapo-pcache to ignore undefined attrs (ITS#6600) Fixed slapo-ppolicy don't update opattrs on consumers (ITS#6608) Fixed slapo-refint when last group member is deleted (ITS#6663) + Fixed slapo-refint with subtree rename (ITS#6730) Fixed slapo-sssvlv initialization (ITS#6649) Fixed slapo-syncprov to send error if consumer is newer (ITS#6606) Fixed slapo-syncprov filter race condition (ITS#6708) diff --git a/servers/slapd/overlays/refint.c b/servers/slapd/overlays/refint.c index c1a8252765..1207bfaa49 100644 --- a/servers/slapd/overlays/refint.c +++ b/servers/slapd/overlays/refint.c @@ -416,6 +416,8 @@ refint_search_cb( ** if this attr exists in the search result, ** and it has a value matching the target: ** allocate an attr; + ** save/build DNs of any subordinate matches; + ** handle special case: found exact + subordinate match; ** handle olcRefintNothing; ** */ @@ -428,12 +430,20 @@ refint_search_cb( ip->attrs = NULL; for(ia = da; ia; ia = ia->next) { if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) ) { - int first = -1, count = 0, deleted = 0; + int exact = -1, is_exact; na = NULL; for(i = 0, b = a->a_nvals; b[i].bv_val; i++) { if(dnIsSuffix(&b[i], &rq->oldndn)) { + is_exact = b[i].bv_len == rq->oldndn.bv_len; + + /* Paranoia: skip buggy duplicate exact match, + * it would break ra_numvals + */ + if ( is_exact && exact >= 0 ) + continue; + /* first match? create structure */ if ( na == NULL ) { na = op->o_tmpcalloc( 1, @@ -442,78 +452,62 @@ refint_search_cb( na->next = ip->attrs; ip->attrs = na; na->attr = ia->attr; - - /* delete, or exact match? note it's first match */ - if ( BER_BVISEMPTY( &rq->newdn ) && - b[i].bv_len == rq->oldndn.bv_len ) - { - first = i; - } } - /* if it's a rename, or a subordinate match, - * save old and build new dn */ - if ( !BER_BVISEMPTY( &rq->newdn ) && - b[i].bv_len != rq->oldndn.bv_len ) - { - struct berval newsub, newdn, olddn, oldndn; - - /* if not first, save first as well */ - if ( first != -1 ) { - - ber_dupbv_x( &olddn, &a->a_vals[first], op->o_tmpmemctx ); - ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx ); - ber_dupbv_x( &oldndn, &a->a_nvals[first], op->o_tmpmemctx ); - ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx ); - na->ra_numvals++; - - newsub = a->a_vals[first]; - newsub.bv_len -= rq->olddn.bv_len + 1; - - build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx ); + na->ra_numvals++; - ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx ); + if ( is_exact ) { + /* Exact match: refint_repair will deduce the DNs */ + exact = i; - newsub = a->a_nvals[first]; - newsub.bv_len -= rq->oldndn.bv_len + 1; - - build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx ); - - ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx ); - - first = -1; - } + } else { + /* Subordinate match */ + struct berval newsub, newdn, olddn, oldndn; + /* Save old DN */ ber_dupbv_x( &olddn, &a->a_vals[i], op->o_tmpmemctx ); ber_bvarray_add_x( &na->old_vals, &olddn, op->o_tmpmemctx ); + ber_dupbv_x( &oldndn, &a->a_nvals[i], op->o_tmpmemctx ); ber_bvarray_add_x( &na->old_nvals, &oldndn, op->o_tmpmemctx ); - na->ra_numvals++; + if ( BER_BVISEMPTY( &rq->newdn ) ) + continue; + + /* Rename subordinate match: Build new DN */ newsub = a->a_vals[i]; newsub.bv_len -= rq->olddn.bv_len + 1; - build_new_dn( &newdn, &rq->newdn, &newsub, op->o_tmpmemctx ); - ber_bvarray_add_x( &na->new_vals, &newdn, op->o_tmpmemctx ); newsub = a->a_nvals[i]; newsub.bv_len -= rq->oldndn.bv_len + 1; - build_new_dn( &newdn, &rq->newndn, &newsub, op->o_tmpmemctx ); - ber_bvarray_add_x( &na->new_nvals, &newdn, op->o_tmpmemctx ); } + } + } - /* count deletes */ - if ( BER_BVISEMPTY( &rq->newdn ) ) { - deleted++; - } + /* If we got both subordinate and exact match, + * refint_repair won't special-case the exact match */ + if ( exact >= 0 && na->old_vals ) { + struct berval dn; + + ber_dupbv_x( &dn, &a->a_vals[exact], op->o_tmpmemctx ); + ber_bvarray_add_x( &na->old_vals, &dn, op->o_tmpmemctx ); + ber_dupbv_x( &dn, &a->a_nvals[exact], op->o_tmpmemctx ); + ber_bvarray_add_x( &na->old_nvals, &dn, op->o_tmpmemctx ); + + if ( !BER_BVISEMPTY( &rq->newdn ) ) { + ber_dupbv_x( &dn, &rq->newdn, op->o_tmpmemctx ); + ber_bvarray_add_x( &na->new_vals, &dn, op->o_tmpmemctx ); + ber_dupbv_x( &dn, &rq->newndn, op->o_tmpmemctx ); + ber_bvarray_add_x( &na->new_nvals, &dn, op->o_tmpmemctx ); } } /* Deleting/replacing all values and a nothing DN is configured? */ - if ( deleted == i && na && !BER_BVISNULL(&dd->nothing) ) + if ( na && na->ra_numvals == i && !BER_BVISNULL(&dd->nothing) ) na->dont_empty = 1; Debug( LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s (#%d)\n", @@ -572,10 +566,12 @@ refint_repair( for ( dp = rq->attrs; dp; dp = dp->next ) { Operation op2 = *op; - SlapReply rs2 = { 0 }; + SlapReply rs2 = {REP_RESULT}; refint_attrs *ra; Modifications *m; + if ( dp->attrs == NULL ) continue; /* TODO: Is this needed? */ + op2.o_tag = LDAP_REQ_MODIFY; op2.orm_modlist = NULL; op2.o_req_dn = dp->dn; @@ -588,12 +584,8 @@ refint_repair( continue; } - rs2.sr_type = REP_RESULT; - for ( ra = dp->attrs; ra; ra = ra->next ) { - size_t len; - - /* Set our ModifiersName */ - if ( SLAP_LASTMOD( op->o_bd ) ) { + /* Set our ModifiersName */ + if ( SLAP_LASTMOD( op->o_bd ) ) { m = op2.o_tmpalloc( sizeof(Modifications) + 4*sizeof(BerValue), op2.o_tmpmemctx ); m->sml_next = op2.orm_modlist; @@ -609,7 +601,10 @@ refint_repair( BER_BVZERO( &m->sml_nvalues[1] ); m->sml_values[0] = id->refint_dn; m->sml_nvalues[0] = id->refint_ndn; - } + } + + for ( ra = dp->attrs; ra; ra = ra->next ) { + size_t len; /* Add values */ if ( ra->dont_empty || !BER_BVISEMPTY( &rq->newdn ) ) { -- GitLab