From 683c03fbc0f72daf4f763d3fa5acfc2b67e9ffa7 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 23 Oct 2015 20:17:45 +0100 Subject: [PATCH] ITS#8281 fix delta-mmr with interrupted refresh Prevent spurious contextCSN generation and ignore consumers when we have no contextCSN yet. But make sure to propagate valid contextCSN updates to accesslog/syncprov for delta consumers. --- servers/slapd/overlays/accesslog.c | 47 ++++++++++++++++++++++++++---- servers/slapd/overlays/syncprov.c | 44 +++++++++++++++++----------- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index f892c19983..7bd4bee372 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -1490,9 +1490,17 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( lo->mask & LOG_OP_WRITES ) { slap_callback *cb; - /* These internal ops are not logged */ - if ( op->o_dont_replicate && op->orm_no_opattrs ) + /* Most internal ops are not logged */ + if ( op->o_dont_replicate) { + /* Let contextCSN updates from syncrepl thru; the underlying + * syncprov needs to see them. Skip others. + */ + if (( op->o_tag != LDAP_REQ_MODIFY || + op->orm_modlist->sml_op != LDAP_MOD_REPLACE || + op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) && + op->orm_no_opattrs ) return SLAP_CB_CONTINUE; + } ldap_pvt_thread_mutex_lock( &li->li_log_mutex ); old = li->li_old; @@ -1831,10 +1839,29 @@ static int accesslog_response(Operation *op, SlapReply *rs) { op2.o_req_ndn = e->e_nname; op2.ora_e = e; op2.o_callback = &nullsc; + op2.o_csn = op->o_csn; + /* contextCSN updates may still reach here */ + op2.o_dont_replicate = op->o_dont_replicate; if (( lo->mask & LOG_OP_WRITES ) && !BER_BVISEMPTY( &op->o_csn )) { - slap_queue_csn( &op2, &op->o_csn ); - do_graduate = 1; + struct berval maxcsn; + char cbuf[LDAP_PVT_CSNSTR_BUFSIZE]; + int foundit; + cbuf[0] = '\0'; + maxcsn.bv_val = cbuf; + maxcsn.bv_len = sizeof(cbuf); + /* If there was a commit CSN on the main DB, + * we must propagate it to the log DB for its + * own syncprov. Otherwise, don't generate one. + */ + slap_get_commit_csn( op, &maxcsn, &foundit ); + if ( !BER_BVISEMPTY( &maxcsn ) ) { + slap_queue_csn( &op2, &op->o_csn ); + do_graduate = 1; + } else { + attr_merge_normalize_one( e, slap_schema.si_ad_entryCSN, + &op->o_csn, op->o_tmpmemctx ); + } } op2.o_bd->be_add( &op2, &rs2 ); @@ -1922,8 +1949,18 @@ accesslog_op_mod( Operation *op, SlapReply *rs ) int doit = 0; /* These internal ops are not logged */ - if ( op->o_dont_replicate && op->orm_no_opattrs ) + if ( op->o_dont_replicate ) { + /* Let contextCSN updates from syncrepl thru; the underlying + * syncprov needs to see them. Skip others. + */ + if (( op->o_tag != LDAP_REQ_MODIFY || + op->orm_modlist->sml_op != LDAP_MOD_REPLACE || + op->orm_modlist->sml_desc != slap_schema.si_ad_contextCSN ) && + op->orm_no_opattrs ) return SLAP_CB_CONTINUE; + /* give this a unique timestamp */ + op->o_tincr++; + } logop = accesslog_op2logop( op ); lo = logops+logop+EN_OFFSET; diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index 5fc6f842dc..6423d3f339 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -1917,10 +1917,13 @@ syncprov_op_response( Operation *op, SlapReply *rs ) } else { ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock ); } + if ( csn_changed ) + si->si_numops++; goto leave; } - si->si_numops++; + if ( csn_changed ) + si->si_numops++; if ( si->si_chkops || si->si_chktime ) { /* Never checkpoint adding the context entry, * it will deadlock @@ -2491,6 +2494,28 @@ syncprov_op_search( Operation *op, SlapReply *rs ) return rs->sr_err; } + /* snapshot the ctxcsn */ + ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock ); + numcsns = si->si_numcsns; + if ( numcsns ) { + ber_bvarray_dup_x( &ctxcsn, si->si_ctxcsn, op->o_tmpmemctx ); + sids = op->o_tmpalloc( numcsns * sizeof(int), op->o_tmpmemctx ); + for ( i=0; isi_sids[i]; + } else { + ctxcsn = NULL; + sids = NULL; + } + dirty = si->si_dirty; + ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock ); + + /* We know nothing - do nothing */ + if ( !numcsns ) { + rs->sr_err = LDAP_SUCCESS; + send_ldap_result( op, rs ); + return rs->sr_err; + } + srs = op->o_controls[slap_cids.sc_LDAPsync]; /* If this is a persistent search, set it up right away */ @@ -2552,21 +2577,6 @@ syncprov_op_search( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex ); } - /* snapshot the ctxcsn */ - ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock ); - numcsns = si->si_numcsns; - if ( numcsns ) { - ber_bvarray_dup_x( &ctxcsn, si->si_ctxcsn, op->o_tmpmemctx ); - sids = op->o_tmpalloc( numcsns * sizeof(int), op->o_tmpmemctx ); - for ( i=0; isi_sids[i]; - } else { - ctxcsn = NULL; - sids = NULL; - } - dirty = si->si_dirty; - ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock ); - /* If we have a cookie, handle the PRESENT lookups */ if ( srs->sr_state.ctxcsn ) { sessionlog *sl; @@ -3157,7 +3167,7 @@ syncprov_db_open( char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ]; struct berval csn; - if ( SLAP_SYNC_SHADOW( op->o_bd )) { + if ( slap_serverID || SLAP_SYNC_SHADOW( op->o_bd )) { /* If we're also a consumer, then don't generate anything. * Wait for our provider to send it to us, or for a local * modify if we have multimaster. -- 2.39.5