]> git.sur5r.net Git - openldap/commitdiff
implement per-target, per-operation timeouts
authorPierangelo Masarati <ando@openldap.org>
Tue, 19 Jul 2005 00:43:38 +0000 (00:43 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 19 Jul 2005 00:43:38 +0000 (00:43 +0000)
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/config.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c

index 31b0fcb59a108d8db161060223c44c7ea31b6fde..3cc3431d73df2106e20b6d78a19deb89256eec8e 100644 (file)
@@ -43,6 +43,7 @@ meta_back_add( Operation *op, SlapReply *rs )
        LDAPMod         **attrs;
        struct berval   mdn = BER_BVNULL, mapped;
        dncookie        dc;
+       int             msgid;
        int             do_retry = 1;
 
        Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
@@ -163,20 +164,49 @@ meta_back_add( Operation *op, SlapReply *rs )
        attrs[ i ] = NULL;
 
 retry:;
-#if 0
        rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
                              attrs, op->o_ctrls, NULL, &msgid );
-       rs->sr_err = meta_back_op_result( op, rs, &mc->mc_conns[ candidate ], msgid, LDAP_BACK_SENDERR );
-#endif
-       rs->sr_err = ldap_add_ext_s( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                             attrs, op->o_ctrls, NULL );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+
+       } else if ( rs->sr_err == LDAP_SUCCESS ) {
+               struct timeval  tv, *tvp = NULL;
+               LDAPMessage     *res = NULL;
+
+               if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_ADD ];
+                       tv.tv_usec = 0;
+                       tvp = &tv;
+               }
+
+               rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
+                       msgid, LDAP_MSG_ONE, tvp, &res );
+               switch ( rs->sr_err ) {
+               case -1:
+                       rs->sr_err = LDAP_OTHER;
+                       send_ldap_result( op, rs );
+                       goto cleanup;
+
+               case 0:
+                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
+                               msgid, NULL, NULL );
+                       rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
+                               LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
+                       send_ldap_result( op, rs );
+                       goto cleanup;
+
+               default:
+                       ldap_msgfree( res );
+                       break;
+               }
        }
 
+       (void)meta_back_op_result( mc, op, rs, candidate );
+
+cleanup:;
        for ( --i; i >= 0; --i ) {
                free( attrs[ i ]->mod_bvalues );
                free( attrs[ i ] );
@@ -187,8 +217,6 @@ retry:;
                BER_BVZERO( &mdn );
        }
 
-       (void)meta_back_op_result( mc, op, rs, candidate );
-
 done:;
        meta_back_release_conn( op, mc );
 
index c3c23adadb38afd8a4eb5acdb3bac3d120a9f441..daf6e85df9f35567073ccb978bf88b50f68442f6 100644 (file)
@@ -193,6 +193,14 @@ typedef struct metaconn_t {
         * in one block with the metaconn_t structure */
 } metaconn_t;
 
+enum {
+       META_OP_ADD = 0,
+       META_OP_DELETE,
+       META_OP_MODIFY,
+       META_OP_MODRDN,
+       META_OP_LAST
+};
+
 typedef struct metatarget_t {
        char                    *mt_uri;
 
@@ -215,6 +223,7 @@ typedef struct metatarget_t {
 
        unsigned                mt_flags;
        int                     mt_version;
+       time_t                  mt_timeout[ META_OP_LAST ];
 } metatarget_t;
 
 typedef struct metadncache_t {
@@ -253,6 +262,7 @@ typedef struct metainfo_t {
 #define        META_BACK_ONERR_CONTINUE(mi)    ( !META_BACK_ONERR_CONTINUE( (mi) ) )
 
        int                     mi_version;
+       time_t                  mi_timeout[ META_OP_LAST ];
 } metainfo_t;
 
 typedef enum meta_op_type {
index 62fcd5f071eeb5d7c33b0f436ae577d1cd473835..d4167bd0948e08ce4ac7ffc8a8970fc88b2d862e 100644 (file)
@@ -96,6 +96,7 @@ meta_back_db_config(
                LDAPURLDesc     *ludp, *tmpludp;
                struct berval   dn;
                int             rc;
+               int             c;
                
                if ( argc != 2 ) {
                        fprintf( stderr,
@@ -129,6 +130,10 @@ meta_back_db_config(
                mi->mi_targets[ i ].mt_flags = mi->flags;
                mi->mi_targets[ i ].mt_version = mi->mi_version;
 
+               for ( c = 0; c < META_OP_LAST; c++ ) {
+                       mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
+               }
+
                /*
                 * uri MUST be legal!
                 */
@@ -492,6 +497,67 @@ meta_back_db_config(
                        return 1;
                }
 
+       } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
+               char    *sep, *next;
+               time_t  *tv = mi->mi_ntargets ?
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_timeout
+                               : &mi->mi_timeout;
+               int     c;
+
+               if ( argc < 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"timeout [{add|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               for ( c = 1; c < argc; c++ ) {
+                       time_t  *t = NULL, val;
+
+                       sep = strchr( argv[ c ], '=' );
+                       if ( sep != NULL ) {
+                               size_t  len = sep - argv[ c ];
+
+                               if ( strncasecmp( argv[ c ], "add", len ) == 0 ) {
+                                       t = &tv[ META_OP_ADD ];
+                               } else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) {
+                                       t = &tv[ META_OP_DELETE ];
+                               } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) {
+                                       t = &tv[ META_OP_MODIFY ];
+                               } else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) {
+                                       t = &tv[ META_OP_MODRDN ];
+                               } else {
+                                       fprintf( stderr,
+               "%s: line %d: unknown operation \"%s\" for timeout #%d.\n",
+                                               fname, lineno, argv[ c ], c );
+                                       return 1;
+                               }
+                               sep++;
+       
+                       } else {
+                               sep = argv[ c ];
+                       }
+       
+                       val = strtoul( sep, &next, 10 );
+                       if ( next == sep || next[ 0 ] != '\0' ) {
+                               fprintf( stderr,
+               "%s: line %d: unable to parse value \"%s\" for timeout.\n",
+                                       fname, lineno, sep );
+                               return 1;
+                       }
+               
+                       if ( t ) {
+                               *t = val;
+       
+                       } else {
+                               int     i;
+       
+                               for ( i = 0; i < META_OP_LAST; i++ ) {
+                                       tv[ i ] = val;
+                               }
+                       }
+               }
+       
        /* name to use as pseudo-root dn */
        } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) {
                int             i = mi->mi_ntargets - 1;
index d247de359a4cc288a7845acbd99b1b0578bc86b8..36a89cdadcdb77283e2f56fea19ab2399f804893 100644 (file)
@@ -39,6 +39,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
        int             candidate = -1;
        struct berval   mdn = BER_BVNULL;
        dncookie        dc;
+       int             msgid;
        int             do_retry = 1;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@@ -62,22 +63,54 @@ meta_back_delete( Operation *op, SlapReply *rs )
        }
 
 retry:;
-       rs->sr_err = ldap_delete_ext_s( mc->mc_conns[ candidate ].msc_ld,
-                       mdn.bv_val, op->o_ctrls, NULL );
+       rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
+                       mdn.bv_val, op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+
+       } else if ( rs->sr_err == LDAP_SUCCESS ) {
+               struct timeval  tv, *tvp = NULL;
+               LDAPMessage     *res = NULL;
+
+               if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_DELETE ];
+                       tv.tv_usec = 0;
+                       tvp = &tv;
+               }
+
+               rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
+                       msgid, LDAP_MSG_ONE, tvp, &res );
+               switch ( rs->sr_err ) {
+               case -1:
+                       rs->sr_err = LDAP_OTHER;
+                       send_ldap_result( op, rs );
+                       goto cleanup;
+
+               case 0:
+                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
+                               msgid, NULL, NULL );
+                       rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
+                               LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
+                       send_ldap_result( op, rs );
+                       goto cleanup;
+
+               default:
+                       ldap_msgfree( res );
+                       break;
+               }
        }
 
+       rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
+
+cleanup:;
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
                BER_BVZERO( &mdn );
        }
        
-       rs->sr_err = meta_back_op_result( mc, op, rs, candidate );
-
 done:;
        meta_back_release_conn( op, mc );
 
index 2d51289cb11aa8ba2da2138c0c22e77946eb08b5..379a1e03ec780f26ce9bf8066613d76001abe438 100644 (file)
@@ -45,6 +45,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
        struct berval   mdn = BER_BVNULL;
        struct berval   mapped;
        dncookie        dc;
+       int             msgid;
        int             do_retry = 1;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@@ -172,13 +173,44 @@ meta_back_modify( Operation *op, SlapReply *rs )
        modv[ i ] = 0;
 
 retry:;
-       rs->sr_err = ldap_modify_ext_s( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                       modv, op->o_ctrls, NULL );
+       rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
+                       modv, op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+
+       } else if ( rs->sr_err == LDAP_SUCCESS ) {
+               struct timeval  tv, *tvp = NULL;
+               LDAPMessage     *res = NULL;
+
+               if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODIFY ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODIFY ];
+                       tv.tv_usec = 0;
+                       tvp = &tv;
+               }
+
+               rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
+                       msgid, LDAP_MSG_ONE, tvp, &res );
+               switch ( rs->sr_err ) {
+               case -1:
+                       rs->sr_err = LDAP_OTHER;
+                       rc = -1;
+                       break;
+
+               case 0:
+                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
+                               msgid, NULL, NULL );
+                       rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
+                               LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
+                       rc = -1;
+                       break;
+
+               default:
+                       ldap_msgfree( res );
+                       break;
+               }
        }
 
 cleanup:;
index a63e99e48c731ad0d9ae763ce57fc5f4c3c7a263..90b151761ee6dfa8acbc7e7e04165ca1c597118d 100644 (file)
 int
 meta_back_modrdn( Operation *op, SlapReply *rs )
 {
-       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
-       metaconn_t              *mc;
-       int                     candidate = -1;
-       struct berval           mdn = BER_BVNULL,
-                               mnewSuperior = BER_BVNULL;
-       dncookie                dc;
-       int                     do_retry = 1;
+       metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
+       metaconn_t      *mc;
+       int             candidate = -1;
+       struct berval   mdn = BER_BVNULL,
+                       mnewSuperior = BER_BVNULL;
+       dncookie        dc;
+       int             msgid;
+       int             do_retry = 1;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
@@ -101,15 +102,44 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
        }
 
 retry:;
-       rs->sr_err = ldap_rename_s( mc->mc_conns[ candidate ].msc_ld,
+       rs->sr_err = ldap_rename( mc->mc_conns[ candidate ].msc_ld,
                        mdn.bv_val, op->orr_newrdn.bv_val,
                        mnewSuperior.bv_val, op->orr_deleteoldrdn,
-                       op->o_ctrls, NULL );
+                       op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
                if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+
+       } else if ( rs->sr_err == LDAP_SUCCESS ) {
+               struct timeval  tv, *tvp = NULL;
+               LDAPMessage     *res = NULL;
+
+               if ( mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ] != 0 ) {
+                       tv.tv_sec = mi->mi_targets[ candidate ].mt_timeout[ META_OP_MODRDN ];
+                       tv.tv_usec = 0;
+                       tvp = &tv;
+               }
+
+               rs->sr_err = ldap_result( mc->mc_conns[ candidate ].msc_ld,
+                       msgid, LDAP_MSG_ONE, tvp, &res );
+               switch ( rs->sr_err ) {
+               case -1:
+                       rs->sr_err = LDAP_OTHER;
+                       break;
+
+               case 0:
+                       ldap_abandon_ext( mc->mc_conns[ candidate ].msc_ld,
+                               msgid, NULL, NULL );
+                       rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
+                               LDAP_ADMINLIMIT_EXCEEDED : LDAP_OPERATIONS_ERROR;
+                       break;
+
+               default:
+                       ldap_msgfree( res );
+                       break;
+               }
        }
 
 cleanup:;