]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
Partial revert of f30269f5d2e4bb5ee7486fe6542078d1b59dba6d
[openldap] / servers / slapd / syncrepl.c
index 3fd5489e536ca11afe296f754e9b47889ce7ab1e..39382881a1f2109a1edf60e4ae4e1b6a989576ca 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2011 The OpenLDAP Foundation.
+ * Copyright 2003-2012 The OpenLDAP Foundation.
  * Portions Copyright 2003 by IBM Corporation.
  * Portions Copyright 2003-2008 by Howard Chu, Symas Corporation.
  * All rights reserved.
@@ -2636,7 +2636,7 @@ typedef struct dninfo {
        int delOldRDN;  /* Was old RDN deleted? */
        Modifications **modlist;        /* the modlist we received */
        Modifications *mods;    /* the modlist we compared */
-       Attribute *oldNattr;    /* old naming attr */
+       int oldNcount;          /* #values of old naming attr */
        AttributeDescription *oldDesc;  /* for renames */
        AttributeDescription *newDesc;  /* for renames */
 } dninfo;
@@ -2820,6 +2820,23 @@ syncrepl_entry(
                                 */
                                op->o_csn = a->a_vals[0];
                                freecsn = 0;
+                               /* There was no cookie CSN attached to this op,
+                                * make sure it's new enough
+                                */
+                               if ( !syncCSN ) {
+                                       int i, sid = slap_parse_csn_sid( &a->a_vals[0] );
+                                       for ( i = 0; i<si->si_cookieState->cs_num; i++ ) {
+                                               if ( sid < si->si_cookieState->cs_sids[i] )
+                                                       break;
+                                               if ( sid == si->si_cookieState->cs_sids[i] ) {
+                                                       if ( ber_bvcmp( &a->a_vals[0], &si->si_cookieState->cs_vals[i] ) <= 0 ) {
+                                                               Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s entryCSN too old, ignoring %s (%s)\n",
+                                                               si->si_ridtxt, a->a_vals[0].bv_val, entry->e_name.bv_val );
+                                                               goto done;
+                                                       }
+                                               }
+                                       }
+                               }
                        }
                }
 retry_add:;
@@ -2846,8 +2863,24 @@ retry_add:;
 
                        case LDAP_REFERRAL:
                        /* we assume that LDAP_NO_SUCH_OBJECT is returned 
-                        * only if the suffix entry is not present */
+                        * only if the suffix entry is not present.
+                        * This should not happen during Persist phase.
+                        */
                        case LDAP_NO_SUCH_OBJECT:
+                               if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST &&
+                                       si->si_refreshDone ) {
+                                       /* Something's wrong, start over */
+                                       ber_bvarray_free( si->si_syncCookie.ctxcsn );
+                                       si->si_syncCookie.ctxcsn = NULL;
+                                       ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+                                       ber_bvarray_free( si->si_cookieState->cs_vals );
+                                       ch_free( si->si_cookieState->cs_sids );
+                                       si->si_cookieState->cs_vals = NULL;
+                                       si->si_cookieState->cs_sids = 0;
+                                       si->si_cookieState->cs_num = 0;
+                                       ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+                                       return LDAP_NO_SUCH_OBJECT;
+                               }
                                rc = syncrepl_add_glue( op, entry );
                                entry = NULL;
                                break;
@@ -2938,10 +2971,10 @@ retry_add:;
                         * If delOldRDN is TRUE then we should see a delete modop
                         * for oldDesc. We might see a replace instead.
                         *  delete with no values: therefore newDesc != oldDesc.
-                        *   if oldNattr had only one value, then Drop this op.
+                        *   if oldNcount == 1, then Drop this op.
                         *  delete with 1 value: can only be the oldRDN value. Drop op.
                         *  delete with N values: Drop oldRDN value, keep remainder.
-                        *  replace with 1 value: if oldNattr had only one value and
+                        *  replace with 1 value: if oldNcount == 1 and
                         *     newDesc == oldDesc, Drop this op.
                         * Any other cases must be left intact.
                         *
@@ -2962,7 +2995,7 @@ retry_add:;
                                                        continue;
                                                }
                                                if ( mod->sml_numvals <= 1 &&
-                                                       dni.oldNattr->a_numvals == 1 &&
+                                                       dni.oldNcount == 1 &&
                                                        ( mod->sml_op == LDAP_MOD_DELETE ||
                                                          mod->sml_op == LDAP_MOD_REPLACE )) {
                                                        if ( mod->sml_op == LDAP_MOD_REPLACE )
@@ -3165,6 +3198,8 @@ retry_modrdn:;
                        Debug( LDAP_DEBUG_SYNC,
                                        "syncrepl_entry: %s be_delete %s (%d)\n", 
                                        si->si_ridtxt, op->o_req_dn.bv_val, rc );
+                       if ( rc == LDAP_NO_SUCH_OBJECT )
+                               rc = LDAP_SUCCESS;
 
                        while ( rs_delete.sr_err == LDAP_SUCCESS
                                && op->o_delete_glue_parent ) {
@@ -4117,7 +4152,10 @@ dn_callback(
                                        dni->oldDesc = ad;
                                        for ( oldpos=0, a=rs->sr_entry->e_attrs;
                                                a && a->a_desc != ad; oldpos++, a=a->a_next );
-                                       dni->oldNattr = a;
+                                       /* a should not be NULL but apparently it happens.
+                                        * ITS#7144
+                                        */
+                                       dni->oldNcount = a ? a->a_numvals : 0;
                                        for ( newpos=0, a=dni->new_entry->e_attrs;
                                                a && a->a_desc != ad; newpos++, a=a->a_next );
                                        if ( !a || oldpos != newpos || attr_valfind( a,
@@ -5496,13 +5534,13 @@ syncrepl_config( ConfigArgs *c )
                                                                ldap_pvt_runqueue_stoptask( &slapd_rq, re );
                                                                isrunning = 1;
                                                        }
-                                                       ldap_pvt_runqueue_remove( &slapd_rq, re );
-                                                       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-
                                                        if ( ldap_pvt_thread_pool_retract( &connection_pool,
                                                                        re->routine, re ) > 0 )
                                                                isrunning = 0;
 
+                                                       ldap_pvt_runqueue_remove( &slapd_rq, re );
+                                                       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+
                                                        ldap_pvt_thread_mutex_unlock( &si->si_mutex );
                                                }
                                        }