]> git.sur5r.net Git - openldap/commitdiff
ITS#6373
authorQuanah Gibson-Mount <quanah@openldap.org>
Wed, 18 Nov 2009 02:16:15 +0000 (02:16 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Wed, 18 Nov 2009 02:16:15 +0000 (02:16 +0000)
CHANGES
doc/man/man5/slapd-config.5
doc/man/man5/slapd.conf.5
servers/slapd/bconfig.c
servers/slapd/ctxcsn.c
servers/slapd/overlays/syncprov.c
servers/slapd/proto-slap.h
servers/slapd/sasl.c
servers/slapd/slap.h
servers/slapd/slapadd.c
servers/slapd/syncrepl.c

diff --git a/CHANGES b/CHANGES
index 99921383ccc63756aee8ee083c94a56ba02bfbe3..e1619a9fa125b990c875f78c470d16157ec9446b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,7 @@ OpenLDAP 2.4.20 Engineering
        Fixed libldap uninitialized return value (ITS#6355)
        Fixed liblutil constant (ITS#5909)
        Added slapd handling of hex server IDs (ITS#6297)
+       Added slapd syncrepl contextCSN storing in subentry (ITS#6373)
        Fixed slapd asserts in minimal environment (ITS#6361)
        Fixed slapd configArgs initialization (ITS#6363)
        Fixed slapd debug handling of LDAP_DEBUG_ANY (ITS#6324)
index a646deecefb2e575354970eb662e566c281d2b7f..8ec7a52744bb89eed470126e70e9101bdb5c72d7 100644 (file)
@@ -1614,6 +1614,11 @@ with the inner suffix must come first in the configuration file.
 You may also want to glue such databases together with the
 .B olcSubordinate
 attribute.
+.TP
+.B olcSyncUseSubentry: TRUE | FALSE
+Store the syncrepl contextCSN in a subentry instead of the context entry
+of the database. The subentry's RDN will be "cn=ldapsync". The default is
+FALSE, meaning the contextCSN is stored in the context entry.
 .HP
 .hy 0
 .B olcSyncrepl: rid=<replica ID>
index 0ff35429e9b95152b43186ba71dd4fd058ebd07a..8d0e3c88cc4dd46b14bd9c0e7203f33d1b08cbef 100644 (file)
@@ -1602,6 +1602,11 @@ in order to work over all of the glued databases. E.g.
        overlay syncprov
 .fi
 .RE
+.TP
+.B sync_use_subentry 
+Store the syncrepl contextCSN in a subentry instead of the context entry
+of the database. The subentry's RDN will be "cn=ldapsync". By default
+the contextCSN is stored in the context entry.
 .HP
 .hy 0
 .B syncrepl rid=<replica ID>
index 90cd6229261de78f65fd8f013b43a82db06a2224..dbed5f1b83a0ad7566f4368248eccf41e459673a 100644 (file)
@@ -190,6 +190,7 @@ enum {
        CFG_IX_INTLEN,
        CFG_SYNTAX,
        CFG_ACL_ADD,
+       CFG_SYNC_SUBENTRY,
 
        CFG_LAST
 };
@@ -604,6 +605,10 @@ static ConfigTable config_back_cf_table[] = {
                &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
                        "EQUALITY distinguishedNameMatch "
                        "SYNTAX OMsDN )", NULL, NULL },
+       { "sync_use_subentry", NULL, 0, 0, 0, ARG_ON_OFF|ARG_DB|ARG_MAGIC|CFG_SYNC_SUBENTRY,
+               &config_generic, "( OLcfgDbAt:0.19 NAME 'olcSyncUseSubentry' "
+                       "DESC 'Store sync context in a subentry' "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
                &syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
                        "EQUALITY caseIgnoreMatch "
@@ -815,7 +820,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
                 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
-                "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ "
+                "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ "
                 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ "
                 "olcMonitoring ) )",
                        Cft_Database, NULL, cfAddDatabase },
@@ -1085,6 +1090,9 @@ config_generic(ConfigArgs *c) {
                case CFG_LASTMOD:
                        c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
                        break;
+               case CFG_SYNC_SUBENTRY:
+                       c->value_int = (SLAP_SYNC_SUBENTRY(c->be) != 0);
+                       break;
                case CFG_MIRRORMODE:
                        if ( SLAP_SHADOW(c->be))
                                c->value_int = (SLAP_SINGLE_SHADOW(c->be) == 0);
@@ -1197,6 +1205,7 @@ config_generic(ConfigArgs *c) {
                case CFG_SSTR_IF_MAX:
                case CFG_SSTR_IF_MIN:
                case CFG_ACL_ADD:
+               case CFG_SYNC_SUBENTRY:
                        break;
 
                /* no-ops, requires slapd restart */
@@ -1901,6 +1910,13 @@ sortval_reject:
                                SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_HIDDEN;
                        break;
 
+               case CFG_SYNC_SUBENTRY:
+                       if (c->value_int)
+                               SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SYNC_SUBENTRY;
+                       else
+                               SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SYNC_SUBENTRY;
+                       break;
+
                case CFG_SSTR_IF_MAX:
                        if (c->value_uint < index_substr_if_minlen) {
                                snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] );
index cb828999ccfea8d971949cf05858ae5358cfcf7f..95d7ba6ed1e36dae33b7b8696fa0dfac15ea5f63 100644 (file)
@@ -26,6 +26,8 @@
 #include "slap.h"
 #include "lutil_ldap.h"
 
+const struct berval slap_ldapsync_bv = BER_BVC("ldapsync");
+const struct berval slap_ldapsync_cn_bv = BER_BVC("cn=ldapsync");
 int slap_serverID;
 
 /* maxcsn->bv_val must point to a char buf[LDAP_LUTIL_CSNSTR_BUFSIZE] */
@@ -133,6 +135,46 @@ slap_graduate_commit_csn( Operation *op )
        return;
 }
 
+static struct berval ocbva[] = {
+       BER_BVC("top"),
+       BER_BVC("subentry"),
+       BER_BVC("syncProviderSubentry"),
+       BER_BVNULL
+};
+
+Entry *
+slap_create_context_csn_entry(
+       Backend *be,
+       struct berval *context_csn )
+{
+       Entry* e;
+
+       struct berval bv;
+
+       e = entry_alloc();
+
+       attr_merge( e, slap_schema.si_ad_objectClass,
+               ocbva, NULL );
+       attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
+               &ocbva[1], NULL );
+       attr_merge_one( e, slap_schema.si_ad_cn,
+               (struct berval *)&slap_ldapsync_bv, NULL );
+
+       if ( context_csn ) {
+               attr_merge_one( e, slap_schema.si_ad_contextCSN,
+                       context_csn, NULL );
+       }
+
+       BER_BVSTR( &bv, "{}" );
+       attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
+
+       build_new_dn( &e->e_name, &be->be_nsuffix[0],
+               (struct berval *)&slap_ldapsync_cn_bv, NULL );
+       ber_dupbv( &e->e_nname, &e->e_name );
+
+       return e;
+}
+
 void
 slap_queue_csn(
        Operation *op,
index 2a1c565e02d3ab277c4ee2a49e962e721554480d..49a2cbe8da6e030d5274745a4259b83b69266b51 100644 (file)
@@ -124,6 +124,7 @@ typedef struct sessionlog {
 typedef struct syncprov_info_t {
        syncops         *si_ops;
        BerVarray       si_ctxcsn;      /* ldapsync context */
+       struct berval   si_contextdn;
        int             *si_sids;
        int             si_numcsns;
        int             si_chkops;      /* checkpointing info */
@@ -1361,6 +1362,7 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
        SlapReply rsm = { 0 };
        slap_callback cb = {0};
        BackendDB be;
+
 #ifdef CHECK_CSN
        Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax;
 
@@ -1387,12 +1389,26 @@ syncprov_checkpoint( Operation *op, SlapReply *rs, slap_overinst *on )
                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_req_dn = si->si_contextdn;
+       opm.o_req_ndn = si->si_contextdn;
        opm.o_bd->bd_info = on->on_info->oi_orig;
        opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
        opm.o_no_schema_check = 1;
        opm.o_bd->be_modify( &opm, &rsm );
+
+       if ( rsm.sr_err == LDAP_NO_SUCH_OBJECT &&
+               SLAP_SYNC_SUBENTRY( opm.o_bd )) {
+               const char      *text;
+               char txtbuf[SLAP_TEXT_BUFLEN];
+               size_t textlen = sizeof txtbuf;
+               Entry *e = slap_create_context_csn_entry( opm.o_bd, NULL );
+               slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+               opm.ora_e = e;
+               opm.o_bd->be_add( &opm, &rsm );
+               if ( e == opm.ora_e )
+                       be_entry_release_w( &opm, opm.ora_e );
+       }
+
        if ( mod.sml_next != NULL ) {
                slap_mods_free( mod.sml_next, 1 );
        }
@@ -1763,7 +1779,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
                         * it will deadlock
                         */
                        if ( op->o_tag != LDAP_REQ_ADD ||
-                               !dn_match( &op->o_req_ndn, &op->o_bd->be_nsuffix[0] )) {
+                               !dn_match( &op->o_req_ndn, &si->si_contextdn )) {
                                if ( si->si_chkops && si->si_numops >= si->si_chkops ) {
                                        do_check = 1;
                                        si->si_numops = 0;
@@ -1837,14 +1853,14 @@ syncprov_op_compare( Operation *op, SlapReply *rs )
        syncprov_info_t         *si = on->on_bi.bi_private;
        int rc = SLAP_CB_CONTINUE;
 
-       if ( dn_match( &op->o_req_ndn, op->o_bd->be_nsuffix ) &&
+       if ( dn_match( &op->o_req_ndn, &si->si_contextdn ) &&
                op->oq_compare.rs_ava->aa_desc == slap_schema.si_ad_contextCSN )
        {
                Entry e = {0};
                Attribute a = {0};
 
-               e.e_name = op->o_bd->be_suffix[0];
-               e.e_nname = op->o_bd->be_nsuffix[0];
+               e.e_name = si->si_contextdn;
+               e.e_nname = si->si_contextdn;
                e.e_attrs = &a;
 
                a.a_desc = slap_schema.si_ad_contextCSN;
@@ -2583,7 +2599,7 @@ syncprov_operational(
                return SLAP_CB_CONTINUE;
 
        if ( rs->sr_entry &&
-               dn_match( &rs->sr_entry->e_nname, op->o_bd->be_nsuffix )) {
+               dn_match( &rs->sr_entry->e_nname, &si->si_contextdn )) {
 
                if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
                        ad_inlist( slap_schema.si_ad_contextCSN, rs->sr_attrs )) {
@@ -2876,7 +2892,13 @@ syncprov_db_open(
        op->o_dn = be->be_rootdn;
        op->o_ndn = be->be_rootndn;
 
-       rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL,
+       if ( SLAP_SYNC_SUBENTRY( be )) {
+               build_new_dn( &si->si_contextdn, be->be_nsuffix,
+                       (struct berval *)&slap_ldapsync_cn_bv, NULL );
+       } else {
+               si->si_contextdn = be->be_nsuffix[0];
+       }
+       rc = overlay_entry_get_ov( op, &si->si_contextdn, NULL,
                slap_schema.si_ad_contextCSN, 0, &e, on );
 
        if ( e ) {
index d8a38ba801e9a421febe7df13b3894dbcf7d2ca5..0866c9f2b247f1350bb124a4a756d2e1a9933b1b 100644 (file)
@@ -814,10 +814,13 @@ LDAP_SLAPD_F (ContentRule *) cr_bvfind LDAP_P((
  */
 
 LDAP_SLAPD_V( int ) slap_serverID;
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_bv;
+LDAP_SLAPD_V( const struct berval ) slap_ldapsync_cn_bv;
 LDAP_SLAPD_F (void) slap_get_commit_csn LDAP_P((
        Operation *, struct berval *maxcsn, int *foundit ));
 LDAP_SLAPD_F (void) slap_rewind_commit_csn LDAP_P(( Operation * ));
 LDAP_SLAPD_F (void) slap_graduate_commit_csn LDAP_P(( Operation * ));
+LDAP_SLAPD_F (Entry *) slap_create_context_csn_entry LDAP_P(( Backend *, struct berval *));
 LDAP_SLAPD_F (int) slap_get_csn LDAP_P(( Operation *, struct berval *, int ));
 LDAP_SLAPD_F (void) slap_queue_csn LDAP_P(( Operation *, struct berval * ));
 
index e12a82946fad2fbc7ae0c9caa64b128f95ea5692..7e17377876d5eb3762a5032ca132f28d852732f7 100644 (file)
@@ -266,7 +266,8 @@ slap_auxprop_lookup(
        const char *user,
        unsigned ulen)
 {
-       Operation op = {0};
+       OperationBuffer opbuf = {0};
+       Operation *op = (Operation *)&opbuf;
        int i, doit = 0;
        Connection *conn = NULL;
        lookup_info sl;
@@ -286,22 +287,22 @@ slap_auxprop_lookup(
                        if ( flags & SASL_AUXPROP_AUTHZID ) {
                                if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZLEN] )) {
                                        if ( sl.list[i].values && sl.list[i].values[0] )
-                                               AC_MEMCPY( &op.o_req_ndn.bv_len, sl.list[i].values[0],
-                                                       sizeof( op.o_req_ndn.bv_len ) );
+                                               AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
+                                                       sizeof( op->o_req_ndn.bv_len ) );
                                } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHZ] )) {
                                        if ( sl.list[i].values )
-                                               op.o_req_ndn.bv_val = (char *)sl.list[i].values[0];
+                                               op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
                                        break;
                                }
                        }
 
                        if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) {
                                if ( sl.list[i].values && sl.list[i].values[0] )
-                                       AC_MEMCPY( &op.o_req_ndn.bv_len, sl.list[i].values[0],
-                                               sizeof( op.o_req_ndn.bv_len ) );
+                                       AC_MEMCPY( &op->o_req_ndn.bv_len, sl.list[i].values[0],
+                                               sizeof( op->o_req_ndn.bv_len ) );
                        } else if ( !strcmp( sl.list[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) {
                                if ( sl.list[i].values ) {
-                                       op.o_req_ndn.bv_val = (char *)sl.list[i].values[0];
+                                       op->o_req_ndn.bv_val = (char *)sl.list[i].values[0];
                                        if ( !(flags & SASL_AUXPROP_AUTHZID) )
                                                break;
                                }
@@ -336,30 +337,30 @@ slap_auxprop_lookup(
 
                cb.sc_private = &sl;
 
-               op.o_bd = select_backend( &op.o_req_ndn, 1 );
+               op->o_bd = select_backend( &op->o_req_ndn, 1 );
 
-               if ( op.o_bd ) {
+               if ( op->o_bd ) {
                        /* For rootdn, see if we can use the rootpw */
-                       if ( be_isroot_dn( op.o_bd, &op.o_req_ndn ) &&
-                               !BER_BVISEMPTY( &op.o_bd->be_rootpw )) {
+                       if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) &&
+                               !BER_BVISEMPTY( &op->o_bd->be_rootpw )) {
                                struct berval cbv = BER_BVNULL;
 
                                /* If there's a recognized scheme, see if it's CLEARTEXT */
-                               if ( lutil_passwd_scheme( op.o_bd->be_rootpw.bv_val )) {
-                                       if ( !strncasecmp( op.o_bd->be_rootpw.bv_val,
+                               if ( lutil_passwd_scheme( op->o_bd->be_rootpw.bv_val )) {
+                                       if ( !strncasecmp( op->o_bd->be_rootpw.bv_val,
                                                sc_cleartext.bv_val, sc_cleartext.bv_len )) {
 
                                                /* If it's CLEARTEXT, skip past scheme spec */
-                                               cbv.bv_len = op.o_bd->be_rootpw.bv_len -
+                                               cbv.bv_len = op->o_bd->be_rootpw.bv_len -
                                                        sc_cleartext.bv_len;
                                                if ( cbv.bv_len ) {
-                                                       cbv.bv_val = op.o_bd->be_rootpw.bv_val +
+                                                       cbv.bv_val = op->o_bd->be_rootpw.bv_val +
                                                                sc_cleartext.bv_len;
                                                }
                                        }
                                /* No scheme, use the whole value */
                                } else {
-                                       cbv = op.o_bd->be_rootpw;
+                                       cbv = op->o_bd->be_rootpw;
                                }
                                if ( !BER_BVISEMPTY( &cbv )) {
                                        for( i = 0; sl.list[i].name; i++ ) {
@@ -380,27 +381,28 @@ slap_auxprop_lookup(
                                }
                        }
 
-                       if ( op.o_bd->be_search ) {
+                       if ( op->o_bd->be_search ) {
                                SlapReply rs = {REP_RESULT};
-                               op.o_hdr = conn->c_sasl_bindop->o_hdr;
-                               op.o_tag = LDAP_REQ_SEARCH;
-                               op.o_dn = conn->c_ndn;
-                               op.o_ndn = conn->c_ndn;
-                               op.o_callback = &cb;
-                               slap_op_time( &op.o_time, &op.o_tincr );
-                               op.o_do_not_cache = 1;
-                               op.o_is_auth_check = 1;
-                               op.o_req_dn = op.o_req_ndn;
-                               op.ors_scope = LDAP_SCOPE_BASE;
-                               op.ors_deref = LDAP_DEREF_NEVER;
-                               op.ors_tlimit = SLAP_NO_LIMIT;
-                               op.ors_slimit = 1;
-                               op.ors_filter = &generic_filter;
-                               op.ors_filterstr = generic_filterstr;
+                               op->o_hdr = conn->c_sasl_bindop->o_hdr;
+                               op->o_controls = opbuf.ob_controls;
+                               op->o_tag = LDAP_REQ_SEARCH;
+                               op->o_dn = conn->c_ndn;
+                               op->o_ndn = conn->c_ndn;
+                               op->o_callback = &cb;
+                               slap_op_time( &op->o_time, &op->o_tincr );
+                               op->o_do_not_cache = 1;
+                               op->o_is_auth_check = 1;
+                               op->o_req_dn = op->o_req_ndn;
+                               op->ors_scope = LDAP_SCOPE_BASE;
+                               op->ors_deref = LDAP_DEREF_NEVER;
+                               op->ors_tlimit = SLAP_NO_LIMIT;
+                               op->ors_slimit = 1;
+                               op->ors_filter = &generic_filter;
+                               op->ors_filterstr = generic_filterstr;
                                /* FIXME: we want all attributes, right? */
-                               op.ors_attrs = NULL;
+                               op->ors_attrs = NULL;
 
-                               op.o_bd->be_search( &op, &rs );
+                               op->o_bd->be_search( op, &rs );
                        }
                }
        }
index 18e11a6e588270b8cb9c4f41669ba8fb7ccdd74a..ef9c40f7b91665c74a16bdba18bab8790695912b 100644 (file)
@@ -1804,6 +1804,7 @@ struct BackendDB {
 #define SLAP_DBFLAG_SHADOW_MASK                (SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SINGLE_SHADOW|SLAP_DBFLAG_SYNC_SHADOW|SLAP_DBFLAG_SLURP_SHADOW)
 #define SLAP_DBFLAG_CLEAN              0x10000U /* was cleanly shutdown */
 #define SLAP_DBFLAG_ACL_ADD            0x20000U /* check attr ACLs on adds */
+#define SLAP_DBFLAG_SYNC_SUBENTRY      0x40000U /* use subentry for context */
        slap_mask_t     be_flags;
 #define SLAP_DBFLAGS(be)                       ((be)->be_flags)
 #define SLAP_NOLASTMOD(be)                     (SLAP_DBFLAGS(be) & SLAP_DBFLAG_NOLASTMOD)
@@ -1830,6 +1831,7 @@ struct BackendDB {
 #define SLAP_MULTIMASTER(be)                   (!SLAP_SINGLE_SHADOW(be))
 #define SLAP_DBCLEAN(be)                       (SLAP_DBFLAGS(be) & SLAP_DBFLAG_CLEAN)
 #define SLAP_DBACL_ADD(be)                     (SLAP_DBFLAGS(be) & SLAP_DBFLAG_ACL_ADD)
+#define SLAP_SYNC_SUBENTRY(be)                 (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SYNC_SUBENTRY)
 
        slap_mask_t     be_restrictops;         /* restriction operations */
 #define SLAP_RESTRICT_OP_ADD           0x0001U
index 4159d8ff42ef2258a9382913ec48a2d0e2db95dc..a57511eb7384423c2006f0f88b40ab83f8d84bf1 100644 (file)
@@ -438,10 +438,32 @@ slapadd( int argc, char **argv )
        }
 
        if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) {
-               ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix );
+               struct berval ctxdn;
+               if ( SLAP_SYNC_SUBENTRY( be )) {
+                       build_new_dn( &ctxdn, &be->be_nsuffix[0],
+                               (struct berval *)&slap_ldapsync_cn_bv, NULL );
+               } else {
+                       ctxdn = be->be_nsuffix[0];
+               }
+               ctxcsn_id = be->be_dn2id_get( be, &ctxdn );
                if ( ctxcsn_id == NOID ) {
-                       fprintf( stderr, "%s: context entry is missing\n", progname );
-                       rc = EXIT_FAILURE;
+                       if ( SLAP_SYNC_SUBENTRY( be )) {
+                               ctxcsn_e = slap_create_context_csn_entry( be, NULL );
+                               for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) {
+                                       if ( maxcsn[ sid ].bv_len ) {
+                                               attr_merge_one( ctxcsn_e, slap_schema.si_ad_contextCSN,
+                                                       &maxcsn[ sid ], NULL );
+                                       }
+                               }
+                               ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+                               if ( ctxcsn_id == NOID ) {
+                                       fprintf( stderr, "%s: couldn't create context entry\n", progname );
+                                       rc = EXIT_FAILURE;
+                               }
+                       } else {
+                               fprintf( stderr, "%s: context entry is missing\n", progname );
+                               rc = EXIT_FAILURE;
+                       }
                } else {
                        ctxcsn_e = be->be_entry_get( be, ctxcsn_id );
                        if ( ctxcsn_e != NULL ) {
index 22496b66b3825f246c2f5f7a5f75bb097aafa2ae..e0982518243d04b101ec0efea0e863ddd22ffb8c 100644 (file)
@@ -70,6 +70,7 @@ typedef struct syncinfo_s {
        struct berval           si_logbase;
        struct berval           si_filterstr;
        struct berval           si_logfilterstr;
+       struct berval           si_contextdn;
        int                     si_scope;
        int                     si_attrsonly;
        char                    *si_anfile;
@@ -119,7 +120,7 @@ static int syncrepl_entry(
                                        Modifications**,int, struct berval*,
                                        struct berval *cookieCSN );
 static int syncrepl_updateCookie(
-                                       syncinfo_t *, Operation *, struct berval *,
+                                       syncinfo_t *, Operation *,
                                        struct sync_cookie * );
 static struct berval * slap_uuidstr_from_normalized(
                                        struct berval *, struct berval *, void * );
@@ -458,8 +459,8 @@ check_syncprov(
         */
        a.a_desc = slap_schema.si_ad_contextCSN;
        e.e_attrs = &a;
-       e.e_name = op->o_bd->be_suffix[0];
-       e.e_nname = op->o_bd->be_nsuffix[0];
+       e.e_name = si->si_contextdn;
+       e.e_nname = si->si_contextdn;
        at[0].an_name = a.a_desc->ad_cname;
        at[0].an_desc = a.a_desc;
        BER_BVZERO( &at[1].an_name );
@@ -627,7 +628,7 @@ do_syncrep1(
                                BerVarray csn = NULL;
                                void *ctx = op->o_tmpmemctx;
 
-                               op->o_req_ndn = op->o_bd->be_nsuffix[0];
+                               op->o_req_ndn = si->si_contextdn;
                                op->o_req_dn = op->o_req_ndn;
 
                                /* try to read stored contextCSN */
@@ -753,7 +754,6 @@ do_syncrep2(
                        err = LDAP_SUCCESS;
        ber_len_t       len;
 
-       struct berval   *psub;
        Modifications   *modlist = NULL;
 
        int                             match, m;
@@ -775,8 +775,6 @@ do_syncrep2(
 
        Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2 %s\n", si->si_ridtxt, 0, 0 );
 
-       psub = &si->si_be->be_nsuffix[0];
-
        slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
 
        if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
@@ -873,7 +871,7 @@ do_syncrep2(
                                if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS &&
                                        syncCookie.ctxcsn )
                                {
-                                       rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+                                       rc = syncrepl_updateCookie( si, op, &syncCookie );
                                } else switch ( rc ) {
                                        case LDAP_ALREADY_EXISTS:
                                        case LDAP_NO_SUCH_OBJECT:
@@ -893,7 +891,7 @@ do_syncrep2(
                                        syncstate, &syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS &&
                                        syncCookie.ctxcsn )
                                {
-                                       rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+                                       rc = syncrepl_updateCookie( si, op, &syncCookie );
                                }
                        }
                        ldap_controls_free( rctrls );
@@ -1013,7 +1011,7 @@ do_syncrep2(
                        }
                        if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS )
                        {
-                               rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+                               rc = syncrepl_updateCookie( si, op, &syncCookie );
                        }
                        if ( err == LDAP_SUCCESS
                                && si->si_logstate == SYNCLOG_FALLBACK ) {
@@ -1174,7 +1172,7 @@ do_syncrep2(
 
                                        if ( syncCookie.ctxcsn )
                                        {
-                                               rc = syncrepl_updateCookie( si, op, psub, &syncCookie);
+                                               rc = syncrepl_updateCookie( si, op, &syncCookie);
                                        }
                                } 
 
@@ -1330,6 +1328,12 @@ do_syncrepl(
                } else {
                        si->si_wbe = be;
                }
+               if ( SLAP_SYNC_SUBENTRY( si->si_wbe )) {
+                       build_new_dn( &si->si_contextdn, &si->si_wbe->be_nsuffix[0],
+                               (struct berval *)&slap_ldapsync_cn_bv, NULL );
+               } else {
+                       si->si_contextdn = si->si_wbe->be_nsuffix[0];
+               }
        }
        if ( !si->si_schemachecking )
                op->o_no_schema_check = 1;
@@ -2957,7 +2961,6 @@ static int
 syncrepl_updateCookie(
        syncinfo_t *si,
        Operation *op,
-       struct berval *pdn,
        struct sync_cookie *syncCookie )
 {
        Backend *be = op->o_bd;
@@ -3048,8 +3051,8 @@ syncrepl_updateCookie(
        cb.sc_private = si;
 
        op->o_callback = &cb;
-       op->o_req_dn = op->o_bd->be_suffix[0];
-       op->o_req_ndn = op->o_bd->be_nsuffix[0];
+       op->o_req_dn = si->si_contextdn;
+       op->o_req_ndn = si->si_contextdn;
 
        /* update contextCSN */
        op->o_dont_replicate = 1;
@@ -3057,6 +3060,20 @@ syncrepl_updateCookie(
        op->orm_modlist = &mod;
        op->orm_no_opattrs = 1;
        rc = op->o_bd->be_modify( op, &rs_modify );
+
+       if ( rs_modify.sr_err == LDAP_NO_SUCH_OBJECT &&
+               SLAP_SYNC_SUBENTRY( op->o_bd )) {
+               const char      *text;
+               char txtbuf[SLAP_TEXT_BUFLEN];
+               size_t textlen = sizeof txtbuf;
+               Entry *e = slap_create_context_csn_entry( op->o_bd, NULL );
+               rc = slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+               op->ora_e = e;
+               rc = op->o_bd->be_add( op, &rs_modify );
+               if ( e == op->ora_e )
+                       be_entry_release_w( op, op->ora_e );
+       }
+
        op->orm_no_opattrs = 0;
        op->o_dont_replicate = 0;
 
@@ -3695,6 +3712,9 @@ syncinfo_free( syncinfo_t *sie, int free_all )
                if ( sie->si_logbase.bv_val ) {
                        ch_free( sie->si_logbase.bv_val );
                }
+               if ( SLAP_SYNC_SUBENTRY( sie->si_be )) {
+                       ch_free( sie->si_contextdn.bv_val );
+               }
                if ( sie->si_attrs ) {
                        int i = 0;
                        while ( sie->si_attrs[i] != NULL ) {