--- servers/slapd/overlays/syncprov.c 2009/03/05 20:20:47 1.147.2.47 +++ servers/slapd/overlays/syncprov.c 2008/05/08 23:51:26 1.234 @@ -1,8 +1,8 @@ -/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/syncprov.c,v 1.147.2.46 2009/02/23 02:15:32 quanah Exp $ */ +/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/syncprov.c,v 1.233 2008/05/06 01:03:47 hyc Exp $ */ /* syncprov.c - syncrepl provider */ /* This work is part of OpenLDAP Software . * - * Copyright 2004-2009 The OpenLDAP Foundation. + * Copyright 2004-2008 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,10 +28,6 @@ #include "config.h" #include "ldap_rq.h" -#ifdef LDAP_DEVEL -#define CHECK_CSN 1 -#endif - /* A modify request on a particular entry */ typedef struct modinst { struct modinst *mi_next; @@ -397,6 +393,9 @@ static struct berval generic_filterstr = static int syncprov_findbase( Operation *op, fbase_cookie *fc ) { + opcookie *opc = op->o_callback->sc_private; + slap_overinst *on = opc->son; + /* Use basic parameters from syncrepl search, but use * current op's threadctx / tmpmemctx */ @@ -405,6 +404,7 @@ syncprov_findbase( Operation *op, fbase_ slap_callback cb = {0}; Operation fop; SlapReply frs = { REP_RESULT }; + BackendInfo *bi; int rc; fc->fss->s_flags ^= PS_FIND_BASE; @@ -412,10 +412,11 @@ syncprov_findbase( Operation *op, fbase_ fop = *fc->fss->s_op; - fop.o_bd = fop.o_bd->bd_self; fop.o_hdr = op->o_hdr; + fop.o_bd = op->o_bd; fop.o_time = op->o_time; fop.o_tincr = op->o_tincr; + bi = op->o_bd->bd_info; cb.sc_response = findbase_cb; cb.sc_private = fc; @@ -433,7 +434,8 @@ syncprov_findbase( Operation *op, fbase_ fop.ors_filter = &generic_filter; fop.ors_filterstr = generic_filterstr; - rc = fop.o_bd->be_search( &fop, &frs ); + rc = overlay_op_walk( &fop, &frs, op_search, on->on_info, on ); + op->o_bd->bd_info = bi; } else { ldap_pvt_thread_mutex_unlock( &fc->fss->s_mutex ); fc->fbase = 1; @@ -498,8 +500,7 @@ findmax_cb( Operation *op, SlapReply *rs Attribute *a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ); - if ( a && ber_bvcmp( &a->a_vals[0], maxcsn ) > 0 && - slap_parse_csn_sid( &a->a_vals[0] ) == slap_serverID ) { + if ( a && ber_bvcmp( &a->a_vals[0], maxcsn ) > 0 ) { maxcsn->bv_len = a->a_vals[0].bv_len; strcpy( maxcsn->bv_val, a->a_vals[0].bv_val ); } @@ -589,7 +590,7 @@ syncprov_findcsn( Operation *op, find_cs sync_control *srs = NULL; struct slap_limits_set fc_limits; int i, rc = LDAP_SUCCESS, findcsn_retry = 1; - int maxid; + int maxid = 0; if ( mode != FIND_MAXCSN ) { srs = op->o_controls[slap_cids.sc_LDAPsync]; @@ -615,23 +616,17 @@ again: switch( mode ) { case FIND_MAXCSN: cf.f_choice = LDAP_FILTER_GE; - /* If there are multiple CSNs, use the one with our serverID */ - for ( i=0; isi_numcsns; i++) { - if ( slap_serverID == si->si_sids[i] ) { + cf.f_av_value = si->si_ctxcsn[0]; + /* If there are multiple CSNs, use the largest */ + for ( i=1; isi_numcsns; i++) { + if ( ber_bvcmp( &cf.f_av_value, &si->si_ctxcsn[i] ) < 0 ) { + cf.f_av_value = si->si_ctxcsn[i]; maxid = i; - break; } } - if ( i == si->si_numcsns ) { - /* No match: this is multimaster, and none of the content in the DB - * originated locally. Treat like no CSN. - */ - return LDAP_NO_SUCH_OBJECT; - } - cf.f_av_value = si->si_ctxcsn[maxid]; fop.ors_filterstr.bv_len = snprintf( buf, sizeof( buf ), "(entryCSN>=%s)", cf.f_av_value.bv_val ); - if ( fop.ors_filterstr.bv_len >= sizeof( buf ) ) { + if ( fop.ors_filterstr.bv_len < 0 || fop.ors_filterstr.bv_len >= sizeof( buf ) ) { return LDAP_OTHER; } fop.ors_attrsonly = 0; @@ -668,7 +663,7 @@ again: fop.ors_filterstr.bv_len = snprintf( buf, sizeof( buf ), "(entryCSN<=%s)", cf.f_av_value.bv_val ); } - if ( fop.ors_filterstr.bv_len >= sizeof( buf ) ) { + if ( fop.ors_filterstr.bv_len < 0 || fop.ors_filterstr.bv_len >= sizeof( buf ) ) { return LDAP_OTHER; } fop.ors_attrsonly = 1; @@ -708,10 +703,6 @@ again: switch( mode ) { case FIND_MAXCSN: if ( ber_bvcmp( &si->si_ctxcsn[maxid], &maxcsn )) { -#ifdef CHECK_CSN - Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax; - assert( !syn->ssyn_validate( syn, &maxcsn )); -#endif ber_bvreplace( &si->si_ctxcsn[maxid], &maxcsn ); si->si_numops++; /* ensure a checkpoint */ } @@ -808,7 +799,7 @@ syncprov_sendresp( Operation *op, opcook rs.sr_entry = *e; if ( rs.sr_entry->e_private ) rs.sr_flags = REP_ENTRY_MUSTRELEASE; - if ( opc->sreference && so->s_op->o_managedsait <= SLAP_CONTROL_IGNORED ) { + if ( opc->sreference ) { rs.sr_ref = get_entry_referrals( op, rs.sr_entry ); rs.sr_err = send_search_reference( op, &rs ); ber_bvarray_free( rs.sr_ref ); @@ -831,7 +822,7 @@ syncprov_sendresp( Operation *op, opcook e_uuid.e_name = opc->sdn; e_uuid.e_nname = opc->sndn; rs.sr_entry = &e_uuid; - if ( opc->sreference && so->s_op->o_managedsait <= SLAP_CONTROL_IGNORED ) { + if ( opc->sreference ) { struct berval bv = BER_BVNULL; rs.sr_ref = &bv; rs.sr_err = send_search_reference( op, &rs ); @@ -876,34 +867,27 @@ syncprov_qplay( Operation *op, struct re break; ldap_pvt_thread_mutex_unlock( &so->s_mutex ); - if ( sr->s_mode == LDAP_SYNC_NEW_COOKIE ) { - SlapReply rs = { REP_INTERMEDIATE }; - - rc = syncprov_sendinfo( op, &rs, LDAP_TAG_SYNC_NEW_COOKIE, - &sr->s_csn, 0, NULL, 0 ); - } else { - opc.sdn = sr->s_dn; - opc.sndn = sr->s_ndn; - opc.suuid = sr->s_uuid; - opc.sctxcsn = sr->s_csn; - opc.sreference = sr->s_isreference; - e = NULL; - - if ( sr->s_mode != LDAP_SYNC_DELETE ) { - rc = overlay_entry_get_ov( op, &opc.sndn, NULL, NULL, 0, &e, on ); - if ( rc ) { - Debug( LDAP_DEBUG_SYNC, "syncprov_qplay: failed to get %s, " - "error (%d), ignoring...\n", opc.sndn.bv_val, rc, 0 ); - ch_free( sr ); - rc = 0; - continue; - } + opc.sdn = sr->s_dn; + opc.sndn = sr->s_ndn; + opc.suuid = sr->s_uuid; + opc.sctxcsn = sr->s_csn; + opc.sreference = sr->s_isreference; + e = NULL; + + if ( sr->s_mode != LDAP_SYNC_DELETE ) { + rc = overlay_entry_get_ov( op, &opc.sndn, NULL, NULL, 0, &e, on ); + if ( rc ) { + Debug( LDAP_DEBUG_SYNC, "syncprov_qplay: failed to get %s, " + "error (%d), ignoring...\n", opc.sndn.bv_val, rc, 0 ); + ch_free( sr ); + rc = 0; + continue; } - rc = syncprov_sendresp( op, &opc, so, &e, sr->s_mode ); + } + rc = syncprov_sendresp( op, &opc, so, &e, sr->s_mode ); - if ( e ) { - overlay_entry_release_ov( op, e, 0, on ); - } + if ( e ) { + overlay_entry_release_ov( op, e, 0, on ); } ch_free( sr ); @@ -923,10 +907,6 @@ syncprov_qplay( Operation *op, struct re } else { /* bail out on any error */ ldap_pvt_runqueue_remove( &slapd_rq, rtask ); - - /* Prevent duplicate remove */ - if ( so->s_qtask == rtask ) - so->s_qtask = NULL; } ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); ldap_pvt_thread_mutex_unlock( &so->s_mutex ); @@ -1014,25 +994,17 @@ static int syncprov_qresp( opcookie *opc, syncops *so, int mode ) { syncres *sr; - int srsize; - struct berval cookie = opc->sctxcsn; - - if ( mode == LDAP_SYNC_NEW_COOKIE ) { - syncprov_info_t *si = opc->son->on_bi.bi_private; + int sid, srsize; - slap_compose_sync_cookie( NULL, &cookie, si->si_ctxcsn, - so->s_rid, so->s_sid); - } else if ( opc->sctxcsn.bv_len ) { - /* Don't send changes back to their originator */ - int sid = slap_parse_csn_sid( &opc->sctxcsn ); - if ( sid >= 0 && sid == so->s_sid ) - return LDAP_SUCCESS; - } + /* Don't send changes back to their originator */ + sid = slap_parse_csn_sid( &opc->sctxcsn ); + if ( sid >= 0 && sid == so->s_sid ) + return LDAP_SUCCESS; srsize = sizeof(syncres) + opc->suuid.bv_len + 1 + opc->sdn.bv_len + 1 + opc->sndn.bv_len + 1; - if ( cookie.bv_len ) - srsize += cookie.bv_len + 1; + if ( opc->sctxcsn.bv_len ) + srsize += opc->sctxcsn.bv_len + 1; sr = ch_malloc( srsize ); sr->s_next = NULL; sr->s_dn.bv_val = (char *)(sr + 1); @@ -1046,17 +1018,13 @@ syncprov_qresp( opcookie *opc, syncops * opc->sndn.bv_val ) + 1; sr->s_uuid.bv_len = opc->suuid.bv_len; AC_MEMCPY( sr->s_uuid.bv_val, opc->suuid.bv_val, opc->suuid.bv_len ); - if ( cookie.bv_len ) { + if ( opc->sctxcsn.bv_len ) { sr->s_csn.bv_val = sr->s_uuid.bv_val + sr->s_uuid.bv_len + 1; - strcpy( sr->s_csn.bv_val, cookie.bv_val ); + strcpy( sr->s_csn.bv_val, opc->sctxcsn.bv_val ); } else { sr->s_csn.bv_val = NULL; } - sr->s_csn.bv_len = cookie.bv_len; - - if ( mode == LDAP_SYNC_NEW_COOKIE && cookie.bv_val ) { - ch_free( cookie.bv_val ); - } + sr->s_csn.bv_len = opc->sctxcsn.bv_len; ldap_pvt_thread_mutex_lock( &so->s_mutex ); if ( !so->s_res ) { @@ -1209,7 +1177,6 @@ syncprov_matchops( Operation *op, opcook sprev = ss, ss=snext) { Operation op2; - Opheader oh; syncmatches *sm; int found = 0; @@ -1257,14 +1224,8 @@ syncprov_matchops( Operation *op, opcook } } - if ( fc.fscope ) { + if ( fc.fscope ) op2 = *ss->s_op; - oh = *op->o_hdr; - oh.oh_conn = ss->s_op->o_conn; - oh.oh_connid = ss->s_op->o_connid; - op2.o_hdr = &oh; - op2.o_extra = op->o_extra; - } /* check if current o_req_dn is in scope and matches filter */ if ( fc.fscope && test_filter( &op2, e, ss->s_op->ors_filter ) == @@ -1285,14 +1246,6 @@ syncprov_matchops( Operation *op, opcook } else if ( !saveit && found ) { /* send DELETE */ syncprov_qresp( opc, ss, LDAP_SYNC_DELETE ); - } else if ( !saveit ) { - syncprov_qresp( opc, ss, LDAP_SYNC_NEW_COOKIE ); - } - if ( !saveit && found ) { - /* Decrement s_inuse, was incremented when called - * with saveit == TRUE - */ - syncprov_free_syncop( ss ); } } ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex ); @@ -1368,20 +1321,13 @@ syncprov_checkpoint( Operation *op, Slap SlapReply rsm = { 0 }; slap_callback cb = {0}; BackendDB be; -#ifdef CHECK_CSN - Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax; - int i; - for ( i=0; isi_numcsns; i++ ) { - assert( !syn->ssyn_validate( syn, si->si_ctxcsn+i )); - } -#endif mod.sml_numvals = si->si_numcsns; mod.sml_values = si->si_ctxcsn; mod.sml_nvalues = NULL; mod.sml_desc = slap_schema.si_ad_contextCSN; mod.sml_op = LDAP_MOD_REPLACE; - mod.sml_flags = SLAP_MOD_INTERNAL; + mod.sml_flags = 0; mod.sml_next = NULL; cb.sc_response = slap_null_cb; @@ -1403,11 +1349,6 @@ syncprov_checkpoint( Operation *op, Slap if ( mod.sml_next != NULL ) { slap_mods_free( mod.sml_next, 1 ); } -#ifdef CHECK_CSN - for ( i=0; isi_numcsns; i++ ) { - assert( !syn->ssyn_validate( syn, si->si_ctxcsn+i )); - } -#endif } static void @@ -1625,16 +1566,14 @@ syncprov_playlog( Operation *op, SlapRep 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 ); } + 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, delcsn[0].bv_len ? &cookie : NULL, 0, uuids, 1 ); - if ( delcsn[0].bv_len ) { - op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx ); - } + op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx ); } op->o_tmpfree( uuids, op->o_tmpmemctx ); } @@ -1649,41 +1588,22 @@ syncprov_op_response( Operation *op, Sla if ( rs->sr_err == LDAP_SUCCESS ) { - struct berval maxcsn; + struct berval maxcsn = BER_BVNULL; char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; - int do_check = 0, have_psearches, foundit, csn_changed = 0; + int do_check = 0, have_psearches; /* Update our context CSN */ cbuf[0] = '\0'; - maxcsn.bv_val = cbuf; - maxcsn.bv_len = sizeof(cbuf); ldap_pvt_thread_rdwr_wlock( &si->si_csn_rwlock ); - slap_get_commit_csn( op, &maxcsn, &foundit ); - if ( BER_BVISEMPTY( &maxcsn ) && SLAP_GLUE_SUBORDINATE( op->o_bd )) { - /* syncrepl queues the CSN values in the db where - * it is configured , not where the changes are made. - * So look for a value in the glue db if we didn't - * find any in this db. - */ - BackendDB *be = op->o_bd; - op->o_bd = select_backend( &be->be_nsuffix[0], 1); - maxcsn.bv_val = cbuf; - maxcsn.bv_len = sizeof(cbuf); - slap_get_commit_csn( op, &maxcsn, &foundit ); - op->o_bd = be; - } - if ( !BER_BVISEMPTY( &maxcsn ) ) { + slap_get_commit_csn( op, &maxcsn ); + if ( !BER_BVISNULL( &maxcsn ) ) { int i, sid; -#ifdef CHECK_CSN - Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax; - assert( !syn->ssyn_validate( syn, &maxcsn )); -#endif + strcpy( cbuf, maxcsn.bv_val ); sid = slap_parse_csn_sid( &maxcsn ); for ( i=0; isi_numcsns; i++ ) { if ( sid == si->si_sids[i] ) { if ( ber_bvcmp( &maxcsn, &si->si_ctxcsn[i] ) > 0 ) { ber_bvreplace( &si->si_ctxcsn[i], &maxcsn ); - csn_changed = 1; } break; } @@ -1691,20 +1611,16 @@ syncprov_op_response( Operation *op, Sla /* It's a new SID for us */ if ( i == si->si_numcsns ) { value_add_one( &si->si_ctxcsn, &maxcsn ); - csn_changed = 1; si->si_numcsns++; si->si_sids = ch_realloc( si->si_sids, si->si_numcsns * sizeof(int)); si->si_sids[i] = sid; } - } else if ( !foundit ) { - /* internal ops that aren't meant to be replicated */ - ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock ); - return SLAP_CB_CONTINUE; } /* Don't do any processing for consumer contextCSN updates */ - if ( op->o_dont_replicate ) { + if ( SLAP_SYNC_SHADOW( op->o_bd ) && + op->o_msgid == SLAP_SYNC_UPDATE_MSGID ) { ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock ); return SLAP_CB_CONTINUE; } @@ -1733,10 +1649,8 @@ syncprov_op_response( Operation *op, Sla ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock ); } - /* only update consumer ctx if this is a newer csn */ - if ( csn_changed ) { - opc->sctxcsn = maxcsn; - } + opc->sctxcsn.bv_len = maxcsn.bv_len; + opc->sctxcsn.bv_val = cbuf; /* Handle any persistent searches */ ldap_pvt_thread_mutex_lock( &si->si_ops_mutex ); @@ -1799,7 +1713,6 @@ syncprov_op_compare( Operation *op, Slap a.a_vals = si->si_ctxcsn; a.a_nvals = a.a_vals; - a.a_numvals = si->si_numcsns; rs->sr_err = access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc, &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ); @@ -1999,7 +1912,6 @@ syncprov_detach_op( Operation *op, synco op2->o_time = op->o_time; op2->o_bd = on->on_info->oi_origdb; op2->o_request = op->o_request; - op2->o_managedsait = op->o_managedsait; LDAP_SLIST_FIRST(&op2->o_extra)->oe_key = on; LDAP_SLIST_NEXT(LDAP_SLIST_FIRST(&op2->o_extra), oe_next) = NULL; @@ -2173,16 +2085,17 @@ syncprov_search_response( Operation *op, op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx ); /* 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 ); /* But not if this connection was closed along the way */ if ( op->o_abandon ) { ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - /* syncprov_ab_cleanup will free this syncop */ + ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex ); + syncprov_free_syncop( ss->ss_so ); return SLAPD_ABANDON; } else { - ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex ); /* Turn off the refreshing flag */ ss->ss_so->s_flags ^= PS_IS_REFRESHING; @@ -2193,8 +2106,8 @@ syncprov_search_response( Operation *op, /* 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 ); } + ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex ); return LDAP_SUCCESS; } @@ -2225,6 +2138,7 @@ syncprov_op_search( Operation *op, SlapR } srs = op->o_controls[slap_cids.sc_LDAPsync]; + op->o_managedsait = SLAP_CONTROL_NONCRITICAL; /* If this is a persistent search, set it up right away */ if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) { @@ -2383,15 +2297,6 @@ no_change: if ( !(op->o_sync_mode & SLA send_ldap_error( op, rs, LDAP_SYNC_REFRESH_REQUIRED, "sync cookie is stale" ); return rs->sr_err; } - if ( srs->sr_state.ctxcsn ) { - ber_bvarray_free_x( srs->sr_state.ctxcsn, op->o_tmpmemctx ); - srs->sr_state.ctxcsn = NULL; - } - if ( srs->sr_state.sids ) { - slap_sl_free( srs->sr_state.sids, op->o_tmpmemctx ); - srs->sr_state.sids = NULL; - } - srs->sr_state.numcsns = 0; } else { gotstate = 1; /* If changed and doing Present lookup, send Present UUIDs */ @@ -2570,11 +2475,7 @@ static ConfigOCs spocs[] = { "NAME 'olcSyncProvConfig' " "DESC 'SyncRepl Provider configuration' " "SUP olcOverlayConfig " - "MAY ( olcSpCheckpoint " - "$ olcSpSessionlog " - "$ olcSpNoPresent " - "$ olcSpReloadHint " - ") )", + "MAY ( olcSpCheckpoint $ olcSpSessionlog $ olcSpNoPresent ) )", Cft_Overlay, spcfg }, { NULL, 0, NULL } }; @@ -2593,7 +2494,7 @@ sp_cf_gen(ConfigArgs *c) struct berval bv; bv.bv_len = snprintf( c->cr_msg, sizeof( c->cr_msg ), "%d %d", si->si_chkops, si->si_chktime ); - if ( bv.bv_len >= sizeof( c->cr_msg ) ) { + if ( bv.bv_len < 0 || bv.bv_len >= sizeof( c->cr_msg ) ) { rc = 1; } else { bv.bv_val = c->cr_msg; @@ -2787,7 +2688,7 @@ syncprov_db_open( si->si_sids = slap_parse_csn_sids( si->si_ctxcsn, a->a_numvals, NULL ); } overlay_entry_release_ov( op, e, 0, on ); - if ( si->si_ctxcsn && !SLAP_DBCLEAN( be )) { + if ( si->si_ctxcsn ) { op->o_req_dn = be->be_suffix[0]; op->o_req_ndn = be->be_nsuffix[0]; op->ors_scope = LDAP_SCOPE_SUBTREE;