slaptools update : replica promotion / demotion

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.
This commit is contained in:
Jong Hyuk Choi 2003-10-07 20:01:37 +00:00
parent 6c25cb17d5
commit a8574a450f
8 changed files with 571 additions and 134 deletions

View 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 );
}

View 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

View 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;
}
static struct berval ocbva[] = {
BER_BVC("top"),
BER_BVC("subentry"),
BER_BVC("syncProviderSubentry"),
{0,NULL}
};
char **
str2clist( char ***out, char *in, const char *brkstr )
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;
Entry* e;
int rc;
/* find last element in list */
for (i = 0; *out && *out[i]; i++);
struct berval bv;
/* protect the input string from strtok */
str = ch_strdup( in );
e = ( Entry * ) ch_calloc( 1, sizeof( Entry ));
if ( *str == '\0' ) {
free( str );
return( *out );
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 );
}
/* Count words in string */
j=1;
for ( s = str; *s; s++ ) {
if ( strchr( brkstr, *s ) != NULL ) {
j++;
}
}
bv.bv_val = "{}";
bv.bv_len = sizeof("{}")-1;
attr_merge_one( e, slap_schema.si_ad_subtreeSpecification, &bv, NULL );
*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++;
}
build_new_dn( &e->e_name, &be->be_nsuffix[0], rdn, NULL );
ber_dupbv( &e->e_nname, &e->e_name );
*new = NULL;
free( str );
return( *out );
return e;
}

View 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

View 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( )
{
return;
}
void* do_syncrepl( void *ctx, void *arg )
{
return NULL;
}
char** str2clist( char ***out, char *in, const char *brkstr )
{
return NULL;
}
void syncrepl_add_glue( syncinfo_t *si, LDAP *ld, Operation *op, Entry *e,
Modifications *modlist, int syncstate, struct berval* syncUUID,
struct berval* syncCookie )
{
return;
}
int slap_entry2mods( Entry *e, Modifications **mods, const char **text )
{
return -1;
}
volatile sig_atomic_t slapd_abrupt_shutdown;
int slap_mods_check( Modifications *ml, int update, const char **text,
char *textbuf, size_t textlen, void *ctx )
{
return -1;
}
int slap_mods2entry( Modifications *mods, Entry **e, int repl_user,
int dup, const char **text, char *textbuf, size_t textlen )
{
return -1;
}
int slap_mods_opattrs( Operation *op, Modifications *mods,
Modifications **modtail, const char **text,
char *textbuf, size_t textlen )
{
return -1;
}

View File

@ -21,6 +21,18 @@
#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,78 +265,398 @@ main( int argc, char **argv )
vals[0] = csn;
attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
}
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 (!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 ( 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';
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 );
}
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);
rc = EXIT_FAILURE;
}
if ( verbose ) {
fprintf( stderr, "modified: \"%s\" (%08lx)\n", ctxcsn_e->e_dn, (long) ctxcsn_id );
}
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 {
fprintf( stderr, "%s: could not modify ctxcsn subentry\n", progname);
rc = EXIT_FAILURE;
match = -1;
}
if ( match < 0 ) {
if ( maxcsn.bv_val )
ch_free( maxcsn.bv_val );
ber_dupbv( &maxcsn, &sei->cookie );
}
}
}
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, &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;
}
}
}
} 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 ( 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 {
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 );
if( be->be_entry_close( be )) rc = EXIT_FAILURE;

View 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;

View 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;