]> git.sur5r.net Git - openldap/commitdiff
ITS#8281 fix delta-mmr with interrupted refresh
authorHoward Chu <hyc@openldap.org>
Fri, 23 Oct 2015 19:17:45 +0000 (20:17 +0100)
committerHoward Chu <hyc@openldap.org>
Sat, 24 Oct 2015 05:06:49 +0000 (06:06 +0100)
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
servers/slapd/overlays/syncprov.c

index 4804205c80421b81bd8606e6c29f060851511e08..d499343b6696d873a6eacadaaaedf0587af7523d 100644 (file)
@@ -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;
index d2da4c718133228053e2bf4bbcccd82d5812f1af..69be484165452ff6d7e4b4491188250ab1ef277c 100644 (file)
@@ -1915,10 +1915,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
@@ -2489,6 +2492,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; i<numcsns; i++ )
+                       sids[i] = si->si_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 */
@@ -2550,21 +2575,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; i<numcsns; i++ )
-                       sids[i] = si->si_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;
@@ -3155,7 +3165,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.