X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackover.c;h=bd95b393610b1a3cc9a67a62efc60c1980a61c90;hb=3cdba151ad18dba10786fde4464442ddaf67b5fe;hp=0aa4a72be93ca3e193060cc214b0a7282ac5d2fa;hpb=fed3c18e889eddf1a176c2105f06d926de07fea9;p=openldap
diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c
index 0aa4a72be9..bd95b39361 100644
--- a/servers/slapd/backover.c
+++ b/servers/slapd/backover.c
@@ -2,7 +2,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 2003-2005 The OpenLDAP Foundation.
+ * Copyright 2003-2007 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,10 +210,13 @@ over_db_destroy(
rc = over_db_func( be, db_destroy );
- for (next = on->on_next; on; on=next) {
- next = on->on_next;
- free( on );
+ if ( on ) {
+ for (next = on->on_next; on; on=next) {
+ next = on->on_next;
+ free( on );
+ }
}
+
free( oi );
return rc;
}
@@ -235,11 +238,15 @@ over_back_response ( Operation *op, SlapReply *rs )
if ( rc != SLAP_CB_CONTINUE ) break;
}
}
+ /* Bypass the remaining on_response layers, but allow
+ * normal execution to continue.
+ */
+ if ( rc == SLAP_CB_BYPASS )
+ rc = SLAP_CB_CONTINUE;
op->o_bd = be;
return rc;
}
-#ifdef SLAP_OVERLAY_ACCESS
static int
over_access_allowed(
Operation *op,
@@ -450,7 +457,6 @@ over_acl_attribute(
return rc;
}
-#endif /* SLAP_OVERLAY_ACCESS */
/*
* default return code in case of missing backend function
@@ -492,6 +498,8 @@ int overlay_op_walk(
if ( rc != SLAP_CB_CONTINUE ) break;
}
}
+ if ( rc == SLAP_CB_BYPASS )
+ rc = SLAP_CB_CONTINUE;
func = &oi->oi_orig->bi_op_bind;
if ( func[which] && rc == SLAP_CB_CONTINUE ) {
@@ -890,7 +898,7 @@ overlay_register_control( BackendDB *be, const char *oid )
return -1;
}
- if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
+ if ( SLAP_ISGLOBALOVERLAY( be ) ) {
BackendDB *bd;
/* add to all backends... */
@@ -934,14 +942,77 @@ overlay_destroy_one( BackendDB *be, slap_overinst *on )
}
}
+void
+overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
+ int idx )
+{
+ slap_overinfo *oi = (slap_overinfo *)be->bd_info;
+
+ if ( idx == -1 ) {
+ on2->on_next = oi->oi_list;
+ oi->oi_list = on2;
+ } else {
+ int i;
+ slap_overinst *on, *otmp1 = NULL, *otmp2;
+
+ /* Since the list is in reverse order and is singly linked,
+ * we reverse it to find the idx insertion point. Adding
+ * on overlay at a specific point should be a pretty
+ * infrequent occurrence.
+ */
+ for ( on = oi->oi_list; on; on=otmp2 ) {
+ otmp2 = on->on_next;
+ on->on_next = otmp1;
+ otmp1 = on;
+ }
+ oi->oi_list = NULL;
+ /* advance to insertion point */
+ for ( i=0, on = otmp1; ion_next;
+ on->on_next = oi->oi_list;
+ oi->oi_list = on;
+ }
+ /* insert */
+ on2->on_next = oi->oi_list;
+ oi->oi_list = on2;
+ if ( otmp1 ) {
+ *prev = &otmp1->on_next;
+ /* replace remainder of list */
+ for ( on=otmp1; on; on=otmp1 ) {
+ otmp1 = on->on_next;
+ on->on_next = oi->oi_list;
+ oi->oi_list = on;
+ }
+ }
+ }
+}
+
+void
+overlay_move( BackendDB *be, slap_overinst *on, int idx )
+{
+ slap_overinfo *oi = (slap_overinfo *)be->bd_info;
+ slap_overinst **onp;
+
+ for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
+ if ( *onp == on ) {
+ *onp = on->on_next;
+ break;
+ }
+ }
+ overlay_insert( be, on, &onp, idx );
+}
+
/* add an overlay to a particular backend. */
int
-overlay_config( BackendDB *be, const char *ov )
+overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
{
- slap_overinst *on = NULL, *on2 = NULL;
+ slap_overinst *on = NULL, *on2 = NULL, **prev;
slap_overinfo *oi = NULL;
BackendInfo *bi = NULL;
+ if ( res )
+ *res = NULL;
+
on = overlay_find( ov );
if ( !on ) {
Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
@@ -952,15 +1023,33 @@ overlay_config( BackendDB *be, const char *ov )
* overlay info structure
*/
if ( !overlay_is_over( be ) ) {
+ int isglobal = 0;
+
+ /* NOTE: the first time a global overlay is configured,
+ * frontendDB gets this flag; it is used later by overlays
+ * to determine if they're stacked on top of the frontendDB */
+ if ( be->bd_info == frontendDB->bd_info || SLAP_ISGLOBALOVERLAY( be ) ) {
+ isglobal = 1;
+ if ( on->on_bi.bi_flags & SLAPO_BFLAG_DBONLY ) {
+ Debug( LDAP_DEBUG_ANY, "overlay_config(): "
+ "overlay \"%s\" cannot be global.\n",
+ ov, 0, 0 );
+ return 1;
+ }
+
+ } else if ( on->on_bi.bi_flags & SLAPO_BFLAG_GLOBONLY ) {
+ Debug( LDAP_DEBUG_ANY, "overlay_config(): "
+ "overlay \"%s\" can only be global.\n",
+ ov, 0, 0 );
+ return 1;
+ }
+
oi = ch_malloc( sizeof( slap_overinfo ) );
oi->oi_orig = be->bd_info;
oi->oi_bi = *be->bd_info;
oi->oi_origdb = be;
- /* NOTE: the first time a global overlay is configured,
- * frontendDB gets this flag; it is used later by overlays
- * to determine if they're stacked on top of the frontendDB */
- if ( oi->oi_orig == frontendDB->bd_info ) {
+ if ( isglobal ) {
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
}
@@ -1000,12 +1089,10 @@ overlay_config( BackendDB *be, const char *ov )
bi->bi_chk_referrals = over_aux_chk_referrals;
bi->bi_chk_controls = over_aux_chk_controls;
-#ifdef SLAP_OVERLAY_ACCESS
/* these have specific arglists */
bi->bi_access_allowed = over_access_allowed;
bi->bi_acl_group = over_acl_group;
bi->bi_acl_attribute = over_acl_attribute;
-#endif /* SLAP_OVERLAY_ACCESS */
bi->bi_connection_init = over_connection_init;
bi->bi_connection_destroy = over_connection_destroy;
@@ -1015,31 +1102,54 @@ overlay_config( BackendDB *be, const char *ov )
} else {
if ( overlay_is_inst( be, ov ) ) {
Debug( LDAP_DEBUG_ANY, "overlay_config(): "
- "warning, overlay \"%s\" "
- "already in list\n", ov, 0, 0 );
+ "overlay \"%s\" already in list\n",
+ ov, 0, 0 );
+ if ( SLAPO_SINGLE( be ) ) {
+ return 1;
+ }
}
oi = be->bd_info->bi_private;
}
- /* Insert new overlay on head of list. Overlays are executed
- * in reverse of config order...
+ /* Insert new overlay into list. By default overlays are
+ * added to head of list and executed in LIFO order.
*/
on2 = ch_calloc( 1, sizeof(slap_overinst) );
*on2 = *on;
on2->on_info = oi;
- on2->on_next = oi->oi_list;
- oi->oi_list = on2;
+
+ prev = &oi->oi_list;
+ /* Do we need to find the insertion point? */
+ if ( idx >= 0 ) {
+ int i;
+
+ /* count current overlays */
+ for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
+
+ /* are we just appending a new one? */
+ if ( idx >= i )
+ idx = -1;
+ }
+ overlay_insert( be, on2, &prev, idx );
/* Any initialization needed? */
- if ( on->on_bi.bi_db_init ) {
+ if ( on2->on_bi.bi_db_init ) {
int rc;
be->bd_info = (BackendInfo *)on2;
rc = on2->on_bi.bi_db_init( be );
be->bd_info = (BackendInfo *)oi;
- if ( rc ) return rc;
+ if ( rc ) {
+ *prev = on2->on_next;
+ ch_free( on2 );
+ on2 = NULL;
+ return rc;
+ }
}
+ if ( res )
+ *res = &on2->on_bi;
+
return 0;
}