]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/glue.c
Mroe abandon checks for ITS#3671
[openldap] / servers / slapd / overlays / glue.c
index 6c64d6cfddec4d794818bd16ee8b8e8d2f0f11f9..965a1e9895c3e7b7f687b040dfd164607f72ac28 100644 (file)
@@ -2,7 +2,7 @@
 /* $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
@@ -40,7 +40,6 @@
 
 typedef struct gluenode {
        BackendDB *gn_be;
-       int     gn_bx;
        struct berval gn_pdn;
        int gn_async;
 } gluenode;
@@ -154,6 +153,97 @@ glue_op_response ( Operation *op, SlapReply *rs )
        return 0;
 }
 
+enum glue_which {
+       op_modify = 0,
+       op_modrdn,
+       op_add,
+       op_delete
+};
+
+static int
+glue_op_func ( 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;
+       BI_op_modify **func;
+       enum glue_which which;
+       int rc;
+
+       op->o_bd = glue_back_select (b0, &op->o_req_ndn);
+       b0->bd_info = on->on_info->oi_orig;
+
+       switch(op->o_tag) {
+       case LDAP_REQ_ADD: which = op_add; break;
+       case LDAP_REQ_DELETE: which = op_delete; break;
+       case LDAP_REQ_MODIFY: which = op_modify; break;
+       case LDAP_REQ_MODRDN: which = op_modrdn; break;
+       }
+
+       func = &op->o_bd->bd_info->bi_op_modify;
+       if ( func[which] )
+               rc = func[which]( op, rs );
+       else
+               rc = SLAP_CB_CONTINUE;
+
+       op->o_bd = b0;
+       op->o_bd->bd_info = bi0;
+       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 )
 {
@@ -180,7 +270,11 @@ 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:
@@ -188,6 +282,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
        case LDAP_SCOPE_SUBORDINATE: /* FIXME */
 #endif
 
+#if 0
                if ( op->o_sync ) {
                        if (op->o_bd && op->o_bd->be_search) {
                                rs->sr_err = op->o_bd->be_search( op, rs );
@@ -197,6 +292,7 @@ glue_op_search ( Operation *op, SlapReply *rs )
                        }
                        return rs->sr_err;
                }
+#endif
 
                op->o_callback = &cb;
                rs->sr_err = gs.err = LDAP_UNWILLING_TO_PERFORM;
@@ -285,6 +381,9 @@ glue_op_search ( Operation *op, SlapReply *rs )
                        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:
@@ -300,7 +399,9 @@ end_of_loop:;
 
                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;
@@ -378,15 +479,43 @@ glue_open (
 {
        slap_overinst *on = glue_tool_inst( bi );
        glueinfo                *gi = on->on_bi.bi_private;
-       int i, rc = 0;
+       static int glueOpened = 0;
+       int i, j, same, bsame = 0, rc = 0;
+
+       if (glueOpened) return 0;
+
+       glueOpened = 1;
 
        /* If we were invoked in tool mode, open all the underlying backends */
        if (slapMode & SLAP_TOOL_MODE) {
-               for ( i=0; i<gi->gi_nodes; i++ ) {
-                       gi->gi_n[i].gn_be = backendDB + gi->gi_n[i].gn_bx;
-                       rc = backend_startup( gi->gi_n[i].gn_be );
+               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;
 }
@@ -399,17 +528,39 @@ glue_close (
 {
        slap_overinst *on = glue_tool_inst( bi );
        glueinfo                *gi = on->on_bi.bi_private;
+       static int glueClosed = 0;
        int i, rc = 0;
 
+       if (glueClosed) return 0;
+
+       glueClosed = 1;
+
        if (slapMode & SLAP_TOOL_MODE) {
-               for ( i=0; i<gi->gi_nodes; i++ ) {
-                       rc = backend_shutdown( gi->gi_n[i].gn_be );
-                       if ( rc ) break;
-               }
+               rc = backend_shutdown( NULL );
        }
        return rc;
 }
 
+static int
+glue_entry_release_rw (
+       Operation *op,
+       Entry *e,
+       int rw
+)
+{
+       BackendDB *b0, b2;
+       int rc;
+
+       b0 = op->o_bd;
+       b2 = *op->o_bd;
+       b2.bd_info = (BackendInfo *)glue_tool_inst( op->o_bd->bd_info );
+       op->o_bd = glue_back_select (&b2, &e->e_nname);
+
+       rc = op->o_bd->be_release( op, e, rw );
+       op->o_bd = b0;
+       return rc;
+}
+
 static ID
 glue_tool_entry_first (
        BackendDB *b0
@@ -541,12 +692,17 @@ glue_tool_sync (
 {
        slap_overinst   *on = glue_tool_inst( b0->bd_info );
        glueinfo                *gi = on->on_bi.bi_private;
+       BackendInfo             *bi = b0->bd_info;
        int i;
 
        /* just sync everyone */
        for (i = 0; i<gi->gi_nodes; i++)
                if (gi->gi_n[i].gn_be->be_sync)
                        gi->gi_n[i].gn_be->be_sync (gi->gi_n[i].gn_be);
+       b0->bd_info = on->on_info->oi_orig;
+       if ( b0->be_sync )
+               b0->be_sync( b0 );
+       b0->bd_info = bi;
        return 0;
 }
 
@@ -569,6 +725,8 @@ glue_db_init(
        oi->oi_bi.bi_open = glue_open;
        oi->oi_bi.bi_close = glue_close;
 
+       oi->oi_bi.bi_entry_release_rw = glue_entry_release_rw;
+
        oi->oi_bi.bi_tool_entry_open = glue_tool_entry_open;
        oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close;
        oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first;
@@ -599,17 +757,13 @@ glue_db_destroy (
 }
 
 static int
-glue_db_open (
+glue_db_close( 
        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;
-       }
+       on->on_info->oi_bi.bi_db_close = NULL;
        return 0;
 }
 
@@ -625,23 +779,30 @@ glue_db_config(
        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 );
@@ -656,9 +817,12 @@ glue_db_config(
                        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++;
@@ -675,10 +839,17 @@ glue_init()
 
        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_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;
 
        return overlay_register( &glue );
 }