X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=76b9ec1a97c4e11bbff14032787d0d678f1b9dac;hb=eb3e92481bfbc655164e5c66aa3499a4315ac6ea;hp=a0de80d99ca48a34b138ca172d6ff18803d3cb3d;hpb=2705cbd749ed8e90f5f693a21f5884d2b34d3599;p=openldap
diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
index a0de80d99c..76b9ec1a97 100644
--- a/servers/slapd/syncrepl.c
+++ b/servers/slapd/syncrepl.c
@@ -2,7 +2,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 2003-2008 The OpenLDAP Foundation.
+ * Copyright 2003-2009 The OpenLDAP Foundation.
* Portions Copyright 2003 by IBM Corporation.
* Portions Copyright 2003-2008 by Howard Chu, Symas Corporation.
* All rights reserved.
@@ -343,7 +343,7 @@ ldap_sync_search(
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
- LDAPControl c[2], *ctrls[3];
+ LDAPControl c[3], *ctrls[4];
int rc;
int rhint;
char *base;
@@ -417,14 +417,19 @@ ldap_sync_search(
c[0].ldctl_iscritical = si->si_type < 0;
ctrls[0] = &c[0];
+ c[1].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ BER_BVZERO( &c[1].ldctl_value );
+ c[1].ldctl_iscritical = 1;
+ ctrls[1] = &c[1];
+
if ( !BER_BVISNULL( &si->si_bindconf.sb_authzId ) ) {
- c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
- c[1].ldctl_value = si->si_bindconf.sb_authzId;
- c[1].ldctl_iscritical = 1;
- ctrls[1] = &c[1];
- ctrls[2] = NULL;
+ c[2].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+ c[2].ldctl_value = si->si_bindconf.sb_authzId;
+ c[2].ldctl_iscritical = 1;
+ ctrls[2] = &c[2];
+ ctrls[3] = NULL;
} else {
- ctrls[1] = NULL;
+ ctrls[2] = NULL;
}
rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
@@ -583,6 +588,8 @@ do_syncrep1(
rc = LDAP_DEREF_NEVER; /* actually could allow DEREF_FINDING */
ldap_set_option( si->si_ld, LDAP_OPT_DEREF, &rc );
+ ldap_set_option( si->si_ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
+
si->si_syncCookie.rid = si->si_rid;
/* whenever there are multiple data sources possible, advertise sid */
@@ -724,7 +731,6 @@ do_syncrep2(
syncinfo_t *si )
{
LDAPControl **rctrls = NULL;
- LDAPControl *rctrlp;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
@@ -781,6 +787,8 @@ do_syncrep2(
while ( ( rc = ldap_result( si->si_ld, si->si_msgid, LDAP_MSG_ONE,
tout_p, &msg ) ) > 0 )
{
+ LDAPControl *rctrlp = NULL;
+
if ( slapd_shutdown ) {
rc = -2;
goto done;
@@ -789,18 +797,22 @@ do_syncrep2(
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 */
+ /* NOTE: since we issue the search request,
+ * we should know what controls to expect,
+ * and there should be none apart from the
+ * sync-related control */
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 );
+ ldap_controls_free( rctrls );
rc = -1;
goto done;
}
@@ -851,6 +863,7 @@ do_syncrep2(
}
}
}
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
}
}
rc = 0;
@@ -921,7 +934,26 @@ do_syncrep2(
si->si_ridtxt, err, ldap_err2string( err ) );
}
if ( rctrls ) {
- rctrlp = *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 */
+ /* NOTE: since we issue the search request,
+ * we should know what controls to expect,
+ * and there should be none apart from the
+ * sync-related control */
+ rctrlp = ldap_control_find( LDAP_CONTROL_SYNC_DONE, rctrls, &next );
+ if ( next && ldap_control_find( LDAP_CONTROL_SYNC_DONE, next, NULL ) )
+ {
+ Debug( LDAP_DEBUG_ANY, "do_syncrep2: %s "
+ "got search result with multiple "
+ "Sync State control\n", si->si_ridtxt, 0, 0 );
+ ldap_controls_free( rctrls );
+ rc = -1;
+ goto done;
+ }
+ }
+ if ( rctrlp ) {
ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
ber_scanf( ber, "{" /*"}"*/);
@@ -938,6 +970,7 @@ do_syncrep2(
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 )
@@ -1006,6 +1039,18 @@ do_syncrep2(
"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:
@@ -1035,6 +1080,7 @@ do_syncrep2(
if ( !BER_BVISNULL( &syncCookie.octet_str ) )
{
slap_parse_sync_cookie( &syncCookie, NULL );
+ op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie;
}
}
/* Defaults to TRUE */
@@ -1070,6 +1116,7 @@ do_syncrep2(
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 );
}
}
@@ -1118,6 +1165,7 @@ do_syncrep2(
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 );
@@ -1215,8 +1263,13 @@ do_syncrepl(
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:
@@ -1375,7 +1428,10 @@ reload:
if ( !si->si_ctype
|| !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) {
- ldap_pvt_runqueue_remove( &slapd_rq, rtask );
+ if ( si->si_re ) {
+ ldap_pvt_runqueue_remove( &slapd_rq, rtask );
+ si->si_re = NULL;
+ }
fail = RETRYNUM_TAIL;
} else if ( RETRYNUM_VALID( si->si_retrynum[i] ) ) {
if ( si->si_retrynum[i] > 0 )
@@ -1408,22 +1464,9 @@ reload:
/* 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;
}
@@ -2062,6 +2105,7 @@ syncrepl_entry(
op->o_time = slap_get_time();
op->ors_tlimit = SLAP_NO_LIMIT;
op->ors_slimit = 1;
+ op->ors_limit = NULL;
op->ors_attrs = slap_anlist_all_attributes;
op->ors_attrsonly = 0;
@@ -2073,12 +2117,10 @@ syncrepl_entry(
dni.new_entry = entry;
dni.modlist = modlist;
- if ( limits_check( op, &rs_search ) == 0 ) {
- rc = be->be_search( op, &rs_search );
- Debug( LDAP_DEBUG_SYNC,
- "syncrepl_entry: %s be_search (%d)\n",
- si->si_ridtxt, rc, 0 );
- }
+ rc = be->be_search( op, &rs_search );
+ Debug( LDAP_DEBUG_SYNC,
+ "syncrepl_entry: %s be_search (%d)\n",
+ si->si_ridtxt, rc, 0 );
if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
@@ -2208,7 +2250,7 @@ retry_add:;
if ( dni.renamed ) {
struct berval noldp, newp;
Modifications *mod, **modtail, **ml, *m2;
- int i, got_replace = 0;
+ int i, got_replace = 0, just_rename = 0;
op->o_tag = LDAP_REQ_MODRDN;
dnRdn( &entry->e_name, &op->orr_newrdn );
@@ -2228,23 +2270,18 @@ retry_add:;
goto done;
}
- /* Drop the RDN mods from this op:
- * If delOldRDN is TRUE then we should see a delete modop
- * for oldDesc. The valid cases are:
- * oldNattr had only one value, newDesc == oldDesc:
- * we'll see a replace modop for oldDesc
- * oldNattr had only one value, newDesc != oldDesc:
- * we'll see a delete modop for oldDesc with no values
- * oldNattr had multiple values:
- * we'll see a delete modop for oldDesc / old RDN value
+ /* Drop the RDN-related mods from this op, because their
+ * equivalents were just setup by slap_modrdn2mods.
*
- * If the modop has only one value, just drop it; it's already
- * present in orr_modlist. Otherwise, if we see a delete for
- * oldDesc with more values, we must remove the old RDN value
- * from that modop since it's already in orr_modlist.
- *
- * Likewise if we see a replace on oldDesc with multiple values,
- * we must drop the new RDN value and turn it into an add.
+ * If delOldRDN is TRUE then we should see a delete modop
+ * for oldDesc. We might see a replace instead.
+ * delete with no values: therefore newDesc != oldDesc.
+ * if oldNattr had only one value, then Drop this op.
+ * delete with 1 value: can only be the oldRDN value. Drop op.
+ * delete with N values: Drop oldRDN value, keep remainder.
+ * replace with 1 value: if oldNattr had only one value and
+ * newDesc == oldDesc, Drop this op.
+ * Any other cases must be left intact.
*
* We should also see an add modop for newDesc. (But not if
* we got a replace modop due to delOldRDN.) If it has
@@ -2254,7 +2291,6 @@ retry_add:;
if ( dni.delOldRDN ) {
for ( ml = &dni.mods; *ml; ml = &(*ml)->sml_next ) {
if ( (*ml)->sml_desc == dni.oldDesc ) {
- short sm_op;
mod = *ml;
if ( mod->sml_op == LDAP_MOD_REPLACE &&
dni.oldDesc != dni.newDesc ) {
@@ -2267,27 +2303,19 @@ retry_add:;
dni.oldNattr->a_numvals == 1 &&
( mod->sml_op == LDAP_MOD_DELETE ||
mod->sml_op == LDAP_MOD_REPLACE )) {
+ if ( mod->sml_op == LDAP_MOD_REPLACE )
+ got_replace = 1;
/* Drop this op */
*ml = mod->sml_next;
mod->sml_next = NULL;
slap_mods_free( mod, 1 );
- if ( mod->sml_op == LDAP_MOD_REPLACE )
- got_replace = 1;
break;
}
- if ( mod->sml_op == LDAP_MOD_ADD )
- continue;
- if ( mod->sml_op == LDAP_MOD_DELETE && mod->sml_numvals == 0 )
+ if ( mod->sml_op != LDAP_MOD_DELETE || mod->sml_numvals == 0 )
continue;
- if ( mod->sml_op == LDAP_MOD_REPLACE ) {
- got_replace = 1;
- sm_op = SLAP_MOD_SOFTADD;
- } else {
- sm_op = LDAP_MOD_DELETE;
- }
for ( m2 = op->orr_modlist; m2; m2=m2->sml_next ) {
if ( m2->sml_desc == dni.oldDesc &&
- m2->sml_op == sm_op ) break;
+ m2->sml_op == LDAP_MOD_DELETE ) break;
}
for ( i=0; isml_numvals; i++ ) {
if ( bvmatch( &mod->sml_values[i], &m2->sml_values[0] )) {
@@ -2303,6 +2331,12 @@ retry_add:;
break;
}
}
+ if ( !mod->sml_numvals ) {
+ /* Drop this op */
+ *ml = mod->sml_next;
+ mod->sml_next = NULL;
+ slap_mods_free( mod, 1 );
+ }
break;
}
}
@@ -2382,8 +2416,12 @@ retry_add:;
*/
if ( dni.mods ) {
mod = dni.mods;
+ /* don't set a CSN for the rename op */
+ if ( syncCSN )
+ slap_graduate_commit_csn( op );
} else {
mod = op->orr_modlist;
+ just_rename = 1;
}
for ( ; mod->sml_next; mod=mod->sml_next );
mod->sml_next = m2;
@@ -2401,6 +2439,9 @@ retry_add:;
/* Renamed entries may still have other mods so just fallthru */
op->o_req_dn = entry->e_name;
op->o_req_ndn = entry->e_nname;
+ /* Use CSN on the modify */
+ if ( syncCSN && !just_rename )
+ slap_queue_csn( op, syncCSN );
}
if ( dni.mods ) {
op->o_tag = LDAP_REQ_MODIFY;
@@ -2554,40 +2595,43 @@ syncrepl_del_nonpresent(
si->si_refreshDelete ^= NP_DELETE_ONE;
} else {
Filter *cf, *of;
+ Filter mmf[2];
+ AttributeAssertion mmaa;
memset( &an[0], 0, 2 * sizeof( AttributeName ) );
an[0].an_name = slap_schema.si_ad_entryUUID->ad_cname;
an[0].an_desc = slap_schema.si_ad_entryUUID;
op->ors_attrs = an;
op->ors_slimit = SLAP_NO_LIMIT;
+ op->ors_tlimit = SLAP_NO_LIMIT;
+ op->ors_limit = NULL;
op->ors_attrsonly = 0;
op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val );
/* In multimaster, updates can continue to arrive while
* we're searching. Limit the search result to entries
- * older than all of our cookie CSNs.
+ * older than our newest cookie CSN.
*/
if ( SLAP_MULTIMASTER( op->o_bd )) {
Filter *f;
int i;
- cf = op->o_tmpalloc( (sc->numcsns+1) * sizeof(Filter) +
- sc->numcsns * sizeof(AttributeAssertion), op->o_tmpmemctx );
- f = cf;
+
+ f = mmf;
f->f_choice = LDAP_FILTER_AND;
- f->f_next = NULL;
+ f->f_next = op->ors_filter;
f->f_and = f+1;
of = f->f_and;
+ f = of;
+ f->f_choice = LDAP_FILTER_LE;
+ f->f_ava = &mmaa;
+ f->f_av_desc = slap_schema.si_ad_entryCSN;
+ f->f_next = NULL;
+ BER_BVZERO( &f->f_av_value );
for ( i=0; inumcsns; i++ ) {
- f = of;
- f->f_choice = LDAP_FILTER_LE;
- f->f_ava = (AttributeAssertion *)(f+1);
- f->f_av_desc = slap_schema.si_ad_entryCSN;
- f->f_av_value = sc->ctxcsn[i];
- f->f_next = (Filter *)(f->f_ava+1);
- of = f->f_next;
+ if ( ber_bvcmp( &sc->ctxcsn[i], &f->f_av_value ) > 0 )
+ f->f_av_value = sc->ctxcsn[i];
}
- f->f_next = op->ors_filter;
of = op->ors_filter;
- op->ors_filter = cf;
+ op->ors_filter = mmf;
filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
} else {
cf = NULL;
@@ -2595,11 +2639,9 @@ syncrepl_del_nonpresent(
}
op->o_nocaching = 1;
- if ( limits_check( op, &rs_search ) == 0 ) {
- rc = be->be_search( op, &rs_search );
- }
+
+ rc = be->be_search( op, &rs_search );
if ( SLAP_MULTIMASTER( op->o_bd )) {
- op->o_tmpfree( cf, op->o_tmpmemctx );
op->ors_filter = of;
}
if ( op->ors_filter ) filter_free_x( op, op->ors_filter, 1 );
@@ -2862,6 +2904,9 @@ syncrepl_updateCookie(
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;
@@ -2878,6 +2923,15 @@ syncrepl_updateCookie(
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+#ifdef CHECK_CSN
+ for ( i=0; inumcsns; i++ ) {
+ assert( !syn->ssyn_validate( syn, syncCookie->ctxcsn+i ));
+ }
+ for ( i=0; isi_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 );
@@ -2980,6 +3034,12 @@ syncrepl_updateCookie(
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; isi_cookieState->cs_num; i++ ) {
+ assert( !syn->ssyn_validate( syn, si->si_cookieState->cs_vals+i ));
+ }
+#endif
+
return rc;
}
@@ -3152,33 +3212,37 @@ dn_callback(
struct berval old_p, new_p;
int is_ctx, new_sup = 0;
- /* Make sure new entry is actually newer than old entry */
- old = attr_find( rs->sr_entry->e_attrs,
- slap_schema.si_ad_entryCSN );
- new = attr_find( dni->new_entry->e_attrs,
- slap_schema.si_ad_entryCSN );
- if ( new && old ) {
- int rc;
- ber_len_t len = old->a_vals[0].bv_len;
- if ( len > new->a_vals[0].bv_len )
- len = new->a_vals[0].bv_len;
- rc = memcmp( old->a_vals[0].bv_val,
- new->a_vals[0].bv_val, len );
- if ( rc > 0 ) {
- Debug( LDAP_DEBUG_SYNC,
- "dn_callback : new entry is older than ours "
- "%s ours %s, new %s\n",
- rs->sr_entry->e_name.bv_val,
- old->a_vals[0].bv_val,
- new->a_vals[0].bv_val );
- return LDAP_SUCCESS;
- } else if ( rc == 0 ) {
- Debug( LDAP_DEBUG_SYNC,
- "dn_callback : entries have identical CSN "
- "%s %s\n",
- rs->sr_entry->e_name.bv_val,
- old->a_vals[0].bv_val, 0 );
- return LDAP_SUCCESS;
+ /* If old entry is not a glue entry, make sure new entry
+ * 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_entryCSN );
+ new = attr_find( dni->new_entry->e_attrs,
+ slap_schema.si_ad_entryCSN );
+ if ( new && old ) {
+ int rc;
+ ber_len_t len = old->a_vals[0].bv_len;
+ if ( len > new->a_vals[0].bv_len )
+ len = new->a_vals[0].bv_len;
+ rc = memcmp( old->a_vals[0].bv_val,
+ new->a_vals[0].bv_val, len );
+ if ( rc > 0 ) {
+ Debug( LDAP_DEBUG_SYNC,
+ "dn_callback : new entry is older than ours "
+ "%s ours %s, new %s\n",
+ rs->sr_entry->e_name.bv_val,
+ old->a_vals[0].bv_val,
+ new->a_vals[0].bv_val );
+ return LDAP_SUCCESS;
+ } else if ( rc == 0 ) {
+ Debug( LDAP_DEBUG_SYNC,
+ "dn_callback : entries have identical CSN "
+ "%s %s\n",
+ rs->sr_entry->e_name.bv_val,
+ old->a_vals[0].bv_val, 0 );
+ return LDAP_SUCCESS;
+ }
}
}
@@ -3304,8 +3368,8 @@ dn_callback(
* stays co-located with the other mod opattrs. But only
* if we know there are other valid mods.
*/
- if ( old->a_desc == slap_schema.si_ad_modifiersName &&
- dni->mods )
+ if ( dni->mods && ( old->a_desc == slap_schema.si_ad_modifiersName ||
+ old->a_desc == slap_schema.si_ad_modifyTimestamp ))
attr_cmp( op, NULL, new, &modtail, &ml );
else
attr_cmp( op, old, new, &modtail, &ml );
@@ -4287,13 +4351,22 @@ add_syncrepl(
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;
}
}
@@ -4490,6 +4563,7 @@ syncrepl_config( ConfigArgs *c )
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;
@@ -4498,19 +4572,21 @@ syncrepl_config( ConfigArgs *c )
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 );
}
@@ -4522,8 +4598,9 @@ syncrepl_config( ConfigArgs *c )
}
}
if ( !c->be->be_syncinfo ) {
- SLAP_DBFLAGS( c->be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW);
- if ( cs ) {
+ SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_SHADOW_MASK;
+ 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 );