From 2aadfa5d86acaf41ff0e5a966938c82ab1e557c9 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 20 Nov 2009 22:47:48 +0000 Subject: [PATCH] Reject old ops based on pending ops, not just committed ops --- servers/slapd/syncrepl.c | 53 ++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 7a4e6d4118..9da5506e44 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -44,8 +44,14 @@ typedef struct cookie_state { int cs_ref; struct berval *cs_vals; int *cs_sids; -} cookie_state; + /* pending changes, not yet committed */ + ldap_pvt_thread_mutex_t cs_pmutex; + int cs_pnum; + struct berval *cs_pvals; + int *cs_psids; +} cookie_state; + #define SYNCDATA_DEFAULT 0 /* entries are plain LDAP entries */ #define SYNCDATA_ACCESSLOG 1 /* entries are accesslog format */ #define SYNCDATA_CHANGELOG 2 /* entries are changelog format */ @@ -859,15 +865,42 @@ do_syncrep2( int i, sid = slap_parse_csn_sid( syncCookie.ctxcsn ); check_syncprov( op, si ); 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; + if ( si->si_cookieState->cs_sids[i] == sid ) { + if ( 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; + } + break; } } + /* check pending CSNs too */ + ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_pmutex ); + for ( i =0; isi_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", + si->si_ridtxt, syncCookie.ctxcsn->bv_val, 0 ); + ldap_controls_free( rctrls ); + rc = 0; + ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_pmutex ); + goto done; + } + ber_bvreplace( &si->si_cookieState->cs_pvals[i], + syncCookie.ctxcsn ); + break; + } + } + /* new SID, add it */ + if ( i == si->si_cookieState->cs_pnum ) { + value_add( &si->si_cookieState->cs_pvals, syncCookie.ctxcsn ); + si->si_cookieState->cs_pnum++; + ch_realloc( si->si_cookieState->cs_psids, si->si_cookieState->cs_num * sizeof(int)); + si->si_cookieState->cs_psids[i] = sid; + } + ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_pmutex ); } op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; } @@ -3791,6 +3824,9 @@ syncinfo_free( syncinfo_t *sie, int free_all ) 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->cs_psids ); + ber_bvarray_free( sie->si_cookieState->cs_pvals ); + ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_pmutex ); ch_free( sie->si_cookieState ); } } @@ -4470,6 +4506,7 @@ add_syncrepl( } else { si->si_cookieState = ch_calloc( 1, sizeof( cookie_state )); ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex ); + ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_pmutex ); c->be->be_syncinfo = si; } -- 2.39.5