]> git.sur5r.net Git - openldap/commitdiff
slaptools update : replica promotion / demotion
authorJong Hyuk Choi <jongchoi@openldap.org>
Tue, 7 Oct 2003 20:01:37 +0000 (20:01 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Tue, 7 Oct 2003 20:01:37 +0000 (20:01 +0000)
new slapadd options
-p       : promote : If the ldif file contains syncConsumerSubentries, convert
                     them to a single syncProviderSubentry. Its contextCSN
                     attribute has the largest value of the syncreplCookie
                     attributes of the syncConsumerSubentries.
                     syncProviderSubentry in the ldif file is retained.
-p -w    : promote : Recalculate contextCSN based on entryCSN of each entry.
           create    Existing syncConsumerSubentries and syncProviderSubentry
                     are ignored and not added to the directory.
-r       : demote  : If the ldif file contains syncProviderSubentry, convert it
                     to a syncConsumerSubentry having the default syncrepl id
                     of 0. syncConsumerSubentries in the ldif file are retained.
-r -w    : demote  : Recalculate syncreplCookie based on entryCSN of each entry.
           create    Existing syncConsumerSubentries and syncProviderSubentry
                     are ignored and not added to the directory. The default
                     syncrepl id of 0 will be used for the new
                     syncConsumerSubentry.
-r -w -i %d[,%d]*  : Using the comma separated list followed by the -i option,
                     it is possible to create multiple syncConsumerSubentries
                     having the syncrepl ids specified in the list.
                     syncreplCookie values of these sycnConsumerSubentries
                     will have the same value, either from the maximum
                     entryCSN value or from the contextCSN value of the
                     syncProviderSubentry.

servers/slapd/config.c
servers/slapd/proto-slap.h
servers/slapd/syncrepl.c
servers/slapd/tools/Makefile.in
servers/slapd/tools/mimic.c
servers/slapd/tools/slapadd.c
servers/slapd/tools/slapcommon.c
servers/slapd/tools/slapcommon.h

index 2b442a015a93fe9903494c69fc585f8d81a78ae6..b233598a661966444e23e290a6762d3d400220cd 100644 (file)
@@ -3084,3 +3084,47 @@ parse_syncrepl_line(
 
        return 0;
 }
+
+char **
+str2clist( char ***out, char *in, const char *brkstr )
+{
+       char    *str;
+       char    *s;
+       char    *lasts;
+       int     i, j;
+       const char *text;
+       char    **new;
+
+       /* find last element in list */
+       for (i = 0; *out && *out[i]; i++);
+
+       /* protect the input string from strtok */
+       str = ch_strdup( in );
+
+       if ( *str == '\0' ) {
+               free( str );
+               return( *out );
+       }
+
+       /* Count words in string */
+       j=1;
+       for ( s = str; *s; s++ ) {
+               if ( strchr( brkstr, *s ) != NULL ) {
+                       j++;
+               }
+       }
+
+       *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
+       new = *out + i;
+       for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
+               s != NULL;
+               s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
+       {
+               *new = ch_strdup( s );
+               new++;
+       }
+
+       *new = NULL;
+       free( str );
+       return( *out );
+}
index ed3762dd6f2038cda17fb7d347f8b8e411badf28..42494eba505af439d81648ee837a26cbba57e340 100644 (file)
@@ -303,6 +303,7 @@ LDAP_SLAPD_F (int) get_supported_controls LDAP_P (( char ***ctrloidsp, slap_mask
  */
 LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, int depth ));
 LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
+LDAP_SLAPD_F (char **) str2clist LDAP_P(( char ***, char *, const char * ));
 
 /*
  * connection.c
@@ -358,6 +359,8 @@ LDAP_SLAPD_F (ContentRule *) cr_bvfind LDAP_P((
  * ctxcsn.c
  */
 
+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 * ));
 LDAP_SLAPD_F (void) slap_rewind_commit_csn LDAP_P(( Operation * ));
 LDAP_SLAPD_F (void) slap_graduate_commit_csn LDAP_P(( Operation * ));
@@ -535,8 +538,6 @@ LDAP_SLAPD_V( const struct berval ) slap_empty_bv;
 LDAP_SLAPD_V( const struct berval ) slap_unknown_bv;
 LDAP_SLAPD_V( const struct berval ) slap_true_bv;
 LDAP_SLAPD_V( const struct berval ) slap_false_bv;
-LDAP_SLAPD_V( const struct berval ) slap_ldapsync_bv;
-LDAP_SLAPD_V( const struct berval ) slap_ldapsync_cn_bv;
 
 /*
  * index.c
@@ -1170,28 +1171,34 @@ LDAP_SLAPD_F (int) do_unbind LDAP_P((Operation *op, SlapReply *rs));
 LDAP_SLAPD_F (int) do_extended LDAP_P((Operation *op, SlapReply *rs));
 
 /*
- * syncrepl
+ * syncrepl.c
  */
 
+LDAP_SLAPD_V( const struct berval ) slap_syncrepl_bvc;
+LDAP_SLAPD_V( const struct berval ) slap_syncrepl_cn_bvc;
+
 LDAP_SLAPD_V (struct runqueue_s) syncrepl_rq;
 
 LDAP_SLAPD_F (void) init_syncrepl LDAP_P(());
 LDAP_SLAPD_F (void*) do_syncrepl LDAP_P((void *, void *));
 LDAP_SLAPD_F (int) ldap_sync_search LDAP_P((
-                                                       syncinfo_t *, LDAP *, LDAPControl **, LDAPControl **, int *));
+                                       syncinfo_t *, LDAP *, LDAPControl **,
+                                       LDAPControl **, int *));
 LDAP_SLAPD_F (Entry*) syncrepl_message_to_entry LDAP_P((
-                                                       syncinfo_t *, LDAP *, Operation *, LDAPMessage *,
-                                                       Modifications **, int*, struct berval *, struct berval * ));
+                                       syncinfo_t *, LDAP *, Operation *, LDAPMessage *,
+                                       Modifications **, int*, struct berval *, struct berval * ));
 LDAP_SLAPD_F (int) syncrepl_entry LDAP_P((
-                                                       syncinfo_t *, LDAP *, Operation*, Entry*,
-                                                       Modifications*,int, struct berval*, struct berval*, int ));
+                                       syncinfo_t *, LDAP *, Operation*, Entry*,
+                                       Modifications*,int, struct berval*, struct berval*, int ));
 LDAP_SLAPD_F (void) syncrepl_updateCookie LDAP_P((
-                                                       syncinfo_t *, LDAP *, Operation *, struct berval *,
-                                                       struct berval * ));
-LDAP_SLAPD_F (char **) str2clist LDAP_P(( char ***, char *, const char * ));
-
-LDAP_SLAPD_F (void)  syncrepl_add_glue LDAP_P(( syncinfo_t *, LDAP *, Operation*, Entry*,
-                                                       Modifications*, int, struct berval*, struct berval* ));
+                                       syncinfo_t *, LDAP *, Operation *, struct berval *,
+                                       struct berval * ));
+LDAP_SLAPD_F (void)  syncrepl_add_glue LDAP_P(( syncinfo_t *, LDAP *,
+                                       Operation*, Entry*, Modifications*, int,
+                                       struct berval*, struct berval* ));
+LDAP_SLAPD_F (Entry*) slap_create_syncrepl_entry LDAP_P((
+                                       Backend *, struct berval *,
+                                       struct berval *, struct berval * ));
 
 LDAP_END_DECL
 
index 360d5740872982be16a8a24741827907792eb148..58ed2f8e6be617f879c048555417a17201d64eb6 100644 (file)
@@ -35,6 +35,9 @@
 
 #include "ldap_rq.h"
 
+const struct berval slap_syncrepl_bvc = BER_BVC("syncreplxxx");
+const struct berval slap_syncrepl_cn_bvc = BER_BVC("cn=syncreplxxx");
+
 static void
 syncrepl_del_nonpresent( LDAP *, Operation * );
 
@@ -1618,47 +1621,45 @@ null_callback(
        return LDAP_SUCCESS;
 }
 
-
-char **
-str2clist( char ***out, char *in, const char *brkstr )
+static struct berval ocbva[] = {
+    BER_BVC("top"),
+    BER_BVC("subentry"),
+    BER_BVC("syncProviderSubentry"),
+    {0,NULL}
+};
+
+Entry *
+slap_create_syncrepl_entry(
+       Backend *be,
+       struct berval *context_csn,
+       struct berval *rdn,
+       struct berval *cn
+)
 {
-       char    *str;
-       char    *s;
-       char    *lasts;
-       int     i, j;
-       const char *text;
-       char    **new;
-
-       /* find last element in list */
-       for (i = 0; *out && *out[i]; i++);
-
-       /* protect the input string from strtok */
-       str = ch_strdup( in );
-
-       if ( *str == '\0' ) {
-               free( str );
-               return( *out );
-       }
+       Entry* e;
+       int rc;
 
-       /* Count words in string */
-       j=1;
-       for ( s = str; *s; s++ ) {
-               if ( strchr( brkstr, *s ) != NULL ) {
-                       j++;
-               }
-       }
+       struct berval bv;
 
-       *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
-       new = *out + i;
-       for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
-               s != NULL;
-               s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
-       {
-               *new = ch_strdup( s );
-               new++;
+       e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
+
+       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, cn, NULL );
+
+       if ( context_csn ) {
+               attr_merge_one( e, slap_schema.si_ad_syncreplCookie,
+                       context_csn, NULL );
        }
 
-       *new = NULL;
-       free( str );
-       return( *out );
+       bv.bv_val = "{}";
+       bv.bv_len = sizeof("{}")-1;
+       attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
+
+       build_new_dn( &e->e_name, &be->be_nsuffix[0], rdn, NULL );
+       ber_dupbv( &e->e_nname, &e->e_name );
+
+       return e;
 }
index 081e9aea5695c770df6207f90377732e5abd9b69..8934eac54cbfa05fd8e738e1fd8079e47f4a74f4 100644 (file)
@@ -46,7 +46,7 @@ SLAPD_OBJS = ../globals.o ../config.o ../ch_malloc.o ../cr.o ../backend.o \
                ../init.o ../controls.o ../kerberos.o ../passwd.o \
                ../index.o ../extended.o ../starttls.o ../sets.o ../mra.o \
                ../referral.o ../backglue.o ../oidm.o ../mods.o ../operation.o \
-               ../cancel.o ../sl_malloc.o ../backover.o ../ctxcsn.o
+               ../cancel.o ../sl_malloc.o ../backover.o ../ctxcsn.o ../syncrepl.o
 
 SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o
 
index 9f972115e2d5ef030abf500e3d29efede37b247a..c9bade3f96d71622f7a6ecf33e2e692d646e51d2 100644 (file)
@@ -236,31 +236,29 @@ int root_dse_info( Connection *conn, Entry **entry, const char **text )
        return -1;
 }
 
-struct runqueue_s syncrepl_rq;
-
-void init_syncrepl( )
+int slap_entry2mods( Entry *e, Modifications **mods, const char **text )
 {
-       return;
+       return -1;
 }
 
-void* do_syncrepl( void *ctx, void *arg )
-{
-       return NULL;
-}
+volatile sig_atomic_t slapd_abrupt_shutdown;
 
-char** str2clist( char ***out, char *in, const char *brkstr )
+int slap_mods_check( Modifications *ml, int update, const char **text,
+                                       char *textbuf, size_t textlen, void *ctx )
 {
-       return NULL;
+       return -1;
 }
 
-void syncrepl_add_glue( syncinfo_t *si, LDAP *ld, Operation *op, Entry *e,
-                               Modifications *modlist, int syncstate, struct berval* syncUUID,
-                               struct berval* syncCookie )
+int slap_mods2entry( Modifications *mods, Entry **e, int repl_user,
+                                   int dup, const char **text, char *textbuf, size_t textlen )
 {
-       return;
+       return -1;
 }
 
-int slap_entry2mods( Entry *e, Modifications **mods, const char **text )
+int slap_mods_opattrs( Operation *op, Modifications *mods,
+                                          Modifications **modtail, const char **text,
+                                          char *textbuf, size_t textlen )
 {
        return -1;
 }
+
index da006c28eaf0422064bc0e1c29c377635f7845ac..1958a4249304ab2dcbe5c6751a14dd5d4177c916 100644 (file)
 #include "slapcommon.h"
 
 static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
+static const struct berval slap_syncrepl_bvc = BER_BVC("syncreplxxx");
+static const struct berval slap_syncrepl_cn_bvc = BER_BVC("cn=syncreplxxx");
+static struct berval slap_syncrepl_bv = BER_BVNULL;
+static struct berval slap_syncrepl_cn_bv = BER_BVNULL;
+
+struct subentryinfo {
+       struct berval cn;
+       struct berval ndn;
+       struct berval rdn;
+       struct berval cookie;
+       LDAP_SLIST_ENTRY( subentryinfo ) sei_next;
+};
 
 int
 main( int argc, char **argv )
@@ -35,11 +47,26 @@ main( int argc, char **argv )
        size_t textlen = sizeof textbuf;
 
        struct berval csn;
+       struct berval maxcsn = { 0, NULL };
+       struct berval ldifcsn = { 0, NULL };
+       int match;
+       int     provider_subentry = 0;
+       struct subentryinfo *sei;
+       LDAP_SLIST_HEAD( consumer_subentry_slist, subentryinfo ) consumer_subentry;
+       Attribute *attr;
+       Entry *ctxcsn_e;
+       ID      ctxcsn_id;
+       struct berval   ctxcsn_ndn = { 0, NULL };
+       int ret;
+       struct berval bvtext;
+       int i;
 #ifdef NEW_LOGGING
        lutil_log_initialize(argc, argv );
 #endif
        slap_tool_init( "slapadd", SLAPADD, argc, argv );
 
+       LDAP_SLIST_INIT( &consumer_subentry );
+
        if( !be->be_entry_open ||
                !be->be_entry_close ||
                !be->be_entry_put )
@@ -60,7 +87,6 @@ main( int argc, char **argv )
 
        while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) {
                Entry *e = str2entry( buf );
-               struct berval bvtext;
 
                /*
                 * Initialize text buffer
@@ -239,76 +265,396 @@ main( int argc, char **argv )
                                vals[0] = csn;
                                attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
                        }
-               }
 
-               if (!dryrun) {
-                       ID id = be->be_entry_put( be, e, &bvtext );
-                       if( id == NOID ) {
-                               fprintf( stderr, "%s: could not add entry dn=\"%s\" (line=%d): %s\n",
-                                       progname, e->e_dn, lineno, bvtext.bv_val );
-                               rc = EXIT_FAILURE;
-                               entry_free( e );
-                               if( continuemode ) continue;
-                               break;
+                       if ( !is_entry_syncProviderSubentry( e ) &&
+                                !is_entry_syncConsumerSubentry( e ) &&
+                                update_ctxcsn != SLAP_TOOL_CTXCSN_KEEP ) {
+                               attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
+                               if ( maxcsn.bv_len != 0 ) {
+                                       value_match( &match, slap_schema.si_ad_entryCSN,
+                                               slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
+                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                               &maxcsn, &attr->a_nvals[0], &text );
+                               } else {
+                                       match = -1;
+                               }
+                               if ( match < 0 ) {
+                                       if ( maxcsn.bv_val )
+                                               ch_free( maxcsn.bv_val );
+                                       ber_dupbv( &maxcsn, &attr->a_nvals[0] );
+                               }
                        }
+               }
+
+               if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP ) {
+                       if ( is_entry_syncProviderSubentry( e )) { 
+                               if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+                                       fprintf( stderr, "%s: consumer and provider subentries "
+                                                                        "are both present\n", progname );
+                                       rc = EXIT_FAILURE;
+                                       entry_free( e );
+                                       sei = LDAP_SLIST_FIRST( &consumer_subentry );
+                                       while ( sei ) {
+                                               ch_free( sei->cn.bv_val );
+                                               ch_free( sei->ndn.bv_val );
+                                               ch_free( sei->rdn.bv_val );
+                                               ch_free( sei->cookie.bv_val );
+                                               LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+                                               ch_free( sei );
+                                               sei = LDAP_SLIST_FIRST( &consumer_subentry );
+                                       }
+                                       break;
+                               }
+                               if ( provider_subentry ) {
+                                       fprintf( stderr, "%s: multiple provider subentries are "
+                                                       "present : add -w flag to refresh\n", progname );
+                                       rc = EXIT_FAILURE;
+                                       entry_free( e );
+                                       break;
+                               }
+                               attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
+                               if ( attr == NULL ) {
+                                       entry_free( e );
+                                       continue;
+                               }
+                               provider_subentry = 1;
+                               ber_dupbv( &maxcsn, &attr->a_nvals[0] );
+                       } else if ( is_entry_syncConsumerSubentry( e )) {
+                               if ( provider_subentry ) {
+                                       fprintf( stderr, "%s: consumer and provider subentries "
+                                                                        "are both present\n", progname );
+                                       rc = EXIT_FAILURE;
+                                       entry_free( e );
+                                       break;
+                               }
 
-                       if ( verbose ) {
-                               fprintf( stderr, "added: \"%s\" (%08lx)\n",
-                                       e->e_dn, (long) id );
+                               attr = attr_find( e->e_attrs, slap_schema.si_ad_cn );
+
+                               if ( attr == NULL ) {
+                                       entry_free( e );
+                                       continue;
+                               }
+
+                               if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+                                       LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+                                               value_match( &match, slap_schema.si_ad_cn,
+                                                       slap_schema.si_ad_cn->ad_type->sat_equality,
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       &sei->cn, &attr->a_nvals[0], &text );
+                                       }
+                                       if ( !match ) {
+                                               fprintf( stderr, "%s: multiple consumer subentries "
+                                                               "have the same id : add -w flag to refresh\n",
+                                                               progname );
+                                               rc = EXIT_FAILURE;
+                                               entry_free( e );
+                                               sei = LDAP_SLIST_FIRST( &consumer_subentry );
+                                               while ( sei ) {
+                                                       ch_free( sei->cn.bv_val );
+                                                       ch_free( sei->ndn.bv_val );
+                                                       ch_free( sei->rdn.bv_val );
+                                                       ch_free( sei->cookie.bv_val );
+                                                       LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+                                                       ch_free( sei );
+                                                       sei = LDAP_SLIST_FIRST( &consumer_subentry );
+                                               }
+                                               break;
+                                       }
+                               }
+                               sei = ch_calloc( 1, sizeof( struct subentryinfo ));
+                               ber_dupbv( &sei->cn, &attr->a_nvals[0] );
+                               ber_dupbv( &sei->ndn, &e->e_nname );
+                               dnExtractRdn( &sei->ndn, &sei->rdn, NULL );
+                               attr = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
+                               if ( attr == NULL ) {
+                                       ch_free( sei->cn.bv_val );
+                                       ch_free( sei->ndn.bv_val );
+                                       ch_free( sei->rdn.bv_val );
+                                       ch_free( sei->cookie.bv_val );
+                                       ch_free( sei );
+                                       entry_free( e );
+                                       continue;
+                               }
+                               ber_dupbv( &sei->cookie, &attr->a_nvals[0] );
+                               LDAP_SLIST_INSERT_HEAD( &consumer_subentry, sei, sei_next );
                        }
-               } else {
-                       if ( verbose ) {
-                               fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
+               }
+
+               if ( !is_entry_syncProviderSubentry( e ) &&
+                        !is_entry_syncConsumerSubentry( e )) {
+                       if (!dryrun) {
+                               ID id = be->be_entry_put( be, e, &bvtext );
+                               if( id == NOID ) {
+                                       fprintf( stderr, "%s: could not add entry dn=\"%s\" "
+                                                                        "(line=%d): %s\n", progname, e->e_dn,
+                                                                        lineno, bvtext.bv_val );
+                                       rc = EXIT_FAILURE;
+                                       entry_free( e );
+                                       if( continuemode ) continue;
+                                       break;
+                               }
+       
+                               if ( verbose ) {
+                                       fprintf( stderr, "added: \"%s\" (%08lx)\n",
+                                               e->e_dn, (long) id );
+                               }
+                       } else {
+                               if ( verbose ) {
+                                       fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
+                               }
                        }
                }
 
                entry_free( e );
        }
 
-       if ( SLAP_LASTMOD(be) && update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH && csn.bv_len > 0 ) {
-               Entry *ctxcsn_e;
-               ID      ctxcsn_id;
-               struct berval   ctxcsn_ndn = { 0, NULL };
-               int ret;
-               struct berval bvtext;
-               Attribute *attr;
-
-               bvtext.bv_len = textlen;
-               bvtext.bv_val = textbuf;
-               bvtext.bv_val[0] = '\0';
+       bvtext.bv_len = textlen;
+       bvtext.bv_val = textbuf;
+       bvtext.bv_val[0] = '\0';
+
+       if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+               maxcsn.bv_len = 0;
+               maxcsn.bv_val = NULL;
+               LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+                       if ( maxcsn.bv_len != 0 ) {
+                               value_match( &match, slap_schema.si_ad_syncreplCookie,
+                                       slap_schema.si_ad_syncreplCookie->ad_type->sat_ordering,
+                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                       &maxcsn, &sei->cookie, &text );
+                       } else {
+                               match = -1;
+                       }
+                       if ( match < 0 ) {
+                               if ( maxcsn.bv_val )
+                                       ch_free( maxcsn.bv_val );
+                               ber_dupbv( &maxcsn, &sei->cookie );
+                       }
+               }
+       }
 
-               build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0], (struct berval *)&slap_ldapsync_cn_bv, NULL );
-               ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
+       if ( SLAP_LASTMOD(be) && replica_promotion ) {
+               if ( provider_subentry || update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
+                        !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+                       build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
+                                                 (struct berval *)&slap_ldapsync_cn_bv, NULL );
+                       ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
                
-               if ( ctxcsn_id == NOID ) {
-                       ctxcsn_e = slap_create_context_csn_entry( be, &csn );
-                       ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
-                       if( ctxcsn_id == NOID ) {
-                               fprintf( stderr, "%s: could not add ctxcsn subentry\n", progname);
-                               rc = EXIT_FAILURE;
-                       }
-                       if ( verbose ) {
-                               fprintf( stderr, "added: \"%s\" (%08lx)\n", ctxcsn_e->e_dn, (long) ctxcsn_id );
+                       if ( ctxcsn_id == NOID ) {
+                               ctxcsn_e = slap_create_context_csn_entry( be, &maxcsn );
+                               if ( !dryrun ) {
+                                       ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+                                       if( ctxcsn_id == NOID ) {
+                                               fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+                                                                                progname);
+                                               rc = EXIT_FAILURE;
+                                       }
+                                       if ( verbose ) {
+                                               fprintf( stderr, "added: \"%s\" (%08lx)\n",
+                                                                                ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                       }
+                               } else {
+                                       if ( verbose ) {
+                                               fprintf( stderr, "(dry) added: \"%s\"\n", ctxcsn_e->e_dn );
+                                       }
+                               }
+                               entry_free( ctxcsn_e );
+                       } else {
+                               ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+                               if ( ret == LDAP_SUCCESS ) {
+                                       attr = attr_find( ctxcsn_e->e_attrs,
+                                                                               slap_schema.si_ad_contextCSN );
+                                       AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+                                       attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+                                       attr->a_vals[0].bv_len = maxcsn.bv_len;
+                                       if ( !dryrun ) {
+                                               ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
+                                               if( ctxcsn_id == NOID ) {
+                                                       fprintf( stderr, "%s: could not modify ctxcsn "
+                                                                                        "subentry\n", progname);
+                                                       rc = EXIT_FAILURE;
+                                               }
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+                                                                                        ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                               }
+                                       } else {
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "(dry) modified: \"%s\"\n",
+                                                                                        ctxcsn_e->e_dn );
+                                               }
+                                       }
+                               } else {
+                                       fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+                                                                        progname);
+                                       rc = EXIT_FAILURE;
+                               }
                        }
-                       entry_free( ctxcsn_e );
-               } else {
-                       ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
-                       if ( ret == LDAP_SUCCESS ) {
-                               attr = attr_find( ctxcsn_e->e_attrs, slap_schema.si_ad_contextCSN );
-                               attr->a_vals[0] = csn;
-                               ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
-                               if( ctxcsn_id == NOID ) {
-                                       fprintf( stderr, "%s: could not modify ctxcsn subentry\n", progname);
+               } 
+       } else if ( SLAP_LASTMOD(be) && replica_demotion &&
+                               ( update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
+                               provider_subentry )) {
+
+               ber_dupbv( &slap_syncrepl_bv, (struct berval *) &slap_syncrepl_bvc );
+               ber_dupbv( &slap_syncrepl_cn_bv,
+                                       (struct berval *) &slap_syncrepl_cn_bvc );
+
+               if ( replica_id_list == NULL ) {
+                       replica_id_list = ch_calloc( 2, sizeof( int ));
+                       replica_id_list[0] = 0;
+                       replica_id_list[1] = -1;
+               }
+
+               for ( i = 0; replica_id_list[i] > -1 ; i++ ) {
+                       slap_syncrepl_bv.bv_len = snprintf( slap_syncrepl_bv.bv_val,
+                                                                       slap_syncrepl_bvc.bv_len,
+                                                                       "syncrepl%d", replica_id_list[i] );
+                       slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
+                                                                               slap_syncrepl_cn_bvc.bv_len,
+                                                                               "cn=syncrepl%d", replica_id_list[i] );
+                       build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
+                                                 (struct berval *)&slap_syncrepl_cn_bv, NULL );
+                       ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
+
+                       if ( ctxcsn_id == NOID ) {
+                               ctxcsn_e = slap_create_syncrepl_entry( be, &maxcsn,
+                                                                                               &slap_syncrepl_cn_bv,
+                                                                                               &slap_syncrepl_bv );
+                               if ( !dryrun ) {
+                                       ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+                                       if( ctxcsn_id == NOID ) {
+                                               fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+                                                                                progname);
+                                               rc = EXIT_FAILURE;
+                                       }
+                                       if ( verbose ) {
+                                               fprintf( stderr, "added: \"%s\" (%08lx)\n",
+                                                                                ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                       }
+                               } else {
+                                       if ( verbose ) {
+                                               fprintf( stderr, "(dry) added: \"%s\"\n",
+                                                                                       ctxcsn_e->e_dn );
+                                       }
+                               }
+                               entry_free( ctxcsn_e );
+                       } else {
+                               ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+                               if ( ret == LDAP_SUCCESS ) {
+                                       attr = attr_find( ctxcsn_e->e_attrs,
+                                                                         slap_schema.si_ad_syncreplCookie );
+                                       AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+                                       attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+                                       attr->a_vals[0].bv_len = maxcsn.bv_len;
+                                       if ( !dryrun ) {
+                                               ctxcsn_id = be->be_entry_modify( be,
+                                                                                       ctxcsn_e, &bvtext );
+                                               if( ctxcsn_id == NOID ) {
+                                                       fprintf( stderr, "%s: could not modify ctxcsn "
+                                                                                        "subentry\n", progname);
+                                                       rc = EXIT_FAILURE;
+                                               }
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+                                                                                        ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                               }
+                                       } else {
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "(dry) modified: \"%s\"\n",
+                                                                                        ctxcsn_e->e_dn );
+                                               }
+                                       }
+                               } else {
+                                       fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+                                                                        progname);
                                        rc = EXIT_FAILURE;
                                }
-                               if ( verbose ) {
-                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n", ctxcsn_e->e_dn, (long) ctxcsn_id );
+                       }
+               }
+               
+               if ( slap_syncrepl_bv.bv_val ) {
+                       ch_free( slap_syncrepl_bv.bv_val );
+               }
+               if ( slap_syncrepl_cn_bv.bv_val ) {
+                       ch_free( slap_syncrepl_cn_bv.bv_val );
+               }
+       } else if ( SLAP_LASTMOD(be) && replica_demotion &&
+                               !LDAP_SLIST_EMPTY( &consumer_subentry )) {
+
+               LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
+                       ctxcsn_id = be->be_dn2id_get( be, &sei->ndn );
+
+                       if ( ctxcsn_id == NOID ) {
+                               ctxcsn_e = slap_create_syncrepl_entry( be, &sei->cookie,
+                                                                                               &sei->rdn, &sei->cn );
+                               if ( !dryrun ) {
+                                       ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
+                                       if( ctxcsn_id == NOID ) {
+                                               fprintf( stderr, "%s: could not add ctxcsn subentry\n",
+                                                                                progname);
+                                               rc = EXIT_FAILURE;
+                                       }
+                                       if ( verbose ) {
+                                               fprintf( stderr, "added: \"%s\" (%08lx)\n",
+                                                                                ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                       }
+                               } else {
+                                       if ( verbose ) {
+                                               fprintf( stderr, "(dry) added: \"%s\"\n",
+                                                                                       ctxcsn_e->e_dn );
+                                       }
                                }
+                               entry_free( ctxcsn_e );
                        } else {
-                               fprintf( stderr, "%s: could not modify ctxcsn subentry\n", progname);
-                               rc = EXIT_FAILURE;
+                               ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
+                               if ( ret == LDAP_SUCCESS ) {
+                                       attr = attr_find( ctxcsn_e->e_attrs,
+                                                                         slap_schema.si_ad_syncreplCookie );
+                                       AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
+                                       attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
+                                       attr->a_vals[0].bv_len = maxcsn.bv_len;
+                                       if ( !dryrun ) {
+                                               ctxcsn_id = be->be_entry_modify( be,
+                                                                                       ctxcsn_e, &bvtext );
+                                               if( ctxcsn_id == NOID ) {
+                                                       fprintf( stderr, "%s: could not modify ctxcsn "
+                                                                                        "subentry\n", progname);
+                                                       rc = EXIT_FAILURE;
+                                               }
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "modified: \"%s\" (%08lx)\n",
+                                                                                        ctxcsn_e->e_dn, (long) ctxcsn_id );
+                                               }
+                                       } else {
+                                               if ( verbose ) {
+                                                       fprintf( stderr, "(dry) modified: \"%s\"\n",
+                                                                                        ctxcsn_e->e_dn );
+                                               }
+                                       }
+                               } else {
+                                       fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
+                                                                        progname);
+                                       rc = EXIT_FAILURE;
+                               }
                        }
                }
+               
+               if ( slap_syncrepl_bv.bv_val ) {
+                       ch_free( slap_syncrepl_bv.bv_val );
+               }
+               if ( slap_syncrepl_cn_bv.bv_val ) {
+                       ch_free( slap_syncrepl_cn_bv.bv_val );
+               }
+       }
+
+       sei = LDAP_SLIST_FIRST( &consumer_subentry );
+       while ( sei ) {
+               ch_free( sei->cn.bv_val );
+               ch_free( sei->ndn.bv_val );
+               ch_free( sei->rdn.bv_val );
+               ch_free( sei->cookie.bv_val );
+               LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
+               ch_free( sei );
+               sei = LDAP_SLIST_FIRST( &consumer_subentry );
        }
 
        ch_free( buf );
index c0a2d47a9d3c54db41731aafca4f01855c55c62e..6719743360beafc38c906e966c51f079f126c7a3 100644 (file)
@@ -23,9 +23,14 @@ char *progname       = NULL;
 char   *conffile       = SLAPD_DEFAULT_CONFIGFILE;
 int            truncatemode = 0;
 int            verbose         = 0;
-int            update_ctxcsn = SLAP_TOOL_CTXCSN_NONE;
+int            update_ctxcsn = SLAP_TOOL_CTXCSN_KEEP;
 int            retrieve_ctxcsn = 0;
 int            retrieve_synccookie = 0;
+int            replica_promotion = 0;
+int            replica_demotion = 0;
+char   *replica_id_string = NULL;
+char   **replica_id_strlist = NULL;
+int            *replica_id_list = NULL;
 int            continuemode = 0;
 int            nosubordinates = 0;
 int            dryrun = 0;
@@ -51,7 +56,7 @@ usage( int tool )
 
        switch( tool ) {
        case SLAPADD:
-               options = "\t[-l ldiffile] [-u] [-W] [-w]\n";
+               options = "\n\t[-l ldiffile] [-u] [-p [-w] | -r [-i syncreplidlist] [-w]]\n";
                break;
 
        case SLAPCAT:
@@ -103,7 +108,7 @@ slap_tool_init(
 
        switch( tool ) {
        case SLAPADD:
-               options = "b:cd:f:l:n:tuvWw";
+               options = "b:cd:f:i:l:n:prtuvWw";
                break;
 
        case SLAPINDEX:
@@ -144,6 +149,21 @@ slap_tool_init(
                        conffile = strdup( optarg );
                        break;
 
+               case 'i': /* specify syncrepl id list */
+                       replica_id_string = strdup( optarg );
+                       if ( !isdigit( *replica_id_string )) {
+                               usage( tool );
+                               exit( EXIT_FAILURE );
+                       }
+                       str2clist( &replica_id_strlist, replica_id_string, "," );
+                       for ( i = 0; replica_id_strlist && replica_id_strlist[i]; i++ ) ;
+                       replica_id_list = ch_calloc( i + 1, sizeof( int ) );
+                       for ( i = 0; replica_id_strlist && replica_id_strlist[i]; i++ ) {
+                               replica_id_list[i] = atoi( replica_id_strlist[i] );
+                       }
+                       replica_id_list[i] = -1;
+                       break;
+
                case 'k':       /* Retrieve sync cookie entry */
                        retrieve_synccookie = 1;
                        break;
@@ -160,6 +180,14 @@ slap_tool_init(
                        dbnum = atoi( optarg ) - 1;
                        break;
 
+               case 'p':       /* replica promotion */
+                       replica_promotion = 1;          
+                       break;
+
+               case 'r':       /* replica demotion */
+                       replica_demotion = 1;           
+                       break;
+
                case 's':       /* dump subtree */
                        subtree = strdup( optarg );
                        break;
@@ -196,6 +224,14 @@ slap_tool_init(
                usage( tool );
        }
 
+       if ( replica_promotion && replica_demotion ) {
+               usage( tool );
+       } else if ( !replica_promotion && !replica_demotion ) {
+               if ( update_ctxcsn != SLAP_TOOL_CTXCSN_KEEP ) {
+                       usage( tool );
+               }
+       }
+
        if ( ldiffile == NULL ) {
                ldiffp = tool == SLAPCAT ? stdout : stdin;
 
index 925b9976b185f406d91129d9837b4a02153aec70..4d3b7b5694b75b0779b1571b70c924d9d4770ff7 100644 (file)
@@ -18,7 +18,7 @@ enum slaptool {
        SLAPTEST        /* database testing tool */
 };
 
-#define SLAP_TOOL_CTXCSN_NONE  0
+#define SLAP_TOOL_CTXCSN_KEEP  0
 #define SLAP_TOOL_CTXCSN_ENTRY 1
 #define SLAP_TOOL_CTXCSN_BATCH 2
 
@@ -30,6 +30,11 @@ extern       int             verbose;
 extern int             update_ctxcsn;
 extern int             retrieve_ctxcsn;
 extern int             retrieve_synccookie;
+extern int             replica_promotion;
+extern int             replica_demotion;
+extern char    *replica_id_string;
+extern char    **replica_id_strlist;
+extern int     *replica_id_list;
 extern int             continuemode;
 extern int             nosubordinates;
 extern int             dryrun;