int rc = LDAP_SUCCESS;
int dostop = 0;
ber_socket_t s;
- int i, defer = 1, fail = 0;
+ int i, defer = 1, fail = 0, freeinfo = 0;
Backend *be;
if ( si == NULL )
return NULL;
+ if ( slapd_shutdown )
+ return NULL;
Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 );
ldap_pvt_thread_yield();
}
- if ( !si->si_ctype )
+ if ( si->si_ctype < 1 ) {
goto deleted;
+ }
switch( abs( si->si_type ) ) {
case LDAP_SYNC_REFRESH_ONLY:
connection_fake_init( &conn, &opbuf, ctx );
op = &opbuf.ob_op;
- /* use global malloc for now */
- op->o_tmpmemctx = NULL;
- op->o_tmpmfuncs = &ch_mfuncs;
-
op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
be = si->si_be;
deleted:
/* We got deleted while running on cn=config */
- if ( !si->si_ctype ) {
+ if ( si->si_ctype < 1 ) {
+ if ( si->si_ctype == -1 ) {
+ si->si_ctype = 0;
+ freeinfo = 1;
+ }
if ( si->si_conn )
dostop = 1;
rc = -1;
break;
}
- if ( !si->si_ctype
+ if ( si->si_ctype < 1
|| !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) {
if ( si->si_re ) {
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
}
/* Do final delete cleanup */
- if ( !si->si_ctype ) {
+ if ( freeinfo ) {
syncinfo_free( si, 0 );
}
return NULL;
if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn ) ) {
bdn = bvals[0];
- dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+ rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_ANY,
+ "syncrepl_message_to_op: %s "
+ "dn \"%s\" normalization failed (%d)",
+ si->si_ridtxt, bdn.bv_val, rc );
+ rc = -1;
+ ch_free( bvals );
+ goto done;
+ }
ber_dupbv( &op->o_req_dn, &dn );
ber_dupbv( &op->o_req_ndn, &ndn );
slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
return -1;
}
- dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+ rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
+ if ( rc != LDAP_SUCCESS ) {
+ /* One of the things that could happen is that the schema
+ * is not lined-up; this could result in unknown attributes.
+ * A value non conformant to the syntax should be unlikely,
+ * except when replicating between different versions
+ * of the software, or when syntax validation bugs are fixed
+ */
+ Debug( LDAP_DEBUG_ANY,
+ "syncrepl_message_to_entry: "
+ "%s dn \"%s\" normalization failed (%d)",
+ si->si_ridtxt, bdn.bv_val, rc );
+ return rc;
+ }
+
ber_dupbv( &op->o_req_dn, &dn );
ber_dupbv( &op->o_req_ndn, &ndn );
slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
Debug( LDAP_DEBUG_TRACE, "syncinfo_free: %s\n",
sie->si_ridtxt, 0, 0 );
- sie->si_cookieState->cs_ref--;
- if ( !sie->si_cookieState->cs_ref ) {
- ch_free( sie->si_cookieState->cs_sids );
- ber_bvarray_free( sie->si_cookieState->cs_vals );
- ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
- ch_free( sie->si_cookieState );
- }
do {
si_next = sie->si_next;
ldap_unbind_ext( sie->si_ld, NULL, NULL );
}
- /* re-fetch it, in case it was already removed */
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
- sie->si_re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, sie );
if ( sie->si_re ) {
- if ( ldap_pvt_runqueue_isrunning( &slapd_rq, sie->si_re ) )
- ldap_pvt_runqueue_stoptask( &slapd_rq, sie->si_re );
- ldap_pvt_runqueue_remove( &slapd_rq, sie->si_re );
+ struct re_s *re = sie->si_re;
+ sie->si_re = 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 );
+ ldap_pvt_runqueue_remove( &slapd_rq, re );
+ ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
-
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
- ldap_pvt_thread_mutex_destroy( &sie->si_mutex );
-
+
+ ldap_pvt_thread_mutex_destroy( &sie->si_mutex );
+
bindconf_free( &sie->si_bindconf );
-
+
if ( sie->si_filterstr.bv_val ) {
ch_free( sie->si_filterstr.bv_val );
}
}
ch_free( npe );
}
+ sie->si_cookieState->cs_ref--;
+ if ( !sie->si_cookieState->cs_ref ) {
+ ch_free( sie->si_cookieState->cs_sids );
+ ber_bvarray_free( sie->si_cookieState->cs_vals );
+ ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
+ ch_free( sie->si_cookieState );
+ }
ch_free( sie );
sie = si_next;
} while ( free_all && si_next );
si->si_cookieState = c->be->be_syncinfo->si_cookieState;
- // add new syncrepl to end of list (same order as when deleting)
+ /* add new syncrepl to end of list (same order as when deleting) */
for ( sip = c->be->be_syncinfo; sip->si_next; sip = sip->si_next );
sip->si_next = si;
} else {
if ( si->si_re ) {
if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
isrunning = 1;
- } else if ( si->si_conn ) {
- isrunning = 1;
- /* If there's a persistent connection, we don't
- * know if it's already got a thread queued.
- * so defer the free, but reschedule the task.
- * If there's a connection thread queued, it
- * will cleanup as necessary. If not, then the
- * runqueue task will cleanup.
- */
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
- if ( !ldap_pvt_runqueue_isrunning( &slapd_rq, si->si_re )) {
- si->si_re->interval.tv_sec = 0;
- ldap_pvt_runqueue_resched( &slapd_rq, si->si_re, 0 );
- si->si_re->interval.tv_sec = si->si_interval;
- }
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
-
} else {
+ 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 );
+ }
ldap_pvt_thread_mutex_unlock( &si->si_mutex );
}
}
if ( isrunning ) {
- si->si_ctype = 0;
+ si->si_ctype = -1;
si->si_next = NULL;
} else {
syncinfo_free( si, 0 );