From: Howard Chu Date: Sat, 8 Mar 2008 23:51:07 +0000 (+0000) Subject: ITS#5407 more checks for pool pausing X-Git-Tag: OPENLDAP_REL_ENG_2_4_9~20^2~103 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a287573d2db89a1ebf5883b27f1175650dc69852;p=openldap ITS#5407 more checks for pool pausing --- diff --git a/include/ldap_pvt_thread.h b/include/ldap_pvt_thread.h index f08dfb4e6a..1325e77226 100644 --- a/include/ldap_pvt_thread.h +++ b/include/ldap_pvt_thread.h @@ -251,6 +251,10 @@ LDAP_F( int ) ldap_pvt_thread_pool_backload LDAP_P(( ldap_pvt_thread_pool_t *pool )); +LDAP_F( int ) +ldap_pvt_thread_pool_pausecheck LDAP_P(( + ldap_pvt_thread_pool_t *pool )); + LDAP_F( int ) ldap_pvt_thread_pool_pause LDAP_P(( ldap_pvt_thread_pool_t *pool )); diff --git a/libraries/libldap_r/tpool.c b/libraries/libldap_r/tpool.c index 34d3e591c3..f03f3c4178 100644 --- a/libraries/libldap_r/tpool.c +++ b/libraries/libldap_r/tpool.c @@ -692,6 +692,45 @@ ldap_int_thread_pool_wrapper ( return(NULL); } +/* See if a pause was requested; wait for it if so. + * Return 1 if we waited, 0 if not + */ +int +ldap_pvt_thread_pool_pausecheck ( + ldap_pvt_thread_pool_t *tpool ) +{ + struct ldap_int_thread_pool_s *pool; + + if (tpool == NULL) + return(-1); + + pool = *tpool; + + if (pool == NULL) + return(0); + + if ( !pool->ltp_pause ) + return(0); + + ldap_pvt_thread_mutex_lock(&pool->ltp_mutex); + + /* If someone else has already requested a pause, we have to wait */ + if (pool->ltp_pause) { + pool->ltp_pending_count++; + pool->ltp_active_count--; + /* let the other pool_pause() know when it can proceed */ + if (pool->ltp_active_count < 2) + ldap_pvt_thread_cond_signal(&pool->ltp_pcond); + do { + ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex); + } while (pool->ltp_pause); + pool->ltp_pending_count--; + pool->ltp_active_count++; + } + ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex); + return 1; +} + /* Pause the pool. Return when all other threads are paused. */ int ldap_pvt_thread_pool_pause ( diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index 2be06d5d1c..d6c2156a06 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -1780,7 +1780,13 @@ syncprov_op_mod( Operation *op, SlapReply *rs ) /* wait for this op to get to head of list */ while ( mt->mt_mods != mi ) { ldap_pvt_thread_mutex_unlock( &mt->mt_mutex ); - ldap_pvt_thread_yield(); + /* FIXME: if dynamic config can delete overlays or + * databases we'll have to check for cleanup here. + * Currently it's not an issue because there are + * no dynamic config deletes... + */ + if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool )) + ldap_pvt_thread_yield(); ldap_pvt_thread_mutex_lock( &mt->mt_mutex ); /* clean up if the caller is giving up */ diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 68b4c96921..f862d8e3e8 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -682,6 +682,8 @@ compare_csns( struct sync_cookie *sc1, struct sync_cookie *sc2, int *which ) return match; } +#define SYNC_PAUSED -3 + static int do_syncrep2( Operation *op, @@ -693,7 +695,6 @@ do_syncrep2( BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; - LDAPMessage *res = NULL; LDAPMessage *msg = NULL; char *retoid = NULL; @@ -744,149 +745,268 @@ do_syncrep2( } while ( ( rc = ldap_result( si->si_ld, si->si_msgid, LDAP_MSG_ONE, - tout_p, &res ) ) > 0 ) + tout_p, &msg ) ) > 0 ) { if ( slapd_shutdown ) { rc = -2; goto done; } - for( msg = ldap_first_message( si->si_ld, res ); - msg != NULL; - msg = ldap_next_message( si->si_ld, msg ) ) - { - if ( slapd_shutdown ) { - rc = -2; - goto done; - } - switch( ldap_msgtype( msg ) ) { - case LDAP_RES_SEARCH_ENTRY: - ldap_get_entry_controls( si->si_ld, msg, &rctrls ); - /* we can't work without the control */ - rctrlp = NULL; - if ( rctrls ) { - LDAPControl **next; - /* NOTE: make sure we use the right one; - * a better approach would be to run thru - * the whole list and take care of all */ - rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_STATE, rctrls, &next ); - if ( next && ldap_control_find( LDAP_CONTROL_SYNC_STATE, next, NULL ) ) - { - Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " - "got search entry with multiple " - "Sync State control\n", si->si_ridtxt, 0, 0 ); - rc = -1; - goto done; - } - } - if ( rctrlp == NULL ) { + switch( ldap_msgtype( msg ) ) { + case LDAP_RES_SEARCH_ENTRY: + ldap_get_entry_controls( si->si_ld, msg, &rctrls ); + /* we can't work without the control */ + rctrlp = NULL; + if ( rctrls ) { + LDAPControl **next; + /* NOTE: make sure we use the right one; + * a better approach would be to run thru + * the whole list and take care of all */ + rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_STATE, rctrls, &next ); + if ( next && ldap_control_find( LDAP_CONTROL_SYNC_STATE, next, NULL ) ) + { Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " - "got search entry without " + "got search entry with multiple " "Sync State control\n", si->si_ridtxt, 0, 0 ); rc = -1; goto done; } - ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); - ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID ); - /* FIXME: what if syncUUID is NULL or empty? - * (happens with back-sql...) */ - if ( BER_BVISEMPTY( &syncUUID ) ) { - Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " - "got empty syncUUID with LDAP_SYNC_%s\n", - si->si_ridtxt, - syncrepl_state2str( syncstate ), 0 ); - ldap_controls_free( rctrls ); - rc = -1; - goto done; + } + if ( rctrlp == NULL ) { + Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " + "got search entry without " + "Sync State control\n", si->si_ridtxt, 0, 0 ); + rc = -1; + goto done; + } + ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); + ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID ); + /* FIXME: what if syncUUID is NULL or empty? + * (happens with back-sql...) */ + if ( BER_BVISEMPTY( &syncUUID ) ) { + Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " + "got empty syncUUID with LDAP_SYNC_%s\n", + si->si_ridtxt, + syncrepl_state2str( syncstate ), 0 ); + ldap_controls_free( rctrls ); + rc = -1; + goto done; + } + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { + ber_scanf( ber, /*"{"*/ "m}", &cookie ); + + Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", + BER_BVISNULL( &cookie ) ? "" : cookie.bv_val, 0, 0 ); + + if ( !BER_BVISNULL( &cookie ) ) { + ch_free( syncCookie.octet_str.bv_val ); + ber_dupbv( &syncCookie.octet_str, &cookie ); + } + if ( !BER_BVISNULL( &syncCookie.octet_str ) ) + { + slap_parse_sync_cookie( &syncCookie, NULL ); + if ( syncCookie.ctxcsn ) { + int i, sid = slap_parse_csn_sid( syncCookie.ctxcsn ); + for ( i =0; isi_cookieState->cs_num; i++ ) { + if ( si->si_cookieState->cs_sids[i] == sid && + ber_bvcmp( syncCookie.ctxcsn, &si->si_cookieState->cs_vals[i] ) <= 0 ) { + Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s CSN too old, ignoring %s\n", + si->si_ridtxt, syncCookie.ctxcsn->bv_val, 0 ); + ldap_controls_free( rctrls ); + rc = 0; + goto done; + } + } + } + } + } + rc = 0; + if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) { + modlist = NULL; + if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS && + syncCookie.ctxcsn ) + { + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); + } else if ( rc == LDAP_NO_SUCH_OBJECT ) { + rc = LDAP_SYNC_REFRESH_REQUIRED; + si->si_logstate = SYNCLOG_FALLBACK; + ldap_abandon_ext( si->si_ld, si->si_msgid, NULL, NULL ); + } + } else if ( ( rc = syncrepl_message_to_entry( si, op, msg, + &modlist, &entry, syncstate ) ) == LDAP_SUCCESS ) + { + if ( ( rc = syncrepl_entry( si, op, entry, &modlist, + syncstate, &syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS && + syncCookie.ctxcsn ) + { + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); + } + } + ldap_controls_free( rctrls ); + if ( modlist ) { + slap_mods_free( modlist, 1 ); + } + if ( rc ) + goto done; + break; + + case LDAP_RES_SEARCH_REFERENCE: + Debug( LDAP_DEBUG_ANY, + "do_syncrep2: %s reference received error\n", + si->si_ridtxt, 0, 0 ); + break; + + case LDAP_RES_SEARCH_RESULT: + Debug( LDAP_DEBUG_SYNC, + "do_syncrep2: %s LDAP_RES_SEARCH_RESULT\n", + si->si_ridtxt, 0, 0 ); + ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL, + &rctrls, 0 ); +#ifdef LDAP_X_SYNC_REFRESH_REQUIRED + if ( err == LDAP_X_SYNC_REFRESH_REQUIRED ) { + /* map old result code to registered code */ + err = LDAP_SYNC_REFRESH_REQUIRED; + } +#endif + if ( err == LDAP_SYNC_REFRESH_REQUIRED ) { + if ( si->si_logstate == SYNCLOG_LOGGING ) { + si->si_logstate = SYNCLOG_FALLBACK; } + rc = err; + goto done; + } + if ( rctrls ) { + rctrlp = *rctrls; + ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); + + ber_scanf( ber, "{" /*"}"*/); if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { - ber_scanf( ber, /*"{"*/ "m}", &cookie ); + ber_scanf( ber, "m", &cookie ); Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", BER_BVISNULL( &cookie ) ? "" : cookie.bv_val, 0, 0 ); if ( !BER_BVISNULL( &cookie ) ) { ch_free( syncCookie.octet_str.bv_val ); - ber_dupbv( &syncCookie.octet_str, &cookie ); + ber_dupbv( &syncCookie.octet_str, &cookie); } if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); - if ( syncCookie.ctxcsn ) { - int i, sid = slap_parse_csn_sid( syncCookie.ctxcsn ); - for ( i =0; isi_cookieState->cs_num; i++ ) { - if ( si->si_cookieState->cs_sids[i] == sid && - ber_bvcmp( syncCookie.ctxcsn, &si->si_cookieState->cs_vals[i] ) <= 0 ) { - Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s CSN too old, ignoring %s\n", - si->si_ridtxt, syncCookie.ctxcsn->bv_val, 0 ); - ldap_controls_free( rctrls ); - rc = 0; - goto done; - } - } - } } } - rc = 0; - if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) { - modlist = NULL; - if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS && - syncCookie.ctxcsn ) - { - rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); - } else if ( rc == LDAP_NO_SUCH_OBJECT ) { - rc = LDAP_SYNC_REFRESH_REQUIRED; - si->si_logstate = SYNCLOG_FALLBACK; - ldap_abandon_ext( si->si_ld, si->si_msgid, NULL, NULL ); - } - } else if ( ( rc = syncrepl_message_to_entry( si, op, msg, - &modlist, &entry, syncstate ) ) == LDAP_SUCCESS ) + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) { - if ( ( rc = syncrepl_entry( si, op, entry, &modlist, - syncstate, &syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS && - syncCookie.ctxcsn ) - { - rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); - } + ber_scanf( ber, "b", &refreshDeletes ); } + ber_scanf( ber, /*"{"*/ "}" ); + } + if ( !syncCookie.ctxcsn ) { + match = 1; + } else if ( !syncCookie_req.ctxcsn ) { + match = -1; + m = 0; + } else { + match = compare_csns( &syncCookie_req, &syncCookie, &m ); + } + if ( rctrls ) { ldap_controls_free( rctrls ); - if ( modlist ) { - slap_mods_free( modlist, 1 ); + } + if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) { + /* FIXME : different error behaviors according to + * 1) err code : LDAP_BUSY ... + * 2) on err policy : stop service, stop sync, retry + */ + if ( refreshDeletes == 0 && match < 0 && + err == LDAP_SUCCESS ) + { + syncrepl_del_nonpresent( op, si, NULL, + &syncCookie.ctxcsn[m] ); + } else { + avl_free( si->si_presentlist, ch_free ); + si->si_presentlist = NULL; } - if ( rc ) - goto done; - break; - - case LDAP_RES_SEARCH_REFERENCE: - Debug( LDAP_DEBUG_ANY, - "do_syncrep2: %s reference received error\n", - si->si_ridtxt, 0, 0 ); - break; + } + if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS ) + { + rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); + } + if ( err == LDAP_SUCCESS + && si->si_logstate == SYNCLOG_FALLBACK ) { + si->si_logstate = SYNCLOG_LOGGING; + rc = LDAP_SYNC_REFRESH_REQUIRED; + } else { + rc = -2; + } + goto done; + break; - case LDAP_RES_SEARCH_RESULT: - Debug( LDAP_DEBUG_SYNC, - "do_syncrep2: %s LDAP_RES_SEARCH_RESULT\n", - si->si_ridtxt, 0, 0 ); - ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL, - &rctrls, 0 ); -#ifdef LDAP_X_SYNC_REFRESH_REQUIRED - if ( err == LDAP_X_SYNC_REFRESH_REQUIRED ) { - /* map old result code to registered code */ - err = LDAP_SYNC_REFRESH_REQUIRED; - } -#endif - if ( err == LDAP_SYNC_REFRESH_REQUIRED ) { - if ( si->si_logstate == SYNCLOG_LOGGING ) { - si->si_logstate = SYNCLOG_FALLBACK; + case LDAP_RES_INTERMEDIATE: + rc = ldap_parse_intermediate( si->si_ld, msg, + &retoid, &retdata, NULL, 0 ); + if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) { + ber_init2( ber, retdata, LBER_USE_DER ); + + switch ( si_tag = ber_peek_tag( ber, &len ) ) { + ber_tag_t tag; + case LDAP_TAG_SYNC_NEW_COOKIE: + Debug( LDAP_DEBUG_SYNC, + "do_syncrep2: %s %s - %s\n", + si->si_ridtxt, + "LDAP_RES_INTERMEDIATE", + "NEW_COOKIE" ); + ber_scanf( ber, "tm", &tag, &cookie ); + break; + case LDAP_TAG_SYNC_REFRESH_DELETE: + case LDAP_TAG_SYNC_REFRESH_PRESENT: + Debug( LDAP_DEBUG_SYNC, + "do_syncrep2: %s %s - %s\n", + si->si_ridtxt, + "LDAP_RES_INTERMEDIATE", + si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ? + "REFRESH_PRESENT" : "REFRESH_DELETE" ); + if ( si_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) { + si->si_refreshDelete = 1; + } else { + si->si_refreshPresent = 1; } - rc = err; - goto done; - } - if ( rctrls ) { - rctrlp = *rctrls; - ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); + ber_scanf( ber, "t{" /*"}"*/, &tag ); + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) + { + ber_scanf( ber, "m", &cookie ); + + Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", + BER_BVISNULL( &cookie ) ? "" : cookie.bv_val, 0, 0 ); - ber_scanf( ber, "{" /*"}"*/); - if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { + if ( !BER_BVISNULL( &cookie ) ) { + ch_free( syncCookie.octet_str.bv_val ); + ber_dupbv( &syncCookie.octet_str, &cookie ); + } + if ( !BER_BVISNULL( &syncCookie.octet_str ) ) + { + slap_parse_sync_cookie( &syncCookie, NULL ); + } + } + /* Defaults to TRUE */ + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_REFRESHDONE ) + { + ber_scanf( ber, "b", &si->si_refreshDone ); + } else + { + si->si_refreshDone = 1; + } + ber_scanf( ber, /*"{"*/ "}" ); + break; + case LDAP_TAG_SYNC_ID_SET: + Debug( LDAP_DEBUG_SYNC, + "do_syncrep2: %s %s - %s\n", + si->si_ridtxt, + "LDAP_RES_INTERMEDIATE", + "SYNC_ID_SET" ); + ber_scanf( ber, "t{" /*"}"*/, &tag ); + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_SYNC_COOKIE ) + { ber_scanf( ber, "m", &cookie ); Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", @@ -894,19 +1014,44 @@ do_syncrep2( if ( !BER_BVISNULL( &cookie ) ) { ch_free( syncCookie.octet_str.bv_val ); - ber_dupbv( &syncCookie.octet_str, &cookie); + ber_dupbv( &syncCookie.octet_str, &cookie ); } if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); + compare_csns( &syncCookie_req, &syncCookie, &m ); } } - if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_REFRESHDELETES ) { ber_scanf( ber, "b", &refreshDeletes ); } + ber_scanf( ber, "[W]", &syncUUIDs ); ber_scanf( ber, /*"{"*/ "}" ); + if ( refreshDeletes ) { + syncrepl_del_nonpresent( op, si, syncUUIDs, + &syncCookie.ctxcsn[m] ); + ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx ); + } else { + int i; + for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) { + (void)avl_presentlist_insert( si, &syncUUIDs[i] ); + slap_sl_free( syncUUIDs[i].bv_val, op->o_tmpmemctx ); + } + slap_sl_free( syncUUIDs, op->o_tmpmemctx ); + } + slap_sync_cookie_free( &syncCookie, 0 ); + break; + default: + Debug( LDAP_DEBUG_ANY, + "do_syncrep2: %s unknown syncinfo tag (%ld)\n", + si->si_ridtxt, (long) si_tag, 0 ); + ldap_memfree( retoid ); + ber_bvfree( retdata ); + continue; } + if ( !syncCookie.ctxcsn ) { match = 1; } else if ( !syncCookie_req.ctxcsn ) { @@ -915,201 +1060,53 @@ do_syncrep2( } else { match = compare_csns( &syncCookie_req, &syncCookie, &m ); } - if ( rctrls ) { - ldap_controls_free( rctrls ); - } - if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) { - /* FIXME : different error behaviors according to - * 1) err code : LDAP_BUSY ... - * 2) on err policy : stop service, stop sync, retry - */ - if ( refreshDeletes == 0 && match < 0 && - err == LDAP_SUCCESS ) - { + + if ( match < 0 ) { + if ( si->si_refreshPresent == 1 ) { syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn[m] ); - } else { - avl_free( si->si_presentlist, ch_free ); - si->si_presentlist = NULL; } - } - if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS ) - { - rc = syncrepl_updateCookie( si, op, psub, &syncCookie ); - } - if ( err == LDAP_SUCCESS - && si->si_logstate == SYNCLOG_FALLBACK ) { - si->si_logstate = SYNCLOG_LOGGING; - rc = LDAP_SYNC_REFRESH_REQUIRED; - } else { - rc = -2; - } - goto done; - break; - - case LDAP_RES_INTERMEDIATE: - rc = ldap_parse_intermediate( si->si_ld, msg, - &retoid, &retdata, NULL, 0 ); - if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) { - ber_init2( ber, retdata, LBER_USE_DER ); - - switch ( si_tag = ber_peek_tag( ber, &len ) ) { - ber_tag_t tag; - case LDAP_TAG_SYNC_NEW_COOKIE: - Debug( LDAP_DEBUG_SYNC, - "do_syncrep2: %s %s - %s\n", - si->si_ridtxt, - "LDAP_RES_INTERMEDIATE", - "NEW_COOKIE" ); - ber_scanf( ber, "tm", &tag, &cookie ); - break; - case LDAP_TAG_SYNC_REFRESH_DELETE: - case LDAP_TAG_SYNC_REFRESH_PRESENT: - Debug( LDAP_DEBUG_SYNC, - "do_syncrep2: %s %s - %s\n", - si->si_ridtxt, - "LDAP_RES_INTERMEDIATE", - si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ? - "REFRESH_PRESENT" : "REFRESH_DELETE" ); - if ( si_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) { - si->si_refreshDelete = 1; - } else { - si->si_refreshPresent = 1; - } - ber_scanf( ber, "t{" /*"}"*/, &tag ); - if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) - { - ber_scanf( ber, "m", &cookie ); - - Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", - BER_BVISNULL( &cookie ) ? "" : cookie.bv_val, 0, 0 ); - if ( !BER_BVISNULL( &cookie ) ) { - ch_free( syncCookie.octet_str.bv_val ); - ber_dupbv( &syncCookie.octet_str, &cookie ); - } - if ( !BER_BVISNULL( &syncCookie.octet_str ) ) - { - slap_parse_sync_cookie( &syncCookie, NULL ); - } - } - /* Defaults to TRUE */ - if ( ber_peek_tag( ber, &len ) == - LDAP_TAG_REFRESHDONE ) - { - ber_scanf( ber, "b", &si->si_refreshDone ); - } else - { - si->si_refreshDone = 1; - } - ber_scanf( ber, /*"{"*/ "}" ); - break; - case LDAP_TAG_SYNC_ID_SET: - Debug( LDAP_DEBUG_SYNC, - "do_syncrep2: %s %s - %s\n", - si->si_ridtxt, - "LDAP_RES_INTERMEDIATE", - "SYNC_ID_SET" ); - ber_scanf( ber, "t{" /*"}"*/, &tag ); - if ( ber_peek_tag( ber, &len ) == - LDAP_TAG_SYNC_COOKIE ) - { - ber_scanf( ber, "m", &cookie ); - - Debug( LDAP_DEBUG_SYNC, "do_syncrep2: cookie=%s\n", - BER_BVISNULL( &cookie ) ? "" : cookie.bv_val, 0, 0 ); - - if ( !BER_BVISNULL( &cookie ) ) { - ch_free( syncCookie.octet_str.bv_val ); - ber_dupbv( &syncCookie.octet_str, &cookie ); - } - if ( !BER_BVISNULL( &syncCookie.octet_str ) ) - { - slap_parse_sync_cookie( &syncCookie, NULL ); - compare_csns( &syncCookie_req, &syncCookie, &m ); - } - } - if ( ber_peek_tag( ber, &len ) == - LDAP_TAG_REFRESHDELETES ) - { - ber_scanf( ber, "b", &refreshDeletes ); - } - ber_scanf( ber, "[W]", &syncUUIDs ); - ber_scanf( ber, /*"{"*/ "}" ); - if ( refreshDeletes ) { - syncrepl_del_nonpresent( op, si, syncUUIDs, - &syncCookie.ctxcsn[m] ); - ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx ); - } else { - int i; - for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) { - (void)avl_presentlist_insert( si, &syncUUIDs[i] ); - slap_sl_free( syncUUIDs[i].bv_val, op->o_tmpmemctx ); - } - slap_sl_free( syncUUIDs, op->o_tmpmemctx ); - } - slap_sync_cookie_free( &syncCookie, 0 ); - break; - default: - Debug( LDAP_DEBUG_ANY, - "do_syncrep2: %s unknown syncinfo tag (%ld)\n", - si->si_ridtxt, (long) si_tag, 0 ); - ldap_memfree( retoid ); - ber_bvfree( retdata ); - continue; - } - - if ( !syncCookie.ctxcsn ) { - match = 1; - } else if ( !syncCookie_req.ctxcsn ) { - match = -1; - m = 0; - } else { - match = compare_csns( &syncCookie_req, &syncCookie, &m ); + if ( syncCookie.ctxcsn ) + { + rc = syncrepl_updateCookie( si, op, psub, &syncCookie); } + } - if ( match < 0 ) { - if ( si->si_refreshPresent == 1 ) { - syncrepl_del_nonpresent( op, si, NULL, - &syncCookie.ctxcsn[m] ); - } - - if ( syncCookie.ctxcsn ) - { - rc = syncrepl_updateCookie( si, op, psub, &syncCookie); - } - } - - ldap_memfree( retoid ); - ber_bvfree( retdata ); - break; - - } else { - Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " - "unknown intermediate response (%d)\n", - si->si_ridtxt, rc, 0 ); - ldap_memfree( retoid ); - ber_bvfree( retdata ); - break; - } + ldap_memfree( retoid ); + ber_bvfree( retdata ); break; - default: + } else { Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " - "unknown message (0x%02lx)\n", - si->si_ridtxt, - (unsigned long)ldap_msgtype( msg ), 0 ); + "unknown intermediate response (%d)\n", + si->si_ridtxt, rc, 0 ); + ldap_memfree( retoid ); + ber_bvfree( retdata ); break; - - } - if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { - slap_sync_cookie_free( &syncCookie_req, 0 ); - slap_dup_sync_cookie( &syncCookie_req, &syncCookie ); - slap_sync_cookie_free( &syncCookie, 0 ); } + break; + + default: + Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s " + "unknown message (0x%02lx)\n", + si->si_ridtxt, + (unsigned long)ldap_msgtype( msg ), 0 ); + break; + + } + if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { + slap_sync_cookie_free( &syncCookie_req, 0 ); + slap_dup_sync_cookie( &syncCookie_req, &syncCookie ); + slap_sync_cookie_free( &syncCookie, 0 ); + } + ldap_msgfree( msg ); + msg = NULL; + if ( ldap_pvt_thread_pool_pausing( &connection_pool )) { + slap_sync_cookie_free( &syncCookie, 0 ); + slap_sync_cookie_free( &syncCookie_req, 0 ); + return SYNC_PAUSED; } - ldap_msgfree( res ); - res = NULL; } if ( rc == -1 ) { @@ -1127,7 +1124,7 @@ done: slap_sync_cookie_free( &syncCookie, 0 ); slap_sync_cookie_free( &syncCookie_req, 0 ); - if ( res ) ldap_msgfree( res ); + if ( msg ) ldap_msgfree( msg ); if ( rc && rc != LDAP_SYNC_REFRESH_REQUIRED && si->si_ld ) { if ( si->si_conn ) { @@ -1236,29 +1233,32 @@ reload: rc = -1; } - if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) { - /* If we succeeded, enable the connection for further listening. - * If we failed, tear down the connection and reschedule. - */ - if ( rc == LDAP_SUCCESS ) { - if ( si->si_conn ) { - connection_client_enable( si->si_conn ); - } else { - si->si_conn = connection_client_setup( s, do_syncrepl, arg ); - } - } else if ( si->si_conn ) { - dostop = 1; + if ( rc != SYNC_PAUSED ) { + if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) { + /* If we succeeded, enable the connection for further listening. + * If we failed, tear down the connection and reschedule. + */ + if ( rc == LDAP_SUCCESS ) { + if ( si->si_conn ) { + connection_client_enable( si->si_conn ); + } else { + si->si_conn = connection_client_setup( s, do_syncrepl, arg ); + } + } else if ( si->si_conn ) { + dostop = 1; + } + } else { + if ( rc == -2 ) rc = 0; } - } else { - if ( rc == -2 ) rc = 0; } } - /* At this point, we have 4 cases: + /* At this point, we have 5 cases: * 1) for any hard failure, give up and remove this task - * 2) for ServerDown, reschedule this task to run - * 3) for Refresh and Success, reschedule to run - * 4) for Persist and Success, reschedule to defer + * 2) for ServerDown, reschedule this task to run later + * 3) for threadpool pause, reschedule to run immediately + * 4) for Refresh and Success, reschedule to run + * 5) for Persist and Success, reschedule to defer */ ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); @@ -1271,7 +1271,11 @@ reload: si->si_conn = NULL; } - if ( rc == LDAP_SUCCESS ) { + if ( rc == SYNC_PAUSED ) { + rtask->interval.tv_sec = 0; + ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 ); + rc = 0; + } else if ( rc == LDAP_SUCCESS ) { if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) { defer = 0; }