]> git.sur5r.net Git - openldap/commitdiff
add cancel strategies (ITS#4560)
authorPierangelo Masarati <ando@openldap.org>
Sat, 20 May 2006 14:29:01 +0000 (14:29 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 20 May 2006 14:29:01 +0000 (14:29 +0000)
16 files changed:
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/map.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c

index e8e73cc462679fbcf91420b7c64af0bffa88f89c..197b745576fe7203fc8a820a1cd32aa4ad4834c7 100644 (file)
@@ -176,34 +176,57 @@ typedef struct ldapinfo_t {
 #define LDAP_BACK_RETRY_DEFAULT                (3)
 
        unsigned        li_flags;
-#define LDAP_BACK_F_NONE               0x0000U
-#define LDAP_BACK_F_SAVECRED           0x0001U
-#define LDAP_BACK_F_USE_TLS            0x0002U
-#define LDAP_BACK_F_PROPAGATE_TLS      0x0004U
-#define LDAP_BACK_F_TLS_CRITICAL       0x0008U
+#define LDAP_BACK_F_NONE               (0x0000U)
+#define LDAP_BACK_F_SAVECRED           (0x0001U)
+#define LDAP_BACK_F_USE_TLS            (0x0002U)
+#define LDAP_BACK_F_PROPAGATE_TLS      (0x0004U)
+#define LDAP_BACK_F_TLS_CRITICAL       (0x0008U)
 #define LDAP_BACK_F_TLS_USE_MASK       (LDAP_BACK_F_USE_TLS|LDAP_BACK_F_TLS_CRITICAL)
 #define LDAP_BACK_F_TLS_PROPAGATE_MASK (LDAP_BACK_F_PROPAGATE_TLS|LDAP_BACK_F_TLS_CRITICAL)
 #define LDAP_BACK_F_TLS_MASK           (LDAP_BACK_F_TLS_USE_MASK|LDAP_BACK_F_TLS_PROPAGATE_MASK)
-#define LDAP_BACK_F_CHASE_REFERRALS    0x0010U
-#define LDAP_BACK_F_PROXY_WHOAMI       0x0020U
+#define LDAP_BACK_F_CHASE_REFERRALS    (0x0010U)
+#define LDAP_BACK_F_PROXY_WHOAMI       (0x0020U)
 
-#define        LDAP_BACK_F_SUPPORT_T_F_DISCOVER        0x0040U
-#define        LDAP_BACK_F_SUPPORT_T_F         0x0080U
-#define        LDAP_BACK_F_SUPPORT_T_F_MASK    (LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER)
+#define        LDAP_BACK_F_T_F                 (0x0040U)
+#define        LDAP_BACK_F_T_F_DISCOVER        (0x0080U)
+#define        LDAP_BACK_F_T_F_MASK            (LDAP_BACK_F_T_F)
+#define        LDAP_BACK_F_T_F_MASK2           (LDAP_BACK_F_T_F_MASK|LDAP_BACK_F_T_F_DISCOVER)
 
-#define LDAP_BACK_F_MONITOR            0x0100U
-#define        LDAP_BACK_F_SINGLECONN          0x0200U
+#define LDAP_BACK_F_MONITOR            (0x0100U)
+#define        LDAP_BACK_F_SINGLECONN          (0x0200U)
+
+#define        LDAP_BACK_F_ISOPEN              (0x0400U)
+
+#define        LDAP_BACK_F_CANCEL_ABANDON      (0x0000U)
+#define        LDAP_BACK_F_CANCEL_IGNORE       (0x1000U)
+#define        LDAP_BACK_F_CANCEL_EXOP         (0x2000U)
+#define        LDAP_BACK_F_CANCEL_EXOP_DISCOVER        (0x4000U)
+#define        LDAP_BACK_F_CANCEL_MASK         (LDAP_BACK_F_CANCEL_IGNORE|LDAP_BACK_F_CANCEL_EXOP)
+#define        LDAP_BACK_F_CANCEL_MASK2        (LDAP_BACK_F_CANCEL_MASK|LDAP_BACK_F_CANCEL_EXOP_DISCOVER)
 
 #define        LDAP_BACK_ISSET(li,f)           ( ( (li)->li_flags & (f) ) == (f) )
+#define        LDAP_BACK_ISMASK(li,m,f)        ( ( (li)->li_flags & (m) ) == (f) )
+
 #define LDAP_BACK_SAVECRED(li)         LDAP_BACK_ISSET( (li), LDAP_BACK_F_SAVECRED )
 #define LDAP_BACK_USE_TLS(li)          LDAP_BACK_ISSET( (li), LDAP_BACK_F_USE_TLS )
 #define LDAP_BACK_PROPAGATE_TLS(li)    LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROPAGATE_TLS )
 #define LDAP_BACK_TLS_CRITICAL(li)     LDAP_BACK_ISSET( (li), LDAP_BACK_F_TLS_CRITICAL )
 #define LDAP_BACK_CHASE_REFERRALS(li)  LDAP_BACK_ISSET( (li), LDAP_BACK_F_CHASE_REFERRALS )
 #define LDAP_BACK_PROXY_WHOAMI(li)     LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROXY_WHOAMI )
+
+#define        LDAP_BACK_T_F(li)               LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
+#define        LDAP_BACK_T_F_DISCOVER(li)      LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
+
 #define LDAP_BACK_MONITOR(li)          LDAP_BACK_ISSET( (li), LDAP_BACK_F_MONITOR )
 #define        LDAP_BACK_SINGLECONN(li)        LDAP_BACK_ISSET( (li), LDAP_BACK_F_SINGLECONN )
 
+#define        LDAP_BACK_ISOPEN(li)            LDAP_BACK_ISSET( (li), LDAP_BACK_F_ISOPEN )
+
+#define        LDAP_BACK_ABANDON(li)           LDAP_BACK_ISMASK( (li), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_ABANDON )
+#define        LDAP_BACK_IGNORE(li)            LDAP_BACK_ISMASK( (li), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_IGNORE )
+#define        LDAP_BACK_CANCEL(li)            LDAP_BACK_ISMASK( (li), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_EXOP )
+#define        LDAP_BACK_CANCEL_DISCOVER(li)   LDAP_BACK_ISMASK( (li), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
+
        int             li_version;
 
        ldap_avl_info_t li_conninfo;
index 11f55d21f10adffefe860501d542568ae9b3bb7e..74626b493c3bbb7d0422404ce649da37cb34e463 100644 (file)
@@ -1114,6 +1114,35 @@ ldap_back_default_urllist(
        return LDAP_SUCCESS;
 }
 
+int
+ldap_back_cancel(
+               ldapconn_t              *lc,
+               Operation               *op,
+               SlapReply               *rs,
+               ber_int_t               msgid,
+               ldap_back_send_t        sendok )
+{
+       ldapinfo_t      *li = (ldapinfo_t *)op->o_bd->be_private;
+
+       /* default behavior */
+       if ( LDAP_BACK_ABANDON( li ) ) {
+               return ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
+       }
+
+       if ( LDAP_BACK_IGNORE( li ) ) {
+               return LDAP_SUCCESS;
+       }
+
+       if ( LDAP_BACK_CANCEL( li ) ) {
+               /* FIXME: asynchronous? */
+               return ldap_cancel_s( lc->lc_ld, msgid, NULL, NULL );
+       }
+
+       assert( 0 );
+
+       return LDAP_OTHER;
+}
+
 int
 ldap_back_op_result(
                ldapconn_t              *lc,
@@ -1157,7 +1186,7 @@ retry:;
                switch ( rc ) {
                case 0:
                        if ( timeout ) {
-                               (void)ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
+                               (void)ldap_back_cancel( lc, op, rs, msgid, sendok );
                                rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
                                        LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
                                rs->sr_text = "Operation timed out";
index d270b40eab65115d9409f4b5ec45ac5fd0cbc5ef..02b475ca76fdaf1236c02cdfc6183fe4d4d19b12 100644 (file)
@@ -65,6 +65,7 @@ enum {
        LDAP_BACK_CFG_NETWORK_TIMEOUT,
        LDAP_BACK_CFG_VERSION,
        LDAP_BACK_CFG_SINGLECONN,
+       LDAP_BACK_CFG_CANCEL,
        LDAP_BACK_CFG_REWRITE,
 
        LDAP_BACK_CFG_LAST
@@ -259,6 +260,14 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsBoolean "
                        "SINGLE-VALUE )",
                NULL, NULL },
+       { "cancel", "ABANDON|ignore|exop", 2, 0, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.20 "
+                       "NAME 'olcDbCancel' "
+                       "DESC 'abandon/ignore/exop operations when appropriate' "
+                       "SYNTAX OMsDirectoryString "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
        { "suffixmassage", "[virtual]> <real", 2, 3, 0,
                ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
                ldap_back_cf_gen, NULL, NULL, NULL },
@@ -294,6 +303,7 @@ static ConfigOCs ldapocs[] = {
                        "$ olcDbTimeout "
                        "$ olcDbIdleTimeout "
                        "$ olcDbSingleConn "
+                       "$ olcDbCancel "
                ") )",
                        Cft_Database, ldapcfg},
        { NULL, 0, NULL }
@@ -317,12 +327,20 @@ static slap_verbmasks tls_mode[] = {
 };
 
 static slap_verbmasks t_f_mode[] = {
-       { BER_BVC( "yes" ),             LDAP_BACK_F_SUPPORT_T_F },
-       { BER_BVC( "discover" ),        LDAP_BACK_F_SUPPORT_T_F_DISCOVER },
+       { BER_BVC( "yes" ),             LDAP_BACK_F_T_F },
+       { BER_BVC( "discover" ),        LDAP_BACK_F_T_F_DISCOVER },
        { BER_BVC( "no" ),              LDAP_BACK_F_NONE },
        { BER_BVNULL,                   0 }
 };
 
+static slap_verbmasks cancel_mode[] = {
+       { BER_BVC( "ignore" ),          LDAP_BACK_F_CANCEL_IGNORE },
+       { BER_BVC( "exop" ),            LDAP_BACK_F_CANCEL_EXOP },
+       { BER_BVC( "exop-discover" ),   LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
+       { BER_BVC( "abandon" ),         LDAP_BACK_F_CANCEL_ABANDON },
+       { BER_BVNULL,                   0 }
+};
+
 static slap_cf_aux_table timeout_table[] = {
        { BER_BVC("add="), 0 * sizeof( time_t ), 'u', 0, NULL },
        { BER_BVC("delete="), 1 * sizeof( time_t ), 'u', 0, NULL },
@@ -548,7 +566,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                        break;
 
                case LDAP_BACK_CFG_T_F:
-                       enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_SUPPORT_T_F_MASK), &bv );
+                       enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_T_F_MASK2), &bv );
                        if ( BER_BVISNULL( &bv ) ) {
                                /* there's something wrong... */
                                assert( 0 );
@@ -643,6 +661,23 @@ ldap_back_cf_gen( ConfigArgs *c )
                        c->value_int = LDAP_BACK_SINGLECONN( li );
                        break;
 
+               case LDAP_BACK_CFG_CANCEL: {
+                       slap_mask_t     mask = LDAP_BACK_F_CANCEL_MASK2;
+
+                       if ( LDAP_BACK_CANCEL_DISCOVER( li ) ) {
+                               mask &= ~LDAP_BACK_F_CANCEL_EXOP;
+                       }
+                       enum_to_verb( cancel_mode, (li->li_flags & mask), &bv );
+                       if ( BER_BVISNULL( &bv ) ) {
+                               /* there's something wrong... */
+                               assert( 0 );
+                               rc = 1;
+
+                       } else {
+                               value_add_one( &c->rvalue_vals, &bv );
+                       }
+                       } break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -711,6 +746,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                case LDAP_BACK_CFG_CHASE:
                case LDAP_BACK_CFG_T_F:
                case LDAP_BACK_CFG_WHOAMI:
+               case LDAP_BACK_CFG_CANCEL:
                        rc = 1;
                        break;
 
@@ -1258,14 +1294,41 @@ done_url:;
                }
                break;
 
-       case LDAP_BACK_CFG_T_F:
+       case LDAP_BACK_CFG_T_F: {
+               slap_mask_t             mask;
+
                i = verb_to_mask( c->argv[1], t_f_mode );
                if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
                        return 1;
                }
-               li->li_flags &= ~LDAP_BACK_F_SUPPORT_T_F_MASK;
-               li->li_flags |= t_f_mode[i].mask;
-               break;
+
+               mask = t_f_mode[i].mask;
+
+               if ( LDAP_BACK_ISOPEN( li )
+                       && mask == LDAP_BACK_F_T_F_DISCOVER
+                       && !LDAP_BACK_T_F( li ) )
+               {
+                       int             rc;
+
+                       if ( li->li_uri == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "need URI to discover \"cancel\" support "
+                                       "in \"cancel exop-discover\"" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       rc = slap_discover_feature( li->li_uri, li->li_version,
+                                       slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
+                                       LDAP_FEATURE_ABSOLUTE_FILTERS );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               mask |= LDAP_BACK_F_T_F;
+                       }
+               }
+
+               li->li_flags &= ~LDAP_BACK_F_T_F_MASK2;
+               li->li_flags |= mask;
+               } break;
 
        case LDAP_BACK_CFG_WHOAMI:
                if ( c->argc == 1 || c->value_int ) {
@@ -1362,6 +1425,42 @@ done_url:;
                }
                break;
 
+       case LDAP_BACK_CFG_CANCEL: {
+               slap_mask_t             mask;
+
+               i = verb_to_mask( c->argv[1], cancel_mode );
+               if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
+                       return 1;
+               }
+
+               mask = cancel_mode[i].mask;
+
+               if ( LDAP_BACK_ISOPEN( li )
+                       && mask == LDAP_BACK_F_CANCEL_EXOP_DISCOVER
+                       && !LDAP_BACK_CANCEL( li ) )
+               {
+                       int             rc;
+
+                       if ( li->li_uri == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "need URI to discover \"cancel\" support "
+                                       "in \"cancel exop-discover\"" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       rc = slap_discover_feature( li->li_uri, li->li_version,
+                                       slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
+                                       LDAP_EXOP_CANCEL );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               mask |= LDAP_BACK_F_CANCEL_EXOP;
+                       }
+               }
+
+               li->li_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
+               li->li_flags |= mask;
+               } break;
+
        case LDAP_BACK_CFG_REWRITE:
                snprintf( c->msg, sizeof( c->msg ),
                        "rewrite/remap capabilities have been moved "
index 765f201c21e1a0f8ce97667b23a0297dbb37570b..71e13be91cea4822f7144a077c8898b12d8f1db2 100644 (file)
@@ -200,19 +200,30 @@ ldap_back_db_open( BackendDB *be )
        }
 #endif /* SLAPD_MONITOR */
 
-       if ( li->li_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER ) {
+       if ( LDAP_BACK_T_F_DISCOVER( li ) && !LDAP_BACK_T_F( li ) ) {
                int             rc;
 
-               li->li_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
-
                rc = slap_discover_feature( li->li_uri, li->li_version,
                                slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
                                LDAP_FEATURE_ABSOLUTE_FILTERS );
                if ( rc == LDAP_COMPARE_TRUE ) {
-                       li->li_flags |= LDAP_BACK_F_SUPPORT_T_F;
+                       li->li_flags |= LDAP_BACK_F_T_F;
                }
        }
 
+       if ( LDAP_BACK_CANCEL_DISCOVER( li ) && !LDAP_BACK_CANCEL( li ) ) {
+               int             rc;
+
+               rc = slap_discover_feature( li->li_uri, li->li_version,
+                               slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
+                               LDAP_EXOP_CANCEL );
+               if ( rc == LDAP_COMPARE_TRUE ) {
+                       li->li_flags |= LDAP_BACK_F_CANCEL_EXOP;
+               }
+       }
+
+       li->li_flags |= LDAP_BACK_F_ISOPEN;
+
        return 0;
 }
 
index 05d68832549e6ff20bc9cbae843202be0340bb5d..1be04ec5f6ecbdf6ce289e52b3a90bd028e098a4 100644 (file)
@@ -56,6 +56,7 @@ int ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_s
 int ldap_back_map_result( SlapReply *rs );
 int ldap_back_op_result( ldapconn_t *lc, Operation *op, SlapReply *rs,
        ber_int_t msgid, time_t timeout, ldap_back_send_t sendok );
+int ldap_back_cancel( ldapconn_t *lc, Operation *op, SlapReply *rs, ber_int_t msgid, ldap_back_send_t sendok );
 
 int ldap_back_init_cf( BackendInfo *bi );
 
index ec68159ccfb714bb0936730e9b653ee4ff670b93..4fa338b0d7e07e7013a2d8a57e54d96fd587f82a 100644 (file)
@@ -75,7 +75,7 @@ ldap_back_munge_filter(
 
                if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) {
                        oldbv = &bv_true;
-                       if ( li->li_flags & LDAP_BACK_F_SUPPORT_T_F ) {
+                       if ( LDAP_BACK_T_F( li ) ) {
                                newbv = &bv_t;
 
                        } else {
@@ -85,7 +85,7 @@ ldap_back_munge_filter(
                } else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 )
                {
                        oldbv = &bv_false;
-                       if ( li->li_flags & LDAP_BACK_F_SUPPORT_T_F ) {
+                       if ( LDAP_BACK_T_F( li ) ) {
                                newbv = &bv_f;
 
                        } else {
@@ -264,7 +264,7 @@ retry:
                        if ( rc > 0 ) {
                                ldap_msgfree( res );
                        }
-                       ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
+                       (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
                        rc = SLAPD_ABANDON;
                        goto finish;
                }
@@ -277,7 +277,7 @@ retry:
                        if ( op->ors_tlimit != SLAP_NO_LIMIT
                                        && slap_get_time() > stoptime )
                        {
-                               ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
+                               (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
                                rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
                                goto finish;
                        }
@@ -320,7 +320,7 @@ retry:
                                if ( rc == LDAP_UNAVAILABLE ) {
                                        rc = rs->sr_err = LDAP_OTHER;
                                } else {
-                                       ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
+                                       (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
                                }
                                goto finish;
                        }
index 02a0093d5c9d65ec4a329ba58c1626e3076498f5..5835012a87415da4ed6e9c6cc986235b5dc3b7f3 100644 (file)
@@ -195,8 +195,7 @@ retry:;
                        break;
 
                case 0:
-                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
-                               msgid, NULL, NULL );
+                       (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
                                LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
                        break;
index 0516f619f3ba3d27546664dd73d574f80b4f159d..a8c969ba3464af7e0c48f4b22b2f5ba191e4da00 100644 (file)
@@ -228,6 +228,17 @@ typedef struct metatarget_t {
        struct ldaprwmap        mt_rwmap;
 
        unsigned                mt_flags;
+#define        META_BACK_TGT_ISSET(mt,f)               ( ( (mt)->mt_flags & (f) ) == (f) )
+#define        META_BACK_TGT_ISMASK(mt,m,f)            ( ( (mt)->mt_flags & (m) ) == (f) )
+
+#define        META_BACK_TGT_T_F(mt)                   META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
+#define        META_BACK_TGT_T_F_DISCOVER(mt)          META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
+
+#define        META_BACK_TGT_ABANDON(mt)               META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_ABANDON )
+#define        META_BACK_TGT_IGNORE(mt)                META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_IGNORE )
+#define        META_BACK_TGT_CANCEL(mt)                META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK, LDAP_BACK_F_CANCEL_EXOP )
+#define        META_BACK_TGT_CANCEL_DISCOVER(mt)       META_BACK_TGT_ISMASK( (mt), LDAP_BACK_F_CANCEL_MASK2, LDAP_BACK_F_CANCEL_EXOP_DISCOVER )
+
        int                     mt_version;
        time_t                  mt_network_timeout;
        struct timeval          mt_bind_timeout;
@@ -354,6 +365,15 @@ meta_back_single_dobind(
        int                     retries,
        int                     dolock );
 
+extern int
+meta_back_cancel(
+       metaconn_t              *mc,
+       Operation               *op,
+       SlapReply               *rs,
+       ber_int_t               msgid,
+       int                     candidate,
+       ldap_back_send_t        sendok );
+
 extern int
 meta_back_op_result(
        metaconn_t              *mc,
index cd79a04ced6ab3e6392cafe01782ef6dadfa236e..560fad0a0fbfa7f57da176c0898ae2acd2c6ff4a 100644 (file)
@@ -376,7 +376,7 @@ retry:;
 
                        rs->sr_err = LDAP_BUSY;
                        if ( rebinding ) {
-                               ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
+                               (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                                break;
                        }
 
@@ -393,7 +393,7 @@ retry:;
                                &rs->sr_err );
 
                        if ( rebinding ) {
-                               ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
+                               (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        }
 
                        snprintf( buf, sizeof( buf ),
@@ -552,7 +552,7 @@ retry:;
 
                        rc = LDAP_BUSY;
                        if ( rebinding ) {
-                               ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
+                               (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                                break;
                        }
 
@@ -569,7 +569,7 @@ retry:;
                                &rs->sr_err );
 
                        if ( rebinding ) {
-                               ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
+                               (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        }
 
                        snprintf( buf, sizeof( buf ),
@@ -887,6 +887,41 @@ meta_back_default_urllist(
        return LDAP_SUCCESS;
 }
 
+int
+meta_back_cancel(
+       metaconn_t              *mc,
+       Operation               *op,
+       SlapReply               *rs,
+       ber_int_t               msgid,
+       int                     candidate,
+       ldap_back_send_t        sendok )
+{
+       metainfo_t              *mi = (metainfo_t *)op->o_bd->be_private;
+
+       metatarget_t            *mt = mi->mi_targets[ candidate ];
+       metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
+
+       /* default behavior */
+       if ( META_BACK_TGT_ABANDON( mt ) ) {
+               return ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );
+       }
+
+       if ( META_BACK_TGT_IGNORE( mt ) ) {
+               return LDAP_SUCCESS;
+       }
+
+       if ( META_BACK_TGT_CANCEL( mt ) ) {
+               /* FIXME: asynchronous? */
+               return ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL );
+       }
+
+       assert( 0 );
+
+       return LDAP_OTHER;
+}
+
+
+
 /*
  * FIXME: error return must be handled in a cleaner way ...
  */
index abd351e70d469e49b59faba317379b604f994a91..e93bd6c41d6e247e3ea08c6f13ac9a2cdb391fd7 100644 (file)
@@ -734,16 +734,16 @@ meta_back_db_config(
 
                switch ( check_true_false( argv[ 1 ] ) ) {
                case 0:
-                       *flagsp &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
+                       *flagsp &= ~LDAP_BACK_F_T_F_MASK2;
                        break;
 
                case 1:
-                       *flagsp |= LDAP_BACK_F_SUPPORT_T_F;
+                       *flagsp |= LDAP_BACK_F_T_F;
                        break;
 
                default:
                        if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
-                               *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+                               *flagsp |= LDAP_BACK_F_T_F_DISCOVER;
 
                        } else {
                                Debug( LDAP_DEBUG_ANY,
@@ -833,6 +833,41 @@ meta_back_db_config(
                        return 1;
                }
 
+       } else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
+               unsigned        flag = 0;
+               unsigned        *flagsp = mi->mi_ntargets ?
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
+                               : &mi->mi_flags;
+
+               if ( argc != 2 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"cancel {abandon|ignore|exop}\" takes 1 argument\n",
+                               fname, lineno, 0 );
+                       return( 1 );
+               }
+
+               if ( strcasecmp( argv[ 1 ], "abandon" ) == 0 ) {
+                       flag = LDAP_BACK_F_CANCEL_ABANDON;
+
+               } else if ( strcasecmp( argv[ 1 ], "ignore" ) == 0 ) {
+                       flag = LDAP_BACK_F_CANCEL_IGNORE;
+
+               } else if ( strcasecmp( argv[ 1 ], "exop" ) == 0 ) {
+                       flag = LDAP_BACK_F_CANCEL_EXOP;
+
+               } else if ( strcasecmp( argv[ 1 ], "exop-discover" ) == 0 ) {
+                       flag = LDAP_BACK_F_CANCEL_EXOP_DISCOVER;
+
+               } else {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: \"cancel {abandon|ignore|exop[-discover]}\": unknown mode \"%s\" \n",
+                               fname, lineno, argv[ 1 ] );
+                       return( 1 );
+               }
+
+               *flagsp &= ~LDAP_BACK_F_CANCEL_MASK2;
+               *flagsp |= flag;
+
        } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
                char    *sep;
                time_t  *tv = mi->mi_ntargets ?
index 4d23793a8378a7d98df17b5ef20d05ef9f4f5106..b660c76dc0b2efe2562d20ce25ce12fab99a6722 100644 (file)
@@ -94,8 +94,7 @@ retry:;
                        break;
 
                case 0:
-                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
-                               msgid, NULL, NULL );
+                       (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
                                LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
                        break;
index 09f7007afc493f9a7a57fe351db58ae2205d21fd..5462a6fc441f8ede647b7f2a519cab76077235b1 100644 (file)
@@ -130,15 +130,23 @@ meta_back_db_open(
        for ( i = 0; i < mi->mi_ntargets; i++ ) {
                metatarget_t    *mt = mi->mi_targets[ i ];
 
-               if ( mt->mt_flags & LDAP_BACK_F_SUPPORT_T_F_DISCOVER )
-               {
-                       mt->mt_flags &= ~LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+               if ( META_BACK_TGT_T_F_DISCOVER( mt ) ) {
                        rc = slap_discover_feature( mt->mt_uri,
                                        mt->mt_version,
                                        slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
                                        LDAP_FEATURE_ABSOLUTE_FILTERS );
                        if ( rc == LDAP_COMPARE_TRUE ) {
-                               mt->mt_flags |= LDAP_BACK_F_SUPPORT_T_F;
+                               mt->mt_flags |= LDAP_BACK_F_T_F;
+                       }
+               }
+
+               if ( META_BACK_TGT_CANCEL_DISCOVER( mt ) ) {
+                       rc = slap_discover_feature( mt->mt_uri,
+                                       mt->mt_version,
+                                       slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
+                                       LDAP_EXOP_CANCEL );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               mt->mt_flags |= LDAP_BACK_F_CANCEL_EXOP;
                        }
                }
        }
index 912bd1671ded37bcf0150c5d4aa7436559be663e..0f01e6bfc553eec7114d1cfda86e7c9afb41fe47 100644 (file)
@@ -516,7 +516,7 @@ ldap_back_int_filter_map_rewrite(
                /* FIXME: treat UNDEFINED as FALSE */
                case SLAPD_COMPARE_UNDEFINED:
 computed:;
-                       if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) {
+                       if ( META_BACK_TGT_T_F( dc->target ) ) {
                                tmp = &ber_bvtf_false;
                                break;
                        }
@@ -524,7 +524,7 @@ computed:;
                        break;
 
                case LDAP_COMPARE_TRUE:
-                       if ( dc->target->mt_flags & LDAP_BACK_F_SUPPORT_T_F ) {
+                       if ( META_BACK_TGT_T_F( dc->target ) ) {
                                tmp = &ber_bvtf_true;
                                break;
                        }
index 2e11c5b696663bf169326f52606fc857c183974f..3ef81f1192cbf5255ff0b8906a3e7e10b1f1fc00 100644 (file)
@@ -203,8 +203,7 @@ retry:;
                        break;
 
                case 0:
-                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
-                               msgid, NULL, NULL );
+                       (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
                                LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
                        maperr = 0;
index 2c7d603b2bb4717afdfff4acad681f92de5c81a5..3d94f1083eea544c8e6ce97f4ddd8eb636fb6f73 100644 (file)
@@ -149,8 +149,7 @@ retry:;
                        break;
 
                case 0:
-                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
-                               msgid, NULL, NULL );
+                       (void)meta_back_cancel( mc, op, rs, msgid, candidate, LDAP_BACK_DONTSEND );
                        rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
                                LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
                        break;
index 45c16240bd47d1f2894e23951e3d9d5af3f2002d..50519be3f2644cd8f07e2894e2116363ab3be9c6 100644 (file)
@@ -1072,13 +1072,11 @@ really_bad:;
                /* check for abandon */
                if ( op->o_abandon || doabandon ) {
                        for ( i = 0; i < mi->mi_ntargets; i++ ) {
-                               metasingleconn_t        *msc = &mc->mc_conns[ i ];
-
                                if ( candidates[ i ].sr_msgid != META_MSGID_IGNORE )
                                {
-                                       ldap_abandon_ext( msc->msc_ld,
-                                               candidates[ i ].sr_msgid,
-                                               NULL, NULL );
+                                       (void)meta_back_cancel( mc, op, rs,
+                                               candidates[ i ].sr_msgid, i,
+                                               LDAP_BACK_DONTSEND );
                                        candidates[ i ].sr_msgid = META_MSGID_IGNORE;
                                }
                        }