diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
index f774b1322c..46ee8dac69 100644
--- a/servers/slapd/Makefile.in
+++ b/servers/slapd/Makefile.in
@@ -35,7 +35,7 @@ SRCS = main.c globals.c bconfig.c config.c daemon.c \
oidm.c starttls.c index.c sets.c referral.c root_dse.c \
sasl.c module.c mra.c mods.c sl_malloc.c zn_malloc.c limits.c \
operational.c matchedValues.c cancel.c syncrepl.c \
- backover.c ctxcsn.c ldapsync.c frontend.c \
+ backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
aci.c \
@@ -53,7 +53,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
oidm.o starttls.o index.o sets.o referral.o root_dse.o \
sasl.o module.o mra.o mods.o sl_malloc.o zn_malloc.o limits.o \
operational.o matchedValues.o cancel.o syncrepl.o \
- backover.o ctxcsn.o ldapsync.o frontend.o \
+ backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
aci.o \
diff --git a/servers/slapd/overlays/glue.c b/servers/slapd/backglue.c
similarity index 84%
rename from servers/slapd/overlays/glue.c
rename to servers/slapd/backglue.c
index 52f3034ceb..936d617fde 100644
--- a/servers/slapd/overlays/glue.c
+++ b/servers/slapd/backglue.c
@@ -1,4 +1,4 @@
-/* glue.c - backend glue overlay */
+/* backglue.c - backend glue */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
@@ -28,8 +28,6 @@
#include "portable.h"
-#ifdef SLAPD_OVER_GLUE
-
#include
#include
@@ -41,7 +39,6 @@
typedef struct gluenode {
BackendDB *gn_be;
struct berval gn_pdn;
- int gn_async;
} gluenode;
typedef struct glueinfo {
@@ -746,6 +743,8 @@ glue_db_init(
oi->oi_bi.bi_tool_id2entry_get = 0;
oi->oi_bi.bi_tool_entry_modify = 0;
+ SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE;
+
return 0;
}
@@ -772,105 +771,172 @@ glue_db_close(
return 0;
}
-static int
-glue_db_config(
- BackendDB *be,
- const char *fname,
- int lineno,
- int argc,
- char **argv
-)
+int
+glue_sub_del( BackendDB *b0 )
{
- slap_overinst *on = (slap_overinst *)be->bd_info;
- glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+ BackendDB *be;
+ int rc = 0;
- /* redundant; could be applied just once */
- SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE;
+ /* Find the top backend for this subordinate */
+ be = b0;
+ while ( be=LDAP_STAILQ_NEXT( be, be_next )) {
+ slap_overinfo *oi;
+ slap_overinst *on;
+ glueinfo *gi;
+ int i;
- if ( strcasecmp( argv[0], "glue-sub" ) == 0 ) {
- int i, async = 0, advertise = 0;
- BackendDB *b2;
- struct berval bv, dn = BER_BVNULL;
+ if ( SLAP_GLUE_SUBORDINATE( be ))
+ continue;
+ if ( !SLAP_GLUE_INSTANCE( be ))
+ continue;
+ if ( !dnIsSuffix( &b0->be_nsuffix[0], &be->be_nsuffix[0] ))
+ continue;
- if ( argc < 2 ) {
- fprintf( stderr, "%s: line %d: too few arguments in "
- "\"glue-sub [async] [advertise]\"\n", fname, lineno );
- return -1;
+ /* OK, got the right backend, find the overlay */
+ oi = (slap_overinfo *)be->bd_info;
+ for ( on=oi->oi_list; on; on=on->on_next ) {
+ if ( on->on_bi.bi_type == glue.on_bi.bi_type )
+ break;
}
- for ( i = 2; i < argc; i++ ) {
- if ( strcasecmp( argv[i], "async" ) == 0 ) {
- async = 1;
+ assert( on != NULL );
+ gi = on->on_bi.bi_private;
+ for ( i=0; i < gi->gi_nodes; i++ ) {
+ if ( gi->gi_n[i].gn_be == b0 ) {
+ int j;
- } else if ( strcasecmp( argv[i], "advertise" ) == 0 ) {
- advertise = 1;
+ for (j=i+1; j < gi->gi_nodes; j++)
+ gi->gi_n[j-1] = gi->gi_n[j];
- } else {
- fprintf( stderr, "%s: line %d: unrecognized option "
- "\"%s\" ignored.\n", fname, lineno, argv[i] );
+ gi->gi_nodes--;
}
}
- ber_str2bv( argv[1], 0, 0, &bv );
- if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL )) {
- fprintf( stderr, "invalid suffixDN \"%s\"\n", argv[1] );
- return -1;
- }
- b2 = select_backend( &dn, 0, 1 );
- ber_memfree( dn.bv_val );
- if ( !b2 ) {
- fprintf( stderr, "%s: line %d: unknown suffix \"%s\"\n",
- fname, lineno, argv[1] );
- return -1;
- }
- if ( SLAP_GLUE_INSTANCE( b2 )) {
- fprintf( stderr, "%s: line %d: backend for %s is already glued; "
- "only one glue overlay is allowed per tree.\n",
- fname, lineno, argv[1] );
- return -1;
- }
- SLAP_DBFLAGS(b2) |= SLAP_DBFLAG_GLUE_SUBORDINATE;
- if ( advertise ) {
- SLAP_DBFLAGS(b2) |= SLAP_DBFLAG_GLUE_ADVERTISE;
- }
- gi = (glueinfo *)ch_realloc( gi, sizeof(glueinfo) +
- gi->gi_nodes * sizeof(gluenode));
- gi->gi_n[gi->gi_nodes].gn_be = b2;
- dnParent( &b2->be_nsuffix[0], &gi->gi_n[gi->gi_nodes].gn_pdn );
- gi->gi_n[gi->gi_nodes].gn_async = async;
- gi->gi_nodes++;
- on->on_bi.bi_private = gi;
- return 0;
}
- return SLAP_CONF_UNKNOWN;
+ if ( be == NULL )
+ rc = LDAP_NO_SUCH_OBJECT;
+
+ return rc;
+}
+
+typedef struct glue_Addrec {
+ struct glue_Addrec *ga_next;
+ BackendDB *ga_be;
+} glue_Addrec;
+
+/* List of added subordinates */
+static glue_Addrec *ga_list;
+
+/* Attach all the subordinate backends to their superior */
+static int
+glue_sub_attach()
+{
+ glue_Addrec *ga, *gnext = NULL;
+ int rc = 0;
+
+ /* For all the subordinate backends */
+ for ( ga=ga_list; ga != NULL; ga = gnext ) {
+ BackendDB *be;
+
+ gnext = ga->ga_next;
+
+ /* Find the top backend for this subordinate */
+ be = ga->ga_be;
+ while ( be=LDAP_STAILQ_NEXT( be, be_next )) {
+ slap_overinfo *oi;
+ slap_overinst *on;
+ glueinfo *gi;
+
+ if ( SLAP_GLUE_SUBORDINATE( be ))
+ continue;
+ if ( !dnIsSuffix( &ga->ga_be->be_nsuffix[0], &be->be_nsuffix[0] ))
+ continue;
+
+ /* If it's not already configured, set up the overlay */
+ if ( !SLAP_GLUE_INSTANCE( be )) {
+ rc = overlay_config( be, glue.on_bi.bi_type );
+ if ( rc )
+ break;
+ }
+ /* Find the overlay instance */
+ oi = (slap_overinfo *)be->bd_info;
+ for ( on=oi->oi_list; on; on=on->on_next ) {
+ if ( on->on_bi.bi_type == glue.on_bi.bi_type )
+ break;
+ }
+ assert( on != NULL );
+ gi = on->on_bi.bi_private;
+ gi = (glueinfo *)ch_realloc( gi, sizeof(glueinfo) +
+ gi->gi_nodes * sizeof(gluenode));
+ gi->gi_n[gi->gi_nodes].gn_be = ga->ga_be;
+ dnParent( &ga->ga_be->be_nsuffix[0],
+ &gi->gi_n[gi->gi_nodes].gn_pdn );
+ gi->gi_nodes++;
+ on->on_bi.bi_private = gi;
+ break;
+ }
+ if ( !be ) {
+ Debug( LDAP_DEBUG_ANY, "glue: no superior found for sub %s!\n",
+ ga->ga_be->be_suffix[0].bv_val, 0, 0 );
+ rc = LDAP_NO_SUCH_OBJECT;
+ }
+ ch_free( ga );
+ if ( rc ) break;
+ }
+
+ ga_list = gnext;
+
+ return rc;
}
int
-glue_init()
+glue_sub_add( BackendDB *be, int advert, int online )
{
+ glue_Addrec *ga;
+ int rc = 0;
+
+ SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_SUBORDINATE;
+ if ( advert )
+ SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_ADVERTISE;
+
+ ga = ch_malloc( sizeof( glue_Addrec ));
+ ga->ga_next = NULL;
+ ga->ga_be = be;
+ if ( ga_list ) {
+ glue_Addrec *g2 = ga_list;
+
+ for ( ; g2 && g2->ga_next; g2=g2->ga_next );
+ g2->ga_next = ga;
+ } else {
+ ga_list = ga;
+ }
+
+ if ( online )
+ rc = glue_sub_attach();
+
+ return rc;
+}
+
+int
+glue_sub_init()
+{
+ int rc;
+
glue.on_bi.bi_type = "glue";
glue.on_bi.bi_db_init = glue_db_init;
- glue.on_bi.bi_db_config = glue_db_config;
glue.on_bi.bi_db_close = glue_db_close;
glue.on_bi.bi_db_destroy = glue_db_destroy;
glue.on_bi.bi_op_search = glue_op_search;
glue.on_bi.bi_op_modify = glue_op_func;
glue.on_bi.bi_op_modrdn = glue_op_func;
- glue.on_bi.bi_op_add = glue_op_func;
+ glue.on_bi.bi_op_add = glue_op_func;
glue.on_bi.bi_op_delete = glue_op_func;
glue.on_bi.bi_chk_referrals = glue_chk_referrals;
glue.on_bi.bi_chk_controls = glue_chk_controls;
- return overlay_register( &glue );
-}
+ rc = overlay_register( &glue );
+ if ( rc ) return rc;
-#if SLAPD_OVER_GLUE == SLAPD_MOD_DYNAMIC
-int
-init_module( int argc, char *argv[] )
-{
- return glue_init();
+ return glue_sub_attach();
}
-#endif /* SLAPD_OVER_GLUE == SLAPD_MOD_DYNAMIC */
-
-#endif /* defined(SLAPD_OVER_GLUE */
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index 4b47318626..032cc1a0c4 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -105,6 +105,7 @@ static ConfigDriver config_schema_dn;
static ConfigDriver config_sizelimit;
static ConfigDriver config_timelimit;
static ConfigDriver config_overlay;
+static ConfigDriver config_subordinate;
static ConfigDriver config_suffix;
static ConfigDriver config_rootdn;
static ConfigDriver config_rootpw;
@@ -481,6 +482,9 @@ static ConfigTable config_back_cf_table[] = {
#endif
"( OLcfgGlAt:63 NAME 'olcSrvtab' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
+ &config_subordinate, "( OLcfgDbAt:0.14 NAME 'olcSubordinate' "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
{ "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
&config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
"SYNTAX OMsDN )", NULL, NULL },
@@ -634,7 +638,7 @@ static ConfigOCs cf_ocs[] = {
"DESC 'OpenLDAP Database-specific options' "
"SUP olcConfig STRUCTURAL "
"MUST olcDatabase "
- "MAY ( olcSuffix $ olcAccess $ olcLastMod $ olcLimits $ "
+ "MAY ( olcSuffix $ olcSubordinate $ olcAccess $ olcLastMod $ olcLimits $ "
"olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
"olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
"olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ "
@@ -1560,6 +1564,42 @@ config_overlay(ConfigArgs *c) {
return(0);
}
+static int
+config_subordinate(ConfigArgs *c)
+{
+ int rc = 1;
+ int advertise;
+
+ switch( c->op ) {
+ case SLAP_CONFIG_EMIT:
+ if ( SLAP_GLUE_SUBORDINATE( c->be )) {
+ struct berval bv;
+
+ bv.bv_val = SLAP_GLUE_ADVERTISE( c->be ) ? "advertise" : "TRUE";
+ bv.bv_len = SLAP_GLUE_ADVERTISE( c->be ) ? STRLENOF("advertise") :
+ STRLENOF("TRUE");
+
+ value_add_one( &c->rvalue_vals, &bv );
+ rc = 0;
+ }
+ break;
+ case LDAP_MOD_DELETE:
+ if ( !c->line || strcasecmp( c->line, "advertise" )) {
+ glue_sub_del( c->be );
+ } else {
+ SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_GLUE_ADVERTISE;
+ }
+ rc = 0;
+ break;
+ case LDAP_MOD_ADD:
+ case SLAP_CONFIG_ADD:
+ advertise = ( c->argc == 2 && !strcasecmp( c->argv[1], "advertise" ));
+ rc = glue_sub_add( c->be, advertise, CONFIG_ONLINE_ADD( c ));
+ break;
+ }
+ return rc;
+}
+
static int
config_suffix(ConfigArgs *c)
{
diff --git a/servers/slapd/main.c b/servers/slapd/main.c
index 03b264513d..81fbed49f4 100644
--- a/servers/slapd/main.c
+++ b/servers/slapd/main.c
@@ -631,6 +631,14 @@ unhandled_option:;
}
}
+ if ( glue_sub_init( ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "subordinate config error\n",
+ 0, 0, 0 );
+
+ goto destroy;
+ }
+
if ( slap_schema_check( ) != 0 ) {
Debug( LDAP_DEBUG_ANY,
"schema prep error\n",
diff --git a/servers/slapd/overlays/Makefile.in b/servers/slapd/overlays/Makefile.in
index 59547e22fe..86c8f043ca 100644
--- a/servers/slapd/overlays/Makefile.in
+++ b/servers/slapd/overlays/Makefile.in
@@ -18,7 +18,6 @@ SRCS = overlays.c \
denyop.c \
dyngroup.c \
dynlist.c \
- glue.c \
lastmod.c \
pcache.c \
ppolicy.c \
@@ -68,9 +67,6 @@ dyngroup.la : dyngroup.lo
dynlist.la : dynlist.lo
$(LTLINK_MOD) -module -o $@ dynlist.lo version.lo $(LINK_LIBS)
-glue.la : glue.lo
- $(LTLINK_MOD) -module -o $@ glue.lo version.lo $(LINK_LIBS)
-
lastmod.la : lastmod.lo
$(LTLINK_MOD) -module -o $@ lastmod.lo version.lo $(LINK_LIBS)
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 899d13dfcc..d79433ca20 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -389,6 +389,14 @@ LDAP_SLAPD_F (int) backend_operational LDAP_P((
LDAP_SLAPD_V(BackendInfo) slap_binfo[];
+/*
+ * backglue.c
+ */
+
+LDAP_SLAPD_F (int) glue_sub_init( void );
+LDAP_SLAPD_F (int) glue_sub_add( BackendDB *be, int advert, int online );
+LDAP_SLAPD_F (int) glue_sub_del( BackendDB *be );
+
/*
* backover.c
*/
diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c
index a035874ee1..bbdb5bb3e3 100644
--- a/servers/slapd/slapcommon.c
+++ b/servers/slapd/slapcommon.c
@@ -424,6 +424,13 @@ slap_tool_init(
break;
}
+ rc = glue_sub_init();
+
+ if ( rc != 0 ) {
+ fprintf( stderr, "%s: subordinate configuration error\n", progname );
+ exit( EXIT_FAILURE );
+ }
+
rc = slap_schema_check();
if ( rc != 0 ) {