/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2001-2004 The OpenLDAP Foundation.
+ * Copyright 2001-2005 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef struct gluenode {
BackendDB *gn_be;
- int gn_bx;
struct berval gn_pdn;
int gn_async;
} gluenode;
return rc;
}
+static int
+glue_chk_referrals ( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+ BackendDB *b0 = op->o_bd;
+ BackendInfo *bi0 = op->o_bd->bd_info;
+ int rc;
+
+ op->o_bd = glue_back_select (b0, &op->o_req_ndn);
+ b0->bd_info = on->on_info->oi_orig;
+
+ if ( op->o_bd->bd_info->bi_chk_referrals )
+ rc = ( *op->o_bd->bd_info->bi_chk_referrals )( op, rs );
+ else
+ rc = SLAP_CB_CONTINUE;
+
+ op->o_bd = b0;
+ op->o_bd->bd_info = bi0;
+ return rc;
+}
+
+static int
+glue_chk_controls ( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+ BackendDB *b0 = op->o_bd;
+ BackendInfo *bi0 = op->o_bd->bd_info;
+ int rc = SLAP_CB_CONTINUE;
+
+ op->o_bd = glue_back_select (b0, &op->o_req_ndn);
+ b0->bd_info = on->on_info->oi_orig;
+
+ /* if the subordinate database has overlays, the bi_chk_controls()
+ * hook is actually over_aux_chk_controls(); in case it actually
+ * wraps a missing hok, we need to mimic the behavior
+ * of the frontend applied to that database */
+ if ( op->o_bd->bd_info->bi_chk_controls ) {
+ rc = ( *op->o_bd->bd_info->bi_chk_controls )( op, rs );
+ }
+
+
+ if ( rc == SLAP_CB_CONTINUE ) {
+ rc = backend_check_controls( op, rs );
+ }
+
+ op->o_bd = b0;
+ op->o_bd->bd_info = bi0;
+ return rc;
+}
+
static int
glue_op_search ( Operation *op, SlapReply *rs )
{
switch (op->ors_scope) {
case LDAP_SCOPE_BASE:
- return SLAP_CB_CONTINUE;
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ if (op->o_bd && op->o_bd->be_search) {
+ rs->sr_err = op->o_bd->be_search( op, rs );
+ }
+ return rs->sr_err;
case LDAP_SCOPE_ONELEVEL:
case LDAP_SCOPE_SUBTREE:
case LDAP_TIMELIMIT_EXCEEDED:
case LDAP_ADMINLIMIT_EXCEEDED:
case LDAP_NO_SUCH_OBJECT:
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ case LDAP_CANNOT_CHAIN:
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
goto end_of_loop;
default:
break;
}
- if ( !op->o_abandon ) {
+ if ( op->o_abandon ) {
+ rs->sr_err = SLAPD_ABANDON;
+ } else {
op->o_callback = cb.sc_next;
rs->sr_err = gs.err;
rs->sr_matched = gs.matched;
slap_overinst *on = glue_tool_inst( bi );
glueinfo *gi = on->on_bi.bi_private;
static int glueOpened = 0;
- int i, rc = 0;
+ int i, j, same, bsame = 0, rc = 0;
if (glueOpened) return 0;
/* If we were invoked in tool mode, open all the underlying backends */
if (slapMode & SLAP_TOOL_MODE) {
- rc = backend_startup( NULL );
+ for (i = 0; i<gi->gi_nodes; i++) {
+ same = 0;
+ /* Same type as our main backend? */
+ if ( gi->gi_n[i].gn_be->bd_info == on->on_info->oi_orig )
+ bsame = 1;
+
+ /* Loop thru the bd_info's and make sure we only
+ * invoke their bi_open functions once each.
+ */
+ for ( j = 0; j<i; j++ ) {
+ if ( gi->gi_n[i].gn_be->bd_info ==
+ gi->gi_n[j].gn_be->bd_info ) {
+ same = 1;
+ break;
+ }
+ }
+ /* OK, it's unique and non-NULL, call it. */
+ if ( !same && gi->gi_n[i].gn_be->bd_info->bi_open )
+ rc = gi->gi_n[i].gn_be->bd_info->bi_open(
+ gi->gi_n[i].gn_be->bd_info );
+ /* Let backend.c take care of the rest of startup */
+ if ( !rc )
+ rc = backend_startup_one( gi->gi_n[i].gn_be );
+ if ( rc ) break;
+ }
+ if ( !rc && !bsame && on->on_info->oi_orig->bi_open )
+ rc = on->on_info->oi_orig->bi_open( on->on_info->oi_orig );
+
} /* other case is impossible */
return rc;
}
return SLAP_CB_CONTINUE;
}
-static int
-glue_db_open (
- BackendDB *be
-)
-{
- slap_overinst *on = (slap_overinst *)be->bd_info;
- glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
- int i;
-
- for ( i=0; i<gi->gi_nodes; i++ ) {
- gi->gi_n[i].gn_be = backendDB + gi->gi_n[i].gn_bx;
- }
- return 0;
-}
-
static int
glue_db_close(
BackendDB *be
slap_overinst *on = (slap_overinst *)be->bd_info;
glueinfo *gi = (glueinfo *)on->on_bi.bi_private;
+ /* redundant; could be applied just once */
+ SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE;
+
if ( strcasecmp( argv[0], "glue-sub" ) == 0 ) {
- int async = 0;
+ int i, async = 0, advertise = 0;
BackendDB *b2;
struct berval bv, dn;
gluenode *gn;
if ( argc < 2 ) {
fprintf( stderr, "%s: line %d: too few arguments in "
- "\"glue-sub <suffixDN> [async]\"\n", fname, lineno );
+ "\"glue-sub <suffixDN> [async] [advertise]\"\n", fname, lineno );
return -1;
}
- if ( argc == 3 ) {
- if ( strcasecmp( argv[2], "async" )) {
- fprintf( stderr, "%s: line %d: unrecognized option "
- "\"%s\" ignored.\n", fname, lineno, argv[2] );
- } else {
+ for ( i = 2; i < argc; i++ ) {
+ if ( strcasecmp( argv[i], "async" ) == 0 ) {
async = 1;
+
+ } else if ( strcasecmp( argv[i], "advertise" ) == 0 ) {
+ advertise = 1;
+
+ } else {
+ fprintf( stderr, "%s: line %d: unrecognized option "
+ "\"%s\" ignored.\n", fname, lineno, argv[i] );
}
}
ber_str2bv( argv[1], 0, 0, &bv );
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_bx = b2 - backendDB;
+ 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++;
glue.on_bi.bi_db_init = glue_db_init;
glue.on_bi.bi_db_config = glue_db_config;
- glue.on_bi.bi_db_open = glue_db_open;
glue.on_bi.bi_db_close = glue_db_close;
glue.on_bi.bi_db_destroy = glue_db_destroy;
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 );
}