}
}
}
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
}
}
rc = 0;
if ( !BER_BVISNULL( &syncCookie.octet_str ) )
{
slap_parse_sync_cookie( &syncCookie, NULL );
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
}
}
if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
"LDAP_RES_INTERMEDIATE",
"NEW_COOKIE" );
ber_scanf( ber, "tm", &tag, &cookie );
+ Debug( LDAP_DEBUG_SYNC,
+ "do_syncrep2: %s NEW_COOKIE: %s\n",
+ si->si_ridtxt,
+ cookie.bv_val, 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 );
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
+ }
break;
case LDAP_TAG_SYNC_REFRESH_DELETE:
case LDAP_TAG_SYNC_REFRESH_PRESENT:
if ( !BER_BVISNULL( &syncCookie.octet_str ) )
{
slap_parse_sync_cookie( &syncCookie, NULL );
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
}
}
/* Defaults to TRUE */
if ( !BER_BVISNULL( &syncCookie.octet_str ) )
{
slap_parse_sync_cookie( &syncCookie, NULL );
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
compare_csns( &syncCookie_req, &syncCookie, &m );
}
}
if ( match < 0 ) {
if ( si->si_refreshPresent == 1 &&
+ si_tag != LDAP_TAG_SYNC_NEW_COOKIE &&
syncCookie_req.numcsns == syncCookie.numcsns ) {
syncrepl_del_nonpresent( op, si, NULL,
&syncCookie, m );
if ( si == NULL )
return NULL;
- /* There will never be more than one instance active */
- ldap_pvt_thread_mutex_lock( &si->si_mutex );
+ /* Don't get stuck here while a pause is initiated */
+ while ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
+ if ( slapd_shutdown )
+ return NULL;
+ if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool ))
+ ldap_pvt_thread_yield();
+ }
switch( abs( si->si_type ) ) {
case LDAP_SYNC_REFRESH_ONLY:
/* Do final delete cleanup */
if ( !si->si_ctype ) {
- cookie_state *cs = NULL;
- syncinfo_t **sip;
-
- cs = be->be_syncinfo->si_cookieState;
- for ( sip = &be->be_syncinfo; *sip != si; sip = &(*sip)->si_next );
- *sip = si->si_next;
- syncinfo_free( si, 0 );
- if ( !be->be_syncinfo ) {
- SLAP_DBFLAGS( be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW);
- if ( cs ) {
- ch_free( cs->cs_sids );
- ber_bvarray_free( cs->cs_vals );
- ldap_pvt_thread_mutex_destroy( &cs->cs_mutex );
- ch_free( cs );
- }
- }
+ cookie_state *cs = si->si_cookieState;
+ syncinfo_free( si, ( !be->be_syncinfo ||
+ be->be_syncinfo->si_cookieState != cs ));
}
return NULL;
}
break;
}
}
+ if ( !mod->sml_numvals ) {
+ /* Drop this op */
+ *ml = mod->sml_next;
+ mod->sml_next = NULL;
+ slap_mods_free( mod, 1 );
+ }
break;
}
}
Backend *be = op->o_bd;
Modifications mod;
struct berval first = BER_BVNULL;
+#ifdef CHECK_CSN
+ Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax;
+#endif
int rc, i, j;
ber_len_t len;
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+#ifdef CHECK_CSN
+ for ( i=0; i<syncCookie->numcsns; i++ ) {
+ assert( !syn->ssyn_validate( syn, syncCookie->ctxcsn+i ));
+ }
+ for ( i=0; i<si->si_cookieState->cs_num; i++ ) {
+ assert( !syn->ssyn_validate( syn, si->si_cookieState->cs_vals+i ));
+ }
+#endif
+
/* clone the cookieState CSNs so we can Replace the whole thing */
mod.sml_numvals = si->si_cookieState->cs_num;
mod.sml_values = op->o_tmpalloc(( mod.sml_numvals+1 )*sizeof(struct berval), op->o_tmpmemctx );
if ( mod.sml_next ) slap_mods_free( mod.sml_next, 1 );
op->o_tmpfree( mod.sml_values, op->o_tmpmemctx );
+#ifdef CHECK_CSN
+ for ( i=0; i<si->si_cookieState->cs_num; i++ ) {
+ assert( !syn->ssyn_validate( syn, si->si_cookieState->cs_vals+i ));
+ }
+#endif
+
return rc;
}
* is actually newer than old entry
*/
if ( !is_entry_glue( rs->sr_entry )) {
- old = attr_find( rs->sr_entry->e_attrs,
- slap_schema.si_ad_objectClass );
old = attr_find( rs->sr_entry->e_attrs,
slap_schema.si_ad_entryCSN );
new = attr_find( dni->new_entry->e_attrs,
BER_BVISNULL( &si->si_bindconf.sb_uri ) ?
"(null)" : si->si_bindconf.sb_uri.bv_val, 0, 0 );
if ( c->be->be_syncinfo ) {
+ syncinfo_t *sip;
+
si->si_cookieState = c->be->be_syncinfo->si_cookieState;
+
+ // 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 {
si->si_cookieState = ch_calloc( 1, sizeof( cookie_state ));
ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex );
+
+ c->be->be_syncinfo = si;
}
- si->si_next = c->be->be_syncinfo;
- c->be->be_syncinfo = si;
+
+ si->si_next = NULL;
+
return 0;
}
}
return 1;
} else if ( c->op == LDAP_MOD_DELETE ) {
cookie_state *cs = NULL;
+ int isrunning = 0;
if ( c->be->be_syncinfo ) {
syncinfo_t *si, **sip;
int i;
for ( sip = &c->be->be_syncinfo, i=0; *sip; i++ ) {
si = *sip;
if ( c->valx == -1 || i == c->valx ) {
- int isrunning = 0;
*sip = si->si_next;
/* 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.
*/
if ( si->si_re ) {
- ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
- isrunning = ldap_pvt_runqueue_isrunning( &slapd_rq, si->si_re );
- ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+ if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
+ isrunning = 1;
+ } else {
+ ldap_pvt_thread_mutex_unlock( &si->si_mutex );
+ }
}
if ( si->si_re && isrunning ) {
si->si_ctype = 0;
+ si->si_next = NULL;
} else {
syncinfo_free( si, 0 );
}
}
if ( !c->be->be_syncinfo ) {
SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_SHADOW_MASK;
- if ( cs ) {
+ if ( cs && !isrunning ) {
+ ch_free( cs->cs_sids );
ber_bvarray_free( cs->cs_vals );
ldap_pvt_thread_mutex_destroy( &cs->cs_mutex );
ch_free( cs );