+
+static int
+glue_db_destroy (
+ BackendDB *be
+)
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+
+ free (gi);
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+glue_db_close(
+ BackendDB *be
+)
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+
+ on->on_info->oi_bi.bi_db_close = NULL;
+ return 0;
+}
+
+int
+glue_sub_del( BackendDB *b0 )
+{
+ BackendDB *be;
+ int rc = 0;
+
+ /* Find the top backend for this subordinate */
+ be = b0;
+ while ( (be=LDAP_STAILQ_NEXT( be, be_next )) != NULL ) {
+ slap_overinfo *oi;
+ slap_overinst *on;
+ glueinfo *gi;
+ int i;
+
+ if ( SLAP_GLUE_SUBORDINATE( be ))
+ continue;
+ if ( !SLAP_GLUE_INSTANCE( be ))
+ continue;
+ if ( !dnIsSuffix( &b0->be_nsuffix[0], &be->be_nsuffix[0] ))
+ continue;
+
+ /* 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;
+ }
+ 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;
+
+ for (j=i+1; j < gi->gi_nodes; j++)
+ gi->gi_n[j-1] = gi->gi_n[j];
+
+ gi->gi_nodes--;
+ }
+ }
+ }
+ 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 )) != NULL ) {
+ 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_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 = ga_list;
+ ga->ga_be = be;
+ 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_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_delete = glue_op_func;
+
+ glue.on_bi.bi_chk_referrals = glue_chk_referrals;
+ glue.on_bi.bi_chk_controls = glue_chk_controls;
+
+ rc = overlay_register( &glue );
+ if ( rc ) return rc;
+
+ return glue_sub_attach();
+}