]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/refint.c
ITS#6056 refint fix
[openldap] / servers / slapd / overlays / refint.c
index 13c520ecc6992103f69922c602d0c9e7db31752f..a9c0e50c5be66dd42594a0be46713543148d85de 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2008 The OpenLDAP Foundation.
+ * Copyright 2004-2009 The OpenLDAP Foundation.
  * Portions Copyright 2004 Symas Corporation.
  * All rights reserved.
  *
@@ -81,6 +81,8 @@ typedef struct refint_data_s {
        BerValue dn;                            /* basedn in parent, */
        BerValue nothing;                       /* the nothing value, if needed */
        BerValue nnothing;                      /* normalized nothingness */
+       BerValue refint_dn;                     /* modifier's name */
+       BerValue refint_ndn;                    /* normalized modifier's name */
        struct re_s *qtask;
        refint_q *qhead;
        refint_q *qtail;
@@ -93,7 +95,8 @@ static MatchingRule   *mr_dnSubtreeMatch;
 
 enum {
        REFINT_ATTRS = 1,
-       REFINT_NOTHING
+       REFINT_NOTHING,
+       REFINT_MODIFIERSNAME
 };
 
 static ConfigDriver refint_cf_gen;
@@ -110,6 +113,11 @@ static ConfigTable refintcfg[] = {
          "( OLcfgOvAt:11.2 NAME 'olcRefintNothing' "
          "DESC 'Replacement DN to supply when needed' "
          "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+       { "refint_modifiersName", "DN", 2, 2, 0,
+         ARG_DN|ARG_MAGIC|REFINT_MODIFIERSNAME, refint_cf_gen,
+         "( OLcfgOvAt:11.3 NAME 'olcRefintModifiersName' "
+         "DESC 'The DN to use as modifiersName' "
+         "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
@@ -118,7 +126,10 @@ static ConfigOCs refintocs[] = {
          "NAME 'olcRefintConfig' "
          "DESC 'Referential integrity configuration' "
          "SUP olcOverlayConfig "
-         "MAY ( olcRefintAttribute $ olcRefintNothing ) )",
+         "MAY ( olcRefintAttribute "
+               "$ olcRefintNothing "
+               "$ olcRefintModifiersName "
+         ") )",
          Cft_Overlay, refintcfg },
        { NULL, 0, NULL }
 };
@@ -157,6 +168,17 @@ refint_cf_gen(ConfigArgs *c)
                        }
                        rc = 0;
                        break;
+               case REFINT_MODIFIERSNAME:
+                       if ( !BER_BVISEMPTY( &dd->refint_dn )) {
+                               rc = value_add_one( &c->rvalue_vals,
+                                                   &dd->refint_dn );
+                               if ( rc ) return rc;
+                               rc = value_add_one( &c->rvalue_nvals,
+                                                   &dd->refint_ndn );
+                               return rc;
+                       }
+                       rc = 0;
+                       break;
                default:
                        abort ();
                }
@@ -196,6 +218,15 @@ refint_cf_gen(ConfigArgs *c)
                        dd->nnothing.bv_len = 0;
                        rc = 0;
                        break;
+               case REFINT_MODIFIERSNAME:
+                       if ( dd->refint_dn.bv_val )
+                               ber_memfree ( dd->refint_dn.bv_val );
+                       if ( dd->refint_ndn.bv_val )
+                               ber_memfree ( dd->refint_ndn.bv_val );
+                       dd->refint_dn.bv_len = 0;
+                       dd->refint_ndn.bv_len = 0;
+                       rc = 0;
+                       break;
                default:
                        abort ();
                }
@@ -233,6 +264,15 @@ refint_cf_gen(ConfigArgs *c)
                        dd->nnothing = c->value_ndn;
                        rc = 0;
                        break;
+               case REFINT_MODIFIERSNAME:
+                       if ( dd->refint_dn.bv_val )
+                               ber_memfree ( dd->refint_dn.bv_val );
+                       if ( dd->refint_ndn.bv_val )
+                               ber_memfree ( dd->refint_ndn.bv_val );
+                       dd->refint_dn = c->value_dn;
+                       dd->refint_ndn = c->value_ndn;
+                       rc = 0;
+                       break;
                default:
                        abort ();
                }
@@ -302,6 +342,10 @@ refint_open(
                        return -1;
                ber_dupbv( &id->dn, &be->be_nsuffix[0] );
        }
+       if ( BER_BVISNULL( &id->refint_dn ) ) {
+               ber_dupbv( &id->refint_dn, &refint_dn );
+               ber_dupbv( &id->refint_ndn, &refint_ndn );
+       }
        return(0);
 }
 
@@ -339,6 +383,10 @@ refint_close(
        BER_BVZERO( &id->nothing );
        ch_free( id->nnothing.bv_val );
        BER_BVZERO( &id->nnothing );
+       ch_free( id->refint_dn.bv_val );
+       BER_BVZERO( &id->refint_dn );
+       ch_free( id->refint_ndn.bv_val );
+       BER_BVZERO( &id->refint_ndn );
 
        return(0);
 }
@@ -499,7 +547,7 @@ refint_repair(
        refint_data     *id,
        refint_q        *rq )
 {
-       dependent_data  *dp, *dp_next;
+       dependent_data  *dp;
        int             rc;
 
        op->o_callback->sc_response = refint_search_cb;
@@ -538,13 +586,11 @@ refint_repair(
         *
         */
 
-       for ( dp = rq->attrs; dp; dp = dp_next ) {
+       for ( dp = rq->attrs; dp; dp = dp->next ) {
                Operation       op2 = *op;
                SlapReply       rs2 = { 0 };
                refint_attrs    *ra;
-               Modifications   *m, *first = NULL;
-
-               dp_next = dp->next;
+               Modifications   *m;
 
                op2.o_tag = LDAP_REQ_MODIFY;
                op2.orm_modlist = NULL;
@@ -555,21 +601,18 @@ refint_repair(
                        Debug( LDAP_DEBUG_TRACE,
                                "refint_repair: no backend for DN %s!\n",
                                dp->dn.bv_val, 0, 0 );
-                       return 0;
+                       continue;
                }
 
                rs2.sr_type = REP_RESULT;
-               for ( ra = dp->attrs; ra; ra = dp->attrs ) {
+               for ( ra = dp->attrs; ra; ra = ra->next ) {
                        size_t  len;
 
-                       dp->attrs = ra->next;
                        /* 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;
-                               if ( !first )
-                                       first = m;
                                op2.orm_modlist = m;
                                m->sml_op = LDAP_MOD_REPLACE;
                                m->sml_flags = SLAP_MOD_INTERNAL;
@@ -580,8 +623,8 @@ refint_repair(
                                m->sml_nvalues = m->sml_values+2;
                                BER_BVZERO( &m->sml_values[1] );
                                BER_BVZERO( &m->sml_nvalues[1] );
-                               m->sml_values[0] = refint_dn;
-                               m->sml_nvalues[0] = refint_ndn;
+                               m->sml_values[0] = id->refint_dn;
+                               m->sml_nvalues[0] = id->refint_ndn;
                        }
                        if ( !BER_BVISEMPTY( &rq->newdn ) || ( ra->next &&
                                ra->attr == ra->next->attr ) )
@@ -594,8 +637,6 @@ refint_repair(
 
                                m = op2.o_tmpalloc( len, op2.o_tmpmemctx );
                                m->sml_next = op2.orm_modlist;
-                               if ( !first )
-                                       first = m;
                                op2.orm_modlist = m;
                                m->sml_op = LDAP_MOD_ADD;
                                m->sml_flags = 0;
@@ -608,9 +649,6 @@ refint_repair(
                                        BER_BVZERO( &m->sml_nvalues[1] );
                                        m->sml_numvals = 1;
                                        if ( BER_BVISEMPTY( &rq->newdn ) ) {
-                                               op2.o_tmpfree( ra, op2.o_tmpmemctx );
-                                               ra = dp->attrs;
-                                               dp->attrs = ra->next;
                                                m->sml_values[0] = id->nothing;
                                                m->sml_nvalues[0] = id->nnothing;
                                        } else {
@@ -632,8 +670,6 @@ refint_repair(
                        m = op2.o_tmpalloc( len, op2.o_tmpmemctx );
                        m->sml_next = op2.orm_modlist;
                        op2.orm_modlist = m;
-                       if ( !first )
-                               first = m;
                        m->sml_op = LDAP_MOD_DELETE;
                        m->sml_flags = 0;
                        m->sml_desc = ra->attr;
@@ -651,7 +687,6 @@ refint_repair(
                                m->sml_nvalues = ra->old_nvals;
                                m->sml_numvals = ra->ra_numvals;
                        }
-                       op2.o_tmpfree( ra, op2.o_tmpmemctx );
                }
 
                op2.o_dn = op2.o_bd->be_rootdn;
@@ -665,17 +700,8 @@ refint_repair(
 
                while ( ( m = op2.orm_modlist ) ) {
                        op2.orm_modlist = m->sml_next;
-                       if ( m->sml_values && m->sml_values != (BerVarray)(m+1) ) {
-                               ber_bvarray_free_x( m->sml_values, op2.o_tmpmemctx );
-                               ber_bvarray_free_x( m->sml_nvalues, op2.o_tmpmemctx );
-                       }
                        op2.o_tmpfree( m, op2.o_tmpmemctx );
-                       if ( m == first ) break;
                }
-               slap_mods_free( op2.orm_modlist, 1 );
-               op2.o_tmpfree( dp->ndn.bv_val, op2.o_tmpmemctx );
-               op2.o_tmpfree( dp->dn.bv_val, op2.o_tmpmemctx );
-               op2.o_tmpfree( dp, op2.o_tmpmemctx );
        }
 
        return 0;
@@ -728,6 +754,9 @@ refint_qtask( void *ctx, void *arg )
        }
 
        for (;;) {
+               dependent_data  *dp, *dp_next;
+               refint_attrs *ra, *ra_next;
+
                /* Dequeue an op */
                ldap_pvt_thread_mutex_lock( &id->qmutex );
                rq = id->qhead;
@@ -781,6 +810,21 @@ refint_qtask( void *ctx, void *arg )
                        }
                }
 
+               for ( dp = rq->attrs; dp; dp = dp_next ) {
+                       dp_next = dp->next;
+                       for ( ra = dp->attrs; ra; ra = ra_next ) {
+                               ra_next = ra->next;
+                               ber_bvarray_free_x( ra->new_nvals, op->o_tmpmemctx );
+                               ber_bvarray_free_x( ra->new_vals, op->o_tmpmemctx );
+                               ber_bvarray_free_x( ra->old_nvals, op->o_tmpmemctx );
+                               ber_bvarray_free_x( ra->old_vals, op->o_tmpmemctx );
+                               op->o_tmpfree( ra, op->o_tmpmemctx );
+                       }
+                       op->o_tmpfree( dp->ndn.bv_val, op->o_tmpmemctx );
+                       op->o_tmpfree( dp->dn.bv_val, op->o_tmpmemctx );
+                       op->o_tmpfree( dp, op->o_tmpmemctx );
+               }
+
                if ( !BER_BVISNULL( &rq->newndn )) {
                        ch_free( rq->newndn.bv_val );
                        ch_free( rq->newdn.bv_val );