#endif
break;
}
- } else if ( strncasecmp( cargv[i], "attr=", 5 ) == 0 ) {
- if ( add_replica_attrs( be, nr, cargv[i] + 5 ) ) {
+
+ } else if ( strncasecmp( cargv[i], "attr", 4 ) == 0 ) {
+ int exclude = 0;
+ char *arg = cargv[i] + 4;
+
+ if ( arg[0] == '!' ) {
+ arg++;
+ exclude = 1;
+ }
+
+ if ( arg[0] != '=' ) {
+ continue;
+ }
+
+ if ( add_replica_attrs( be, nr, arg + 1, exclude ) ) {
#ifdef NEW_LOGGING
LDAP_LOG(( "config", LDAP_LEVEL_INFO,
"%s: line %d: attribute \"%s\" in \"replica\" line is unknown\n",
- fname, lineno, cargv[i] + 5 ));
+ fname, lineno, arg + 1 ));
#else
Debug( LDAP_DEBUG_ANY,
"%s: line %d: attribute \"%s\" in \"replica\" line is unknown\n",
- fname, lineno, cargv[i] + 5 );
+ fname, lineno, arg + 1 );
#endif
return( 1 );
}
LDAP_SLAPD_F (int) add_replica_suffix LDAP_P(( Backend *be,
int nr, const char *suffix ));
LDAP_SLAPD_F (int) add_replica_attrs LDAP_P(( Backend *be,
- int nr, char *attrs ));
+ int nr, char *attrs, int exclude ));
LDAP_SLAPD_F (void) replog LDAP_P(( Backend *be, Operation *op,
struct berval *dn, struct berval *ndn, void *change ));
be->be_replica[ i ]
= ch_calloc( sizeof( struct slap_replica_info ), 1 );
be->be_replica[ i ]->ri_host = ch_strdup( host );
+ be->be_replica[ i ]->ri_nsuffix = NULL;
+ be->be_replica[ i ]->ri_attrs = NULL;
be->be_replica[ i + 1 ] = NULL;
return( i );
add_replica_attrs(
Backend *be,
int nr,
- char *attrs
+ char *attrs,
+ int exclude
)
{
+ if ( be->be_replica[nr]->ri_attrs != NULL ) {
+ if ( be->be_replica[nr]->ri_exclude != exclude ) {
+ fprintf( stderr, "attr selective replication directive '%s' conflicts with previous one (discarded)\n", attrs );
+ ch_free( be->be_replica[nr]->ri_attrs );
+ be->be_replica[nr]->ri_attrs = NULL;
+ }
+ }
+
+ be->be_replica[nr]->ri_exclude = exclude;
be->be_replica[nr]->ri_attrs = str2anlist( be->be_replica[nr]->ri_attrs,
attrs, "," );
return ( be->be_replica[nr]->ri_attrs == NULL );
/* fall thru */
case LDAP_REQ_MODIFY:
for ( ml = change; ml != NULL; ml = ml->sml_next ) {
- if ( ad_inlist( ml->sml_desc, be->be_replica[i]->ri_attrs ) ) {
+ int is_in, exclude;
+
+ is_in = ad_inlist( ml->sml_desc, be->be_replica[i]->ri_attrs );
+ exclude = be->be_replica[i]->ri_exclude;
+
+ /*
+ * there might be a more clever way to do this test,
+ * but this way, at least, is comprehensible :)
+ */
+ if ( ( is_in && !exclude ) || ( !is_in && exclude ) ) {
subsets = 1;
first = ml;
break;
case LDAP_REQ_ADD:
e = change;
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( ad_inlist( a->a_desc, be->be_replica[i]->ri_attrs ) ) {
+ int is_in, exclude;
+
+ is_in = ad_inlist( a->a_desc, be->be_replica[i]->ri_attrs );
+ exclude = be->be_replica[i]->ri_exclude;
+
+ if ( ( is_in && !exclude ) || ( !is_in && exclude ) ) {
subsets = 1;
first = a;
break;
ml = first ? first : change;
for ( ; ml != NULL; ml = ml->sml_next ) {
char *type;
- if ( ri && ri->ri_attrs && !ad_inlist( ml->sml_desc, ri->ri_attrs ) ) {
- continue;
+ if ( ri && ri->ri_attrs ) {
+ int is_in = ad_inlist( ml->sml_desc, ri->ri_attrs );
+
+ if ( ( !is_in && !ri->ri_exclude ) || ( is_in && ri->ri_exclude ) ) {
+ continue;
+ }
}
type = ml->sml_desc->ad_cname.bv_val;
switch ( ml->sml_op ) {
a = first ? first : e->e_attrs;
for ( ; a != NULL; a=a->a_next ) {
if ( ri && ri->ri_attrs ) {
- if ( !ad_inlist( a->a_desc, ri->ri_attrs ) ) {
+ int is_in = ad_inlist( a->a_desc, ri->ri_attrs );
+ if ( ( !is_in && !ri->ri_exclude ) || ( is_in && ri->ri_exclude ) ) {
continue;
}
/* If the list includes objectClass names,