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;
/* 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;
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;
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;
}
{
struct re_s *rtask = arg;
syncops *so = rtask->arg;
- slap_overinst *on = so->s_op->o_private;
OperationBuffer opbuf;
Operation *op;
BackendDB be;
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?
*/
}
/* 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 );
Operation opm;
SlapReply rsm = { 0 };
slap_callback cb = {0};
+ BackendDB be;
mod.sml_numvals = si->si_numcsns;
mod.sml_values = si->si_ctxcsn;
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;
if ( mod.sml_next != NULL ) {
slap_mods_free( mod.sml_next, 1 );
}
- opm.orm_no_opattrs = 0;
}
static void
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;
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 );
/* 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 */
typedef struct SyncOperationBuffer {
Operation sob_op;
Opheader sob_hdr;
+ OpExtra sob_oe;
AttributeName sob_extra; /* not always present */
/* Further data allocated here */
} SyncOperationBuffer;
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;
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 ) {
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;
/* 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;
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;
*/
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;
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 );
}
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;
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 );
}
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 );
struct sync_cookie *syncCookie )
{
Backend *be = op->o_bd;
- Modifications mod[2];
+ Modifications mod;
struct berval first = BER_BVNULL;
int rc, i, j, len;
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] )
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];
}
}
/* 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];
}
/* 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;
/* 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;
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 );
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 );
- op->o_tmpfree( mod[0].sml_values, op->o_tmpmemctx );
+ if ( mod.sml_next ) slap_mods_free( mod.sml_next, 1 );
+ op->o_tmpfree( mod.sml_values, op->o_tmpmemctx );
return rc;
}