]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/syncprov.c
ITS#5401
[openldap] / servers / slapd / overlays / syncprov.c
index a466f52022e8121378f2b079fca9f9de8f785317..a284d2ae0a619d3df6801445ce98f03ec0ea928f 100644 (file)
@@ -2,7 +2,7 @@
 /* syncprov.c - syncrepl provider */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2006 The OpenLDAP Foundation.
+ * Copyright 2004-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -127,7 +127,7 @@ typedef struct syncprov_info_t {
        time_t  si_chklast;     /* time of last checkpoint */
        Avlnode *si_mods;       /* entries being modified */
        sessionlog      *si_logs;
-       ldap_pvt_thread_mutex_t si_csn_mutex;
+       ldap_pvt_thread_rdwr_t  si_csn_rwlock;
        ldap_pvt_thread_mutex_t si_ops_mutex;
        ldap_pvt_thread_mutex_t si_mods_mutex;
        char            si_ctxcsnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
@@ -401,6 +401,7 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
                slap_callback cb = {0};
                Operation fop;
                SlapReply frs = { REP_RESULT };
+               BackendInfo *bi;
                int rc;
 
                fc->fss->s_flags ^= PS_FIND_BASE;
@@ -412,6 +413,7 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
                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;
@@ -429,9 +431,8 @@ syncprov_findbase( Operation *op, fbase_cookie *fc )
                fop.ors_filter = &generic_filter;
                fop.ors_filterstr = generic_filterstr;
 
-               fop.o_bd->bd_info = on->on_info->oi_orig;
-               rc = fop.o_bd->be_search( &fop, &frs );
-               fop.o_bd->bd_info = (BackendInfo *)on;
+               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;
@@ -580,7 +581,7 @@ syncprov_findcsn( Operation *op, find_csn_t mode )
        char buf[LDAP_LUTIL_CSNSTR_BUFSIZE + STRLENOF("(entryCSN<=)")];
        char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
        struct berval maxcsn;
-       Filter cf, af;
+       Filter cf;
 #ifdef LDAP_COMP_MATCH
        AttributeAssertion eq = { NULL, BER_BVNULL, NULL };
 #else
@@ -641,6 +642,7 @@ again:
                } else {
                        cf.f_choice = LDAP_FILTER_LE;
                        fop.ors_limit = &fc_limits;
+                       memset( &fc_limits, 0, sizeof( fc_limits ));
                        fc_limits.lms_s_unchecked = 1;
                        fop.ors_filterstr.bv_len = sprintf( buf, "(entryCSN<=%s)",
                                cf.f_av_value.bv_val );
@@ -652,14 +654,8 @@ again:
                cb.sc_response = findcsn_cb;
                break;
        case FIND_PRESENT:
-               af.f_choice = LDAP_FILTER_AND;
-               af.f_next = NULL;
-               af.f_and = &cf;
-               cf.f_choice = LDAP_FILTER_LE;
-               cf.f_av_value = srs->sr_state.ctxcsn;
-               cf.f_next = op->ors_filter;
-               fop.ors_filter = &af;
-               filter2bv_x( &fop, fop.ors_filter, &fop.ors_filterstr );
+               fop.ors_filter = op->ors_filter;
+               fop.ors_filterstr = op->ors_filterstr;
                fop.ors_attrsonly = 0;
                fop.ors_attrs = uuid_anlist;
                fop.ors_slimit = SLAP_NO_LIMIT;
@@ -703,7 +699,6 @@ again:
                break;
        case FIND_PRESENT:
                op->o_tmpfree( pcookie.uuids, op->o_tmpmemctx );
-               op->o_tmpfree( fop.ors_filterstr.bv_val, op->o_tmpmemctx );
                break;
        }
 
@@ -774,7 +769,7 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
                        rs.sr_flags = REP_ENTRY_MUSTRELEASE;
                if ( opc->sreference ) {
                        rs.sr_ref = get_entry_referrals( op, rs.sr_entry );
-                       send_search_reference( op, &rs );
+                       rs.sr_err = send_search_reference( op, &rs );
                        ber_bvarray_free( rs.sr_ref );
                        if ( !rs.sr_entry )
                                *e = NULL;
@@ -786,7 +781,7 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
                if ( rs.sr_entry->e_private )
                        rs.sr_flags = REP_ENTRY_MUSTRELEASE;
                rs.sr_attrs = op->ors_attrs;
-               send_search_entry( op, &rs );
+               rs.sr_err = send_search_entry( op, &rs );
                if ( !rs.sr_entry )
                        *e = NULL;
                break;
@@ -798,9 +793,9 @@ syncprov_sendresp( Operation *op, opcookie *opc, syncops *so,
                if ( opc->sreference ) {
                        struct berval bv = BER_BVNULL;
                        rs.sr_ref = &bv;
-                       send_search_reference( op, &rs );
+                       rs.sr_err = send_search_reference( op, &rs );
                } else {
-                       send_search_entry( op, &rs );
+                       rs.sr_err = send_search_entry( op, &rs );
                }
                break;
        default:
@@ -825,7 +820,6 @@ syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
        int rc = 0;
 
        opc.son = on;
-       op->o_bd->bd_info = (BackendInfo *)on->on_info;
 
        for (;;) {
                ldap_pvt_thread_mutex_lock( &so->s_mutex );
@@ -847,16 +841,19 @@ syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
                e = NULL;
 
                if ( sr->s_mode != LDAP_SYNC_DELETE ) {
-                       rc = be_entry_get_rw( op, &opc.sndn, NULL, NULL, 0, &e );
+                       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 );
 
                if ( e ) {
-                       be_entry_release_rw( op, e, 0 );
+                       overlay_entry_release_ov( op, e, 0, on );
                }
 
                ch_free( sr );
@@ -864,7 +861,6 @@ syncprov_qplay( Operation *op, slap_overinst *on, syncops *so )
                if ( rc )
                        break;
        }
-       op->o_bd->bd_info = (BackendInfo *)on;
        return rc;
 }
 
@@ -878,6 +874,7 @@ syncprov_qtask( void *ctx, void *arg )
        OperationBuffer opbuf;
        Operation *op;
        BackendDB be;
+       int rc;
 
        op = (Operation *) &opbuf;
        *op = *so->s_op;
@@ -898,15 +895,20 @@ syncprov_qtask( void *ctx, void *arg )
        op->o_private = NULL;
        op->o_callback = NULL;
 
-       (void)syncprov_qplay( op, on, so );
+       rc = syncprov_qplay( op, on, so );
 
        /* 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, so->s_qtask );
-       ldap_pvt_runqueue_resched( &slapd_rq, so->s_qtask, 1 );
+       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 );
 
        return NULL;
@@ -1058,7 +1060,7 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
 
        fbase_cookie fc;
        syncops *ss, *sprev, *snext;
-       Entry *e;
+       Entry *e = NULL;
        Attribute *a;
        int rc;
        struct berval newdn;
@@ -1080,15 +1082,13 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
                        db = *op->o_bd;
                        op->o_bd = &db;
                }
-               op->o_bd->bd_info = (BackendInfo *)on->on_info;
-               rc = be_entry_get_rw( op, fc.fdn, NULL, NULL, 0, &e );
+               rc = overlay_entry_get_ov( op, fc.fdn, NULL, NULL, 0, &e, on );
                /* If we're sending responses now, make a copy and unlock the DB */
                if ( e && !saveit ) {
                        Entry *e2 = entry_dup( e );
-                       be_entry_release_rw( op, e, 0 );
+                       overlay_entry_release_ov( op, e, 0, on );
                        e = e2;
                }
-               op->o_bd->bd_info = (BackendInfo *)on;
                if ( rc ) {
                        op->o_bd = b0;
                        return;
@@ -1243,9 +1243,9 @@ syncprov_op_cleanup( Operation *op, SlapReply *rs )
 }
 
 static void
-syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on,
-       struct berval *csn )
+syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
 {
+       syncprov_info_t         *si = on->on_bi.bi_private;
        Modifications mod;
        Operation opm;
        SlapReply rsm = { 0 };
@@ -1253,12 +1253,12 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on,
        slap_callback cb = {0};
 
        /* If ctxcsn is empty, delete it */
-       if ( BER_BVISEMPTY( csn )) {
+       if ( BER_BVISEMPTY( &si->si_ctxcsn )) {
                mod.sml_values = NULL;
        } else {
                mod.sml_values = bv;
                bv[1].bv_val = NULL;
-               bv[0] = *csn;
+               bv[0] = si->si_ctxcsn;
        }
        mod.sml_nvalues = NULL;
        mod.sml_desc = slap_schema.si_ad_contextCSN;
@@ -1371,9 +1371,19 @@ syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
         * and everything else at the end. Do this first so we can
         * unlock the list mutex.
         */
+       Debug( LDAP_DEBUG_SYNC, "srs csn %s\n", srs->sr_state.ctxcsn.bv_val, 0, 0 );
        for ( se=sl->sl_head; se; se=se->se_next ) {
-               if ( ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn ) <= 0 ) continue;
-               if ( ber_bvcmp( &se->se_csn, ctxcsn ) > 0 ) break;
+               Debug( LDAP_DEBUG_SYNC, "log csn %s\n", se->se_csn.bv_val, 0, 0 );
+               ndel = ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn );
+               if ( ndel <= 0 ) {
+                       Debug( LDAP_DEBUG_SYNC, "cmp %d, too old\n", ndel, 0, 0 );
+                       continue;
+               }
+               ndel = ber_bvcmp( &se->se_csn, ctxcsn );
+               if ( ndel > 0 ) {
+                       Debug( LDAP_DEBUG_SYNC, "cmp %d, too new\n", ndel, 0, 0 );
+                       break;
+               }
                if ( se->se_tag == LDAP_REQ_DELETE ) {
                        j = i;
                        i++;
@@ -1493,11 +1503,11 @@ syncprov_op_response( Operation *op, SlapReply *rs )
        {
                struct berval maxcsn = BER_BVNULL;
                char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
-               int do_check = 0;
+               int do_check = 0, have_psearches;
 
                /* Update our context CSN */
                cbuf[0] = '\0';
-               ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
+               ldap_pvt_thread_rdwr_wlock( &si->si_csn_rwlock );
                slap_get_commit_csn( op, &maxcsn );
                if ( !BER_BVISNULL( &maxcsn ) ) {
                        strcpy( cbuf, maxcsn.bv_val );
@@ -1510,7 +1520,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
                /* Don't do any processing for consumer contextCSN updates */
                if ( SLAP_SYNC_SHADOW( op->o_bd ) && 
                        op->o_msgid == SLAP_SYNC_UPDATE_MSGID ) {
-                       ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
+                       ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
                        return SLAP_CB_CONTINUE;
                }
 
@@ -1526,17 +1536,22 @@ syncprov_op_response( Operation *op, SlapReply *rs )
                                si->si_chklast = op->o_time;
                        }
                }
-               ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
-
-               opc->sctxcsn.bv_len = maxcsn.bv_len;
-               opc->sctxcsn.bv_val = cbuf;
+               ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
 
                if ( do_check ) {
-                       syncprov_checkpoint( op, rs, on, &opc->sctxcsn );
+                       ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock );
+                       syncprov_checkpoint( op, rs, on );
+                       ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
                }
 
+               opc->sctxcsn.bv_len = maxcsn.bv_len;
+               opc->sctxcsn.bv_val = cbuf;
+
                /* Handle any persistent searches */
-               if ( si->si_ops ) {
+               ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
+               have_psearches = ( si->si_ops != NULL );
+               ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
+               if ( have_psearches ) {
                        switch(op->o_tag) {
                        case LDAP_REQ_ADD:
                        case LDAP_REQ_MODIFY:
@@ -1594,7 +1609,7 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
                a.a_vals = bv;
                a.a_nvals = a.a_vals;
 
-               ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
+               ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock );
 
                rs->sr_err = access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc,
                        &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL );
@@ -1623,7 +1638,7 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
 
 return_results:;
 
-               ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
+               ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
 
                send_ldap_result( op, rs );
 
@@ -1641,12 +1656,19 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
 {
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
        syncprov_info_t         *si = on->on_bi.bi_private;
+       slap_callback *cb;
+       opcookie *opc;
+       int have_psearches, cbsize;
 
-       slap_callback *cb = op->o_tmpcalloc(1, sizeof(slap_callback)+
-               sizeof(opcookie) +
-               (si->si_ops ? sizeof(modinst) : 0 ),
-               op->o_tmpmemctx);
-       opcookie *opc = (opcookie *)(cb+1);
+       ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
+       have_psearches = ( si->si_ops != NULL );
+       ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
+
+       cbsize = sizeof(slap_callback) + sizeof(opcookie) +
+               (have_psearches ? sizeof(modinst) : 0 );
+
+       cb = op->o_tmpcalloc(1, cbsize, op->o_tmpmemctx);
+       opc = (opcookie *)(cb+1);
        opc->son = on;
        cb->sc_response = syncprov_op_response;
        cb->sc_cleanup = syncprov_op_cleanup;
@@ -1657,7 +1679,7 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
        /* If there are active persistent searches, lock this operation.
         * See seqmod.c for the locking logic on its own.
         */
-       if ( si->si_ops ) {
+       if ( have_psearches ) {
                modtarget *mt, mtdummy;
                modinst *mi;
 
@@ -1704,7 +1726,7 @@ syncprov_op_mod( Operation *op, SlapReply *rs )
                }
        }
 
-       if (( si->si_ops || si->si_logs ) && op->o_tag != LDAP_REQ_ADD )
+       if (( have_psearches || si->si_logs ) && op->o_tag != LDAP_REQ_ADD )
                syncprov_matchops( op, opc, 1 );
 
        return SLAP_CB_CONTINUE;
@@ -1818,12 +1840,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;
@@ -1834,6 +1854,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
 {
        searchstate *ss = op->o_callback->sc_private;
        slap_overinst *on = ss->ss_on;
+       syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
        sync_control *srs = op->o_controls[slap_cids.sc_LDAPsync];
 
        if ( rs->sr_type == REP_SEARCH || rs->sr_type == REP_SEARCHREF ) {
@@ -1853,8 +1874,9 @@ syncprov_search_response( Operation *op, SlapReply *rs )
                        a = attr_find( rs->sr_operational_attrs, slap_schema.si_ad_entryCSN );
                }
                if ( a ) {
+                       /* If not a persistent search */
                        /* Make sure entry is less than the snapshot'd contextCSN */
-                       if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
+                       if ( !ss->ss_so && ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
                                Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s greater than snapshot %s\n",
                                        rs->sr_entry->e_name.bv_val,
                                        a->a_nvals[0].bv_val,
@@ -1875,8 +1897,16 @@ syncprov_search_response( Operation *op, SlapReply *rs )
                rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
                        op->o_tmpmemctx );
                rs->sr_ctrls[1] = NULL;
-               rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
-                       LDAP_SYNC_ADD, rs->sr_ctrls, 0, 0, NULL );
+               /* If we're in delta-sync mode, always send a cookie */
+               if ( si->si_nopres && si->si_usehint && a ) {
+                       struct berval cookie;
+                       slap_compose_sync_cookie( op, &cookie, a->a_nvals, srs->sr_state.rid );
+                       rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
+                               LDAP_SYNC_ADD, rs->sr_ctrls, 0, 1, &cookie );
+               } else {
+                       rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
+                               LDAP_SYNC_ADD, rs->sr_ctrls, 0, 0, NULL );
+               }
        } else if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS ) {
                struct berval cookie;
 
@@ -1901,15 +1931,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 );
+
+                       /* 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_ab_cleanup will free this syncop */
+                               return SLAPD_ABANDON;
+
+                       } else {
+                               /* Turn off the refreshing flag */
+                               ss->ss_so->s_flags ^= PS_IS_REFRESHING;
 
-                       /* Turn off the refreshing flag */
-                       ss->ss_so->s_flags ^= PS_IS_REFRESHING;
+                               syncprov_detach_op( op, ss->ss_so, on );
 
-                       syncprov_detach_op( op, ss->ss_so, on );
+                               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 );
+                               /* 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;
@@ -1983,10 +2025,10 @@ syncprov_op_search( Operation *op, SlapReply *rs )
        }
 
        /* snapshot the ctxcsn */
-       ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
+       ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock );
        strcpy( csnbuf, si->si_ctxcsnbuf );
        ctxcsn.bv_len = si->si_ctxcsn.bv_len;
-       ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
+       ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
        ctxcsn.bv_val = csnbuf;
        
        /* If we have a cookie, handle the PRESENT lookups */
@@ -2143,13 +2185,13 @@ syncprov_operational(
                                *ap = a;
                        }
 
-                       ldap_pvt_thread_mutex_lock( &si->si_csn_mutex );
+                       ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock );
                        if ( !ap ) {
                                strcpy( a->a_vals[0].bv_val, si->si_ctxcsnbuf );
                        } else {
                                ber_dupbv( &a->a_vals[0], &si->si_ctxcsn );
                        }
-                       ldap_pvt_thread_mutex_unlock( &si->si_csn_mutex );
+                       ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
                }
        }
        return SLAP_CB_CONTINUE;
@@ -2267,27 +2309,31 @@ sp_cf_gen(ConfigArgs *c)
        switch ( c->type ) {
        case SP_CHKPT:
                if ( lutil_atoi( &si->si_chkops, c->argv[1] ) != 0 ) {
-                       sprintf( c->msg, "%s unable to parse checkpoint ops # \"%s\"",
+                       snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint ops # \"%s\"",
                                c->argv[0], c->argv[1] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( si->si_chkops <= 0 ) {
-                       sprintf( c->msg, "%s invalid checkpoint ops # \"%d\"",
+                       snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint ops # \"%d\"",
                                c->argv[0], si->si_chkops );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( lutil_atoi( &si->si_chktime, c->argv[2] ) != 0 ) {
-                       sprintf( c->msg, "%s unable to parse checkpoint time \"%s\"",
+                       snprintf( c->msg, sizeof( c->msg ), "%s unable to parse checkpoint time \"%s\"",
                                c->argv[0], c->argv[1] );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->msg, 0 );
                        return ARG_BAD_CONF;
                }
                if ( si->si_chktime <= 0 ) {
-                       sprintf( c->msg, "%s invalid checkpoint time \"%d\"",
+                       snprintf( c->msg, sizeof( c->msg ), "%s invalid checkpoint time \"%d\"",
                                c->argv[0], si->si_chkops );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->msg, 0 );
                        return ARG_BAD_CONF;
                }
                si->si_chktime *= 60;
@@ -2297,9 +2343,10 @@ sp_cf_gen(ConfigArgs *c)
                int size = c->value_int;
 
                if ( size < 0 ) {
-                       sprintf( c->msg, "%s size %d is negative",
+                       snprintf( c->msg, sizeof( c->msg ), "%s size %d is negative",
                                c->argv[0], size );
-                       Debug( LDAP_DEBUG_CONFIG, "%s: %s\n", c->log, c->msg, 0 );
+                       Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->msg, 0 );
                        return ARG_BAD_CONF;
                }
                sl = si->si_logs;
@@ -2353,7 +2400,7 @@ syncprov_db_open(
        OperationBuffer opbuf = { 0 };
        char ctxcsnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
        Operation *op = (Operation *) &opbuf;
-       Entry *e;
+       Entry *e = NULL;
        Attribute *a;
        int rc;
        void *thrctx = NULL;
@@ -2381,9 +2428,8 @@ syncprov_db_open(
 
        ctxcsnbuf[0] = '\0';
 
-       op->o_bd->bd_info = on->on_info->oi_orig;
-       rc = be_entry_get_rw( op, be->be_nsuffix, NULL,
-               slap_schema.si_ad_contextCSN, 0, &e );
+       rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL,
+               slap_schema.si_ad_contextCSN, 0, &e, on );
 
        if ( e ) {
                ldap_pvt_thread_t tid;
@@ -2398,9 +2444,8 @@ syncprov_db_open(
                        si->si_ctxcsnbuf[si->si_ctxcsn.bv_len] = '\0';
                        strcpy( ctxcsnbuf, si->si_ctxcsnbuf );
                }
-               be_entry_release_rw( op, e, 0 );
+               overlay_entry_release_ov( op, e, 0, on );
                if ( !BER_BVISEMPTY( &si->si_ctxcsn ) ) {
-                       op->o_bd->bd_info = (BackendInfo *)on;
                        op->o_req_dn = be->be_suffix[0];
                        op->o_req_ndn = be->be_nsuffix[0];
                        op->ors_scope = LDAP_SCOPE_SUBTREE;
@@ -2430,7 +2475,6 @@ syncprov_db_open(
 
 out:
        op->o_bd->bd_info = (BackendInfo *)on;
-       ldap_pvt_thread_pool_context_reset( thrctx );
        return 0;
 }
 
@@ -2448,7 +2492,7 @@ syncprov_db_close(
                return 0;
        }
        if ( si->si_numops ) {
-               Connection conn;
+               Connection conn = {0};
                OperationBuffer opbuf;
                Operation *op = (Operation *) &opbuf;
                SlapReply rs = {REP_RESULT};
@@ -2459,8 +2503,7 @@ syncprov_db_close(
                op->o_bd = be;
                op->o_dn = be->be_rootdn;
                op->o_ndn = be->be_rootndn;
-               syncprov_checkpoint( op, &rs, on, &si->si_ctxcsn );
-               ldap_pvt_thread_pool_context_reset( thrctx );
+               syncprov_checkpoint( op, &rs, on );
        }
 
     return 0;
@@ -2474,9 +2517,16 @@ syncprov_db_init(
        slap_overinst   *on = (slap_overinst *)be->bd_info;
        syncprov_info_t *si;
 
+       if ( SLAP_ISGLOBALOVERLAY( be ) ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "syncprov must be instantiated within a database.\n",
+                       0, 0, 0 );
+               return 1;
+       }
+
        si = ch_calloc(1, sizeof(syncprov_info_t));
        on->on_bi.bi_private = si;
-       ldap_pvt_thread_mutex_init( &si->si_csn_mutex );
+       ldap_pvt_thread_rdwr_init( &si->si_csn_rwlock );
        ldap_pvt_thread_mutex_init( &si->si_ops_mutex );
        ldap_pvt_thread_mutex_init( &si->si_mods_mutex );
        si->si_ctxcsn.bv_val = si->si_ctxcsnbuf;
@@ -2514,7 +2564,7 @@ syncprov_db_destroy(
                }
                ldap_pvt_thread_mutex_destroy( &si->si_mods_mutex );
                ldap_pvt_thread_mutex_destroy( &si->si_ops_mutex );
-               ldap_pvt_thread_mutex_destroy( &si->si_csn_mutex );
+               ldap_pvt_thread_rdwr_destroy( &si->si_csn_rwlock );
                ch_free( si );
        }
 
@@ -2604,8 +2654,8 @@ static int syncprov_parseCtrl (
        sr->sr_rhint = rhint;
        if (!BER_BVISNULL(&cookie)) {
                ber_dupbv_x( &sr->sr_state.octet_str, &cookie, op->o_tmpmemctx );
-               slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx );
-               if ( sr->sr_state.rid == -1 ) {
+               if ( slap_parse_sync_cookie( &sr->sr_state, op->o_tmpmemctx ) ||
+                       sr->sr_state.rid == -1 ) {
                        rs->sr_text = "Sync control : cookie parsing error";
                        return LDAP_PROTOCOL_ERROR;
                }