]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
reduce code duplication
[openldap] / servers / slapd / syncrepl.c
index 723732f2e7cb668891c92833b890743a8ef39164..8e54357aee7310e326365a3ef0f8042b724173dd 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2009 The OpenLDAP Foundation.
+ * Copyright 2003-2010 The OpenLDAP Foundation.
  * Portions Copyright 2003 by IBM Corporation.
  * Portions Copyright 2003-2008 by Howard Chu, Symas Corporation.
  * All rights reserved.
@@ -769,7 +769,7 @@ do_syncrep2(
 
        Modifications   *modlist = NULL;
 
-       int                             match, m, punlock = 0;
+       int                             match, m, punlock = -1;
 
        struct timeval *tout_p = NULL;
        struct timeval tout = { 0, 0 };
@@ -810,7 +810,7 @@ do_syncrep2(
                        ldap_get_entry_controls( si->si_ld, msg, &rctrls );
                        /* we can't work without the control */
                        if ( rctrls ) {
-                               LDAPControl **next;
+                               LDAPControl **next = NULL;
                                /* NOTE: make sure we use the right one;
                                 * a better approach would be to run thru
                                 * the whole list and take care of all */
@@ -890,7 +890,7 @@ do_syncrep2(
                                                for ( i =0; i<si->si_cookieState->cs_pnum; i++ ) {
                                                        if ( si->si_cookieState->cs_psids[i] == sid ) {
                                                                if ( ber_bvcmp( syncCookie.ctxcsn, &si->si_cookieState->cs_pvals[i] ) <= 0 ) {
-                                                                       Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s CSN too old, ignoring %s\n",
+                                                                       Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s CSN pending, ignoring %s\n",
                                                                                si->si_ridtxt, syncCookie.ctxcsn->bv_val, 0 );
                                                                        ldap_controls_free( rctrls );
                                                                        rc = 0;
@@ -909,7 +909,7 @@ do_syncrep2(
                                                        si->si_cookieState->cs_psids = ch_realloc( si->si_cookieState->cs_psids, si->si_cookieState->cs_pnum * sizeof(int));
                                                        si->si_cookieState->cs_psids[i] = sid;
                                                }
-                                               punlock = 1;
+                                               punlock = i;
                                        }
                                        op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
                                }
@@ -943,8 +943,22 @@ do_syncrep2(
                                        rc = syncrepl_updateCookie( si, op, &syncCookie );
                                }
                        }
-                       if ( punlock );
+                       if ( punlock >= 0 ) {
+                               /* on failure, revert pending CSN */
+                               if ( rc != LDAP_SUCCESS ) {
+                                       int i;
+                                       for ( i = 0; i<si->si_cookieState->cs_num; i++ ) {
+                                               if ( si->si_cookieState->cs_sids[i] == si->si_cookieState->cs_psids[punlock] ) {
+                                                       ber_bvreplace( &si->si_cookieState->cs_pvals[punlock],
+                                                               &si->si_cookieState->cs_vals[i] );
+                                                       break;
+                                               }
+                                       }
+                                       if ( i == si->si_cookieState->cs_num )
+                                               si->si_cookieState->cs_pvals[punlock].bv_val[0] = '\0';
+                               }
                                ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_pmutex );
+                       }
                        ldap_controls_free( rctrls );
                        if ( modlist ) {
                                slap_mods_free( modlist, 1 );
@@ -984,7 +998,7 @@ do_syncrep2(
                                        si->si_ridtxt, err, ldap_err2string( err ) );
                        }
                        if ( rctrls ) {
-                               LDAPControl **next;
+                               LDAPControl **next = NULL;
                                /* NOTE: make sure we use the right one;
                                 * a better approach would be to run thru
                                 * the whole list and take care of all */
@@ -4046,6 +4060,10 @@ parse_syncrepl_line(
                {
                        val = c->argv[ i ] + STRLENOF( PROVIDERSTR "=" );
                        ber_str2bv( val, 0, 1, &si->si_bindconf.sb_uri );
+#ifdef HAVE_TLS
+                       if ( ldap_is_ldaps_url( val ))
+                               si->si_bindconf.sb_tls_do_init = 1;
+#endif
                        si->si_got |= GOT_PROVIDER;
                } else if ( !strncasecmp( c->argv[ i ], SCHEMASTR "=",
                                        STRLENOF( SCHEMASTR "=" ) ) )
@@ -4743,6 +4761,8 @@ syncrepl_config( ConfigArgs *c )
                                si = *sip;
                                if ( c->valx == -1 || i == c->valx ) {
                                        *sip = si->si_next;
+                                       si->si_ctype = -1;
+                                       si->si_next = NULL;
                                        /* If the task is currently active, we have to leave
                                         * it running. It will exit on its own. This will only
                                         * happen when running on the cn=config DB.
@@ -4751,22 +4771,34 @@ syncrepl_config( ConfigArgs *c )
                                                if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
                                                        isrunning = 1;
                                                } else {
+                                                       /* There is no active thread, but we must still
+                                                        * ensure that no thread is (or will be) queued
+                                                        * while we removes the task.
+                                                        */
+                                                       struct re_s *re = si->si_re;
+                                                       si->si_re = NULL;
+
                                                        if ( si->si_conn ) {
-                                                               /* If there's a persistent connection, it may
-                                                                * already have a thread queued. We know it's
-                                                                * not active, so it must be pending and we
-                                                                * can simply cancel it now.
-                                                                */
-                                                               ldap_pvt_thread_pool_retract( &connection_pool,
-                                                                       si->si_re->routine, si->si_re );
+                                                               connection_client_stop( si->si_conn );
+                                                               si->si_conn = NULL;
+                                                       }
+
+                                                       ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
+                                                       if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) ) {
+                                                               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_thread_mutex_unlock( &si->si_mutex );
                                                }
                                        }
-                                       if ( isrunning ) {
-                                               si->si_ctype = -1;
-                                               si->si_next = NULL;
-                                       } else {
+                                       if ( !isrunning ) {
                                                syncinfo_free( si, 0 );
                                        }
                                        if ( i == c->valx )