Commit 2770e8df authored by Howard Chu's avatar Howard Chu
Browse files

Sync with HEAD:

ITS#5401, #5405, #5407, #5413, #5418, #5426, #5430, #5432, #5433, #5434
parent e25cba04
......@@ -696,7 +696,10 @@ again:
break;
}
fop.o_bd->bd_info = on->on_info->oi_orig;
if ( on->on_next )
fop.o_bd->bd_info = (BackendInfo *)on->on_next;
else
fop.o_bd->bd_info = on->on_info->oi_orig;
fop.o_bd->be_search( &fop, &frs );
fop.o_bd->bd_info = (BackendInfo *)on;
......@@ -837,8 +840,10 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
/* Play back queued responses */
static int
syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
syncprov_qplay( Operation *op, struct re_s *rtask )
{
syncops *so = rtask->arg;
slap_overinst *on = LDAP_SLIST_FIRST(&so->s_op->o_extra)->oe_key;
syncres *sr;
Entry *e;
opcookie opc;
......@@ -853,10 +858,10 @@ syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
so->s_res = sr->s_next;
if ( !so->s_res )
so->s_restail = NULL;
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
/* Exit loop with mutex held */
if ( !sr || so->s_op->o_abandon )
break;
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
opc.sdn = sr->s_dn;
opc.sndn = sr->s_ndn;
......@@ -883,9 +888,24 @@ syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
ch_free( sr );
if ( rc )
if ( rc ) {
/* Exit loop with mutex held */
ldap_pvt_thread_mutex_lock( &so->s_mutex );
break;
}
}
/* wait until we get explicitly scheduled again */
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
if ( rc == 0 ) {
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 1 );
} else {
/* bail out on any error */
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
}
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return rc;
}
......@@ -895,7 +915,6 @@ syncprov_qtask( void *ctx, void *arg )
{
struct re_s *rtask = arg;
syncops *so = rtask->arg;
slap_overinst *on = so->s_op->o_private;
OperationBuffer opbuf;
Operation *op;
BackendDB be;
......@@ -917,25 +936,14 @@ syncprov_qtask( void *ctx, void *arg )
be = *so->s_op->o_bd;
be.be_flags |= SLAP_DBFLAG_OVERLAY;
op->o_bd = &be;
op->o_private = NULL;
LDAP_SLIST_FIRST(&op->o_extra) = NULL;
op->o_callback = NULL;
rc = syncprov_qplay( op, on, so );
rc = syncprov_qplay( op, rtask );
/* decrement use count... */
syncprov_free_syncop( so );
/* wait until we get explicitly scheduled again */
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
if ( rc == 0 ) {
ldap_pvt_runqueue_resched( &slapd_rq, rtask, 1 );
} else {
/* bail out on any error */
ldap_pvt_runqueue_remove( &slapd_rq, rtask );
}
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
#if 0 /* FIXME: connection_close isn't exported from slapd.
* should it be?
*/
......@@ -1209,7 +1217,7 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
}
/* check if current o_req_dn is in scope and matches filter */
if ( fc.fscope && test_filter( op, e, ss->s_op->ors_filter ) ==
if ( fc.fscope && test_filter( ss->s_op, e, ss->s_op->ors_filter ) ==
LDAP_COMPARE_TRUE ) {
if ( saveit ) {
sm = op->o_tmpalloc( sizeof(syncmatches), op->o_tmpmemctx );
......@@ -1301,6 +1309,7 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
Operation opm;
SlapReply rsm = { 0 };
slap_callback cb = {0};
BackendDB be;
mod.sml_numvals = si->si_numcsns;
mod.sml_values = si->si_ctxcsn;
......@@ -1316,8 +1325,12 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
opm.o_callback = &cb;
opm.orm_modlist = &mod;
opm.orm_no_opattrs = 1;
opm.o_req_dn = op->o_bd->be_suffix[0];
opm.o_req_ndn = op->o_bd->be_nsuffix[0];
if ( SLAP_GLUE_SUBORDINATE( op->o_bd )) {
be = *on->on_info->oi_origdb;
opm.o_bd = &be;
}
opm.o_req_dn = opm.o_bd->be_suffix[0];
opm.o_req_ndn = opm.o_bd->be_nsuffix[0];
opm.o_bd->bd_info = on->on_info->oi_orig;
opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
opm.o_no_schema_check = 1;
......@@ -1325,7 +1338,6 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
if ( mod.sml_next != NULL ) {
slap_mods_free( mod.sml_next, 1 );
}
opm.orm_no_opattrs = 0;
}
static void
......@@ -1519,7 +1531,10 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
fop.ors_filter = ⁡
cb.sc_response = playlog_cb;
fop.o_bd->bd_info = on->on_info->oi_orig;
if ( on->on_next )
fop.o_bd->bd_info = (BackendInfo *)on->on_next;
else
fop.o_bd->bd_info = on->on_info->oi_orig;
for ( i=ndel; i<num; i++ ) {
if ( uuids[i].bv_len == 0 ) continue;
......@@ -1540,13 +1555,16 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
if ( ndel ) {
struct berval cookie;
slap_compose_sync_cookie( op, &cookie, delcsn, srs->sr_state.rid,
srs->sr_state.sid );
if ( delcsn[0].bv_len ) {
slap_compose_sync_cookie( op, &cookie, delcsn, srs->sr_state.rid,
srs->sr_state.sid );
}
Debug( LDAP_DEBUG_SYNC, "syncprov_playlog: cookie=%s\n", cookie.bv_val, 0, 0 );
uuids[ndel].bv_val = NULL;
syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, &cookie, 0, uuids, 1 );
syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET,
delcsn[0].bv_len ? &cookie : NULL, 0, uuids, 1 );
op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
}
op->o_tmpfree( uuids, op->o_tmpmemctx );
......@@ -1775,7 +1793,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 */
......@@ -1843,6 +1867,7 @@ syncprov_search_cleanup( Operation *op, SlapReply *rs )
typedef struct SyncOperationBuffer {
Operation sob_op;
Opheader sob_hdr;
OpExtra sob_oe;
AttributeName sob_extra; /* not always present */
/* Further data allocated here */
} SyncOperationBuffer;
......@@ -1871,6 +1896,7 @@ syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
sopbuf2 = ch_calloc( 1, size );
op2 = &sopbuf2->sob_op;
op2->o_hdr = &sopbuf2->sob_hdr;
LDAP_SLIST_FIRST(&op2->o_extra) = &sopbuf2->sob_oe;
/* Copy the fields we care about explicitly, leave the rest alone */
*op2->o_hdr = *op->o_hdr;
......@@ -1878,7 +1904,8 @@ syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
op2->o_time = op->o_time;
op2->o_bd = on->on_info->oi_origdb;
op2->o_request = op->o_request;
op2->o_private = on;
LDAP_SLIST_FIRST(&op2->o_extra)->oe_key = on;
LDAP_SLIST_NEXT(LDAP_SLIST_FIRST(&op2->o_extra), oe_next) = NULL;
ptr = (char *) sopbuf2 + offsetof( SyncOperationBuffer, sob_extra );
if ( i ) {
......@@ -1929,12 +1956,10 @@ syncprov_detach_op( Operation *op, syncops *so, slap_overinst *on )
op2->o_do_not_cache = 1;
/* Add op2 to conn so abandon will find us */
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
op->o_conn->c_n_ops_executing++;
op->o_conn->c_n_ops_completed--;
LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op2, o_next );
so->s_flags |= PS_IS_DETACHED;
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
/* Prevent anyone else from trying to send a result for this op */
op->o_abandon = 1;
......@@ -2044,15 +2069,27 @@ syncprov_search_response( Operation *op, SlapReply *rs )
/* Detach this Op from frontend control */
ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex );
ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
/* Turn off the refreshing flag */
ss->ss_so->s_flags ^= PS_IS_REFRESHING;
/* But not if this connection was closed along the way */
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
syncprov_free_syncop( ss->ss_so );
return SLAPD_ABANDON;
syncprov_detach_op( op, ss->ss_so, on );
} else {
/* Turn off the refreshing flag */
ss->ss_so->s_flags ^= PS_IS_REFRESHING;
syncprov_detach_op( op, ss->ss_so, on );
/* If there are queued responses, fire them off */
if ( ss->ss_so->s_res )
syncprov_qstart( ss->ss_so );
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
/* If there are queued responses, fire them off */
if ( ss->ss_so->s_res )
syncprov_qstart( ss->ss_so );
}
ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
return LDAP_SUCCESS;
......
......@@ -468,16 +468,16 @@ do_syncrep1(
ldap_set_option( si->si_ld, LDAP_OPT_TIMELIMIT, &si->si_tlimit );
si->si_syncCookie.rid = si->si_rid;
si->si_syncCookie.sid = SLAP_SINGLE_SHADOW( si->si_be ) ? -1 :
slap_serverID;
/* We've just started up, or the remote server hasn't sent us
* any meaningful state.
*/
if ( BER_BVISNULL( &si->si_syncCookie.octet_str ) ) {
int i;
si->si_syncCookie.rid = si->si_rid;
si->si_syncCookie.sid = SLAP_SINGLE_SHADOW( si->si_be ) ? -1 :
slap_serverID;
LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) {
if ( si->si_rid == sc->rid ) {
cmdline_cookie_found = 1;
......@@ -552,26 +552,27 @@ do_syncrep1(
*/
a.a_desc = slap_schema.si_ad_contextCSN;
e.e_attrs = &a;
e.e_name = si->si_wbe->be_suffix[0];
e.e_nname = si->si_wbe->be_nsuffix[0];
rs.sr_entry = &e;
rs.sr_flags = REP_ENTRY_MODIFIABLE;
e.e_name = op->o_bd->be_suffix[0];
e.e_nname = op->o_bd->be_nsuffix[0];
at[0].an_name = a.a_desc->ad_cname;
at[0].an_desc = a.a_desc;
BER_BVZERO( &at[1].an_name );
rs.sr_entry = &e;
rs.sr_flags = REP_ENTRY_MODIFIABLE;
rs.sr_attrs = at;
op->o_req_dn = e.e_name;
op->o_req_ndn = e.e_nname;
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
rc = backend_operational( op, &rs );
if ( rc == LDAP_SUCCESS && a.a_vals ) {
if ( rc == LDAP_SUCCESS && a.a_nvals ) {
int num = a.a_numvals;
/* check for differences */
if ( num != si->si_cookieState->cs_num ) {
changed = 1;
} else {
for ( i=0; i<num; i++ ) {
if ( ber_bvcmp( &a.a_vals[i],
if ( ber_bvcmp( &a.a_nvals[i],
&si->si_cookieState->cs_vals[i] )) {
changed =1;
break;
......@@ -582,50 +583,57 @@ do_syncrep1(
ber_bvarray_free( si->si_cookieState->cs_vals );
ch_free( si->si_cookieState->cs_sids );
si->si_cookieState->cs_num = num;
si->si_cookieState->cs_vals = a.a_vals;
si->si_cookieState->cs_sids = slap_parse_csn_sids( a.a_vals,
si->si_cookieState->cs_vals = a.a_nvals;
si->si_cookieState->cs_sids = slap_parse_csn_sids( a.a_nvals,
num, NULL );
si->si_cookieState->cs_age++;
} else {
ber_bvarray_free( a.a_vals );
ber_bvarray_free( a.a_nvals );
}
changed = 0;
ber_bvarray_free( a.a_vals );
}
/* See if the cookieState has changed due to anything outside
* this particular consumer. That includes other consumers in
* the same context, or local changes detected above.
*/
if ( si->si_cookieState->cs_num > 1 && si->si_cookieAge !=
if ( si->si_cookieState->cs_num > 0 && si->si_cookieAge !=
si->si_cookieState->cs_age ) {
for (i=0; !BER_BVISNULL( &si->si_syncCookie.ctxcsn[i] ); i++) {
/* bogus, just dup everything */
if ( si->si_syncCookie.sids[i] == -1 ) {
ber_bvarray_free( si->si_syncCookie.ctxcsn );
ber_bvarray_dup_x( &si->si_syncCookie.ctxcsn,
si->si_cookieState->cs_vals, NULL );
changed = 1;
break;
}
for (j=0; j<si->si_cookieState->cs_num; j++) {
if ( si->si_syncCookie.sids[i] !=
si->si_cookieState->cs_sids[j] )
continue;
if ( bvmatch( &si->si_syncCookie.ctxcsn[i],
&si->si_cookieState->cs_vals[j] ))
if ( !si->si_syncCookie.numcsns ) {
ber_bvarray_free( si->si_syncCookie.ctxcsn );
ber_bvarray_dup_x( &si->si_syncCookie.ctxcsn,
si->si_cookieState->cs_vals, NULL );
changed = 1;
} else {
for (i=0; !BER_BVISNULL( &si->si_syncCookie.ctxcsn[i] ); i++) {
/* bogus, just dup everything */
if ( si->si_syncCookie.sids[i] == -1 ) {
ber_bvarray_free( si->si_syncCookie.ctxcsn );
ber_bvarray_dup_x( &si->si_syncCookie.ctxcsn,
si->si_cookieState->cs_vals, NULL );
changed = 1;
break;
ber_bvreplace( &si->si_syncCookie.ctxcsn[i],
&si->si_cookieState->cs_vals[j] );
changed = 1;
break;
}
for (j=0; j<si->si_cookieState->cs_num; j++) {
if ( si->si_syncCookie.sids[i] !=
si->si_cookieState->cs_sids[j] )
continue;
if ( bvmatch( &si->si_syncCookie.ctxcsn[i],
&si->si_cookieState->cs_vals[j] ))
break;
ber_bvreplace( &si->si_syncCookie.ctxcsn[i],
&si->si_cookieState->cs_vals[j] );
changed = 1;
break;
}
}
}
if ( changed ) {
ch_free( si->si_syncCookie.octet_str.bv_val );
slap_compose_sync_cookie( NULL, &si->si_syncCookie.octet_str,
si->si_syncCookie.ctxcsn, si->si_syncCookie.rid,
SLAP_SINGLE_SHADOW( si->si_be ) ? -1 : slap_serverID );
}
}
if ( changed ) {
si->si_cookieAge = si->si_cookieState->cs_age;
ch_free( si->si_syncCookie.octet_str.bv_val );
slap_compose_sync_cookie( NULL, &si->si_syncCookie.octet_str,
si->si_syncCookie.ctxcsn, si->si_syncCookie.rid,
si->si_syncCookie.sid );
}
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
}
......@@ -664,14 +672,14 @@ compare_csns( struct sync_cookie *sc1, struct sync_cookie *sc2, int *which )
return -1;
}
for (i=0; !BER_BVISNULL( &sc1->ctxcsn[i] ); i++) {
for (j=0; !BER_BVISNULL( &sc2->ctxcsn[j] ); j++) {
for (i=0; i<sc1->numcsns; i++) {
for (j=0; i<sc2->numcsns; j++) {
if ( sc1->sids[i] != sc2->sids[j] )
continue;
value_match( &match, slap_schema.si_ad_entryCSN,
slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
&sc1->ctxcsn[i], &sc2->ctxcsn[i], &text );
&sc1->ctxcsn[i], &sc2->ctxcsn[j], &text );
if ( match < 0 ) {
*which = j;
return match;
......@@ -1193,25 +1201,40 @@ do_syncrepl(
op->o_tmpmfuncs = &ch_mfuncs;
op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
op->o_bd = be = si->si_be;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
if ( !si->si_schemachecking )
op->o_no_schema_check = 1;
/* If we're glued, send writes through the glue parent */
be = si->si_be;
/* Coordinate contextCSN updates with any syncprov overlays
* in use. This may be complicated by the use of the glue
* overlay.
*
* Typically there is a single syncprov mastering the entire
* glued tree. In that case, our contextCSN updates should
* go to the master DB.
*
* Alternatively, there may be individual syncprov overlays
* on each glued branch. In that case, each syncprov only
* knows about changes within its own branch. And so our
* contextCSN updates should only go to the local DB.
*/
if ( !si->si_wbe ) {
if ( SLAP_GLUE_SUBORDINATE( be )) {
if ( SLAP_GLUE_SUBORDINATE( be ) && !overlay_is_inst( be, "syncprov" )) {
si->si_wbe = select_backend( &be->be_nsuffix[0], 1 );
} else {
si->si_wbe = be;
}
}
if ( !si->si_schemachecking )
op->o_no_schema_check = 1;
/* Establish session, do search */
if ( !si->si_ld ) {
si->si_refreshDelete = 0;
si->si_refreshPresent = 0;
/* use main DB when retrieving contextCSN */
op->o_bd = si->si_wbe;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
rc = do_syncrep1( op, si );
}
......@@ -1220,6 +1243,10 @@ reload:
if ( rc == LDAP_SUCCESS ) {
ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s );
/* use current DB */
op->o_bd = be;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
rc = do_syncrep2( op, si );
if ( rc == LDAP_SYNC_REFRESH_REQUIRED ) {
rc = ldap_sync_search( si, op->o_tmpmemctx );
......@@ -2613,7 +2640,7 @@ syncrepl_updateCookie(
struct sync_cookie *syncCookie )
{
Backend *be = op->o_bd;
Modifications mod[2];
Modifications mod;
struct berval first = BER_BVNULL;
int rc, i, j, len;
......@@ -2621,24 +2648,22 @@ syncrepl_updateCookie(
slap_callback cb = { NULL };
SlapReply rs_modify = {REP_RESULT};
mod[0].sml_op = LDAP_MOD_DELETE;
mod[0].sml_desc = slap_schema.si_ad_contextCSN;
mod[0].sml_type = mod[0].sml_desc->ad_cname;
mod[0].sml_values = NULL;
mod[0].sml_nvalues = NULL;
mod[0].sml_numvals = 0;
mod[0].sml_next = &mod[1];
mod[1].sml_op = LDAP_MOD_ADD;
mod[1].sml_desc = slap_schema.si_ad_contextCSN;
mod[1].sml_type = mod[0].sml_desc->ad_cname;
mod[1].sml_values = NULL;
mod[1].sml_nvalues = NULL;
mod[1].sml_numvals = 0;
mod[1].sml_next = NULL;
mod.sml_op = LDAP_MOD_REPLACE;
mod.sml_desc = slap_schema.si_ad_contextCSN;
mod.sml_type = mod.sml_desc->ad_cname;
mod.sml_nvalues = NULL;
mod.sml_next = NULL;
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
/* 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 );
for ( i=0; i<mod.sml_numvals; i++ )
mod.sml_values[i] = si->si_cookieState->cs_vals[i];
BER_BVZERO( &mod.sml_values[i] );
/* find any CSNs in the syncCookie that are newer than the cookieState */
for ( i=0; i<syncCookie->numcsns; i++ ) {
for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
if ( syncCookie->sids[i] != si->si_cookieState->cs_sids[j] )
......@@ -2648,12 +2673,7 @@ syncrepl_updateCookie(
len = si->si_cookieState->cs_vals[j].bv_len;
if ( memcmp( syncCookie->ctxcsn[i].bv_val,
si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) {
ber_bvarray_add_x( &mod[0].sml_values,
&si->si_cookieState->cs_vals[j], op->o_tmpmemctx );
mod[0].sml_numvals++;
ber_bvarray_add_x( &mod[1].sml_values,
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
mod[1].sml_numvals++;
mod.sml_values[j] = syncCookie->ctxcsn[i];
if ( BER_BVISNULL( &first ))
first = syncCookie->ctxcsn[i];
}
......@@ -2661,9 +2681,10 @@ syncrepl_updateCookie(
}
/* there was no match for this SID, it's a new CSN */
if ( j == si->si_cookieState->cs_num ) {
ber_bvarray_add_x( &mod[1].sml_values,
&syncCookie->ctxcsn[i], op->o_tmpmemctx );
mod[1].sml_numvals++;
mod.sml_values = op->o_tmprealloc( mod.sml_values,
( mod.sml_numvals+2 )*sizeof(struct berval), op->o_tmpmemctx );
mod.sml_values[mod.sml_numvals++] = syncCookie->ctxcsn[i];
BER_BVZERO( &mod.sml_values[mod.sml_numvals] );
if ( BER_BVISNULL( &first ))
first = syncCookie->ctxcsn[i];
}
......@@ -2671,6 +2692,7 @@ syncrepl_updateCookie(
/* Should never happen, ITS#5065 */
if ( BER_BVISNULL( &first )) {
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
op->o_tmpfree( mod.sml_values, op->o_tmpmemctx );
return 0;
}
op->o_bd = si->si_wbe;
......@@ -2688,11 +2710,7 @@ syncrepl_updateCookie(
/* update contextCSN */
op->o_msgid = SLAP_SYNC_UPDATE_MSGID;
if ( mod[0].sml_values )
op->orm_modlist = mod;
else
op->orm_modlist = &mod[1];
op->orm_modlist = &mod;
op->orm_no_opattrs = 1;
rc = op->o_bd->be_modify( op, &rs_modify );
op->orm_no_opattrs = 0;
......@@ -2702,21 +2720,15 @@ syncrepl_updateCookie(
slap_sync_cookie_free( &si->si_syncCookie, 0 );
slap_dup_sync_cookie( &si->si_syncCookie, syncCookie );
/* If we replaced any old values */
if ( mod[0].sml_values ) {
for ( i=0; !BER_BVISNULL( &mod[0].sml_values[i] ); i++ ) {
for ( j=0; j<si->si_cookieState->cs_num; j++ ) {
if ( mod[0].sml_values[i].bv_val !=
si->si_cookieState->cs_vals[j].bv_val )
continue;
ber_bvreplace( &si->si_cookieState->cs_vals[j],
&mod[1].sml_values[i] );
break;
}
}
} else {
/* Else we just added */
si->si_cookieState->cs_num += syncCookie->numcsns;
value_add( &si->si_cookieState->cs_vals, syncCookie->ctxcsn );
for ( i=0; i<si->si_cookieState->cs_num; i++ ) {
if ( mod.sml_values[i].bv_val != si->si_cookieState->cs_vals[i].bv_val )
ber_bvreplace( &si->si_cookieState->cs_vals[i],
&mod.sml_values[i] );
}
/* Handle any added values */
if ( i < mod.sml_numvals ) {
si->si_cookieState->cs_num = mod.sml_numvals;
value_add( &si->si_cookieState->cs_vals, &mod.sml_values[i] );
free( si->si_cookieState->cs_sids );
si->si_cookieState->cs_sids = slap_parse_csn_sids(
si->si_cookieState->cs_vals, si->si_cookieState->cs_num, NULL );
......@@ -2734,9 +2746,8 @@ syncrepl_updateCookie(
op->o_bd = be;
op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx );
BER_BVZERO( &op->o_csn );
if ( mod[1].sml_next ) slap_mods_free( mod[1].sml_next, 1 );
op->o_tmpfree( mod[1].sml_values, op->o_tmpmemctx );