From 2770e8df679491d2adcfcc41b34d4d2f74311cbf Mon Sep 17 00:00:00 2001 From: Howard Chu <hyc@openldap.org> Date: Fri, 21 Mar 2008 02:06:42 +0000 Subject: [PATCH] Sync with HEAD: ITS#5401, #5405, #5407, #5413, #5418, #5426, #5430, #5432, #5433, #5434 --- servers/slapd/overlays/syncprov.c | 111 ++++++++++------ servers/slapd/syncrepl.c | 211 ++++++++++++++++-------------- 2 files changed, 185 insertions(+), 137 deletions(-) diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index ad8b9bb329..74d841b8bf 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -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; diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index f862d8e3e8..e8ddee979a 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -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 ); - 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; } -- GitLab