mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-13 14:27:59 +08:00
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:
parent
6c25cb17d5
commit
a8574a450f
@ -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 );
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user