]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Permit the user to specify number of seconds that a connection may remain idle,
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 21 Jan 2008 18:11:07 +0000 (18:11 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 21 Jan 2008 18:11:07 +0000 (18:11 +0000)
which fixes a crash on reconnect with the MyODBC driver.
(closes issue #11798)
 Reported by: Corydon76
 Patches:
       20080119__res_odbc__idlecheck.diff.txt uploaded by Corydon76 (license 14)
 Tested by: mvanbaak

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@99341 65c4cc65-6c06-0410-ace0-fbb531ad65f3

configs/res_odbc.conf.sample
include/asterisk/res_odbc.h
res/res_odbc.c

index 1cca8b0e7e9437e301b85e9dac28c1f8df065986..4b5fe428fa9fa6f77b5b8376d95f4e8e0a840faf 100644 (file)
@@ -23,6 +23,11 @@ dsn => MySQL-asterisk
 username => myuser
 password => mypass
 pre-connect => yes
+;
+; On some databases, the connection times out and a reconnection will be
+; necessary.  This setting configures the amount of time a connection
+; may sit idle (in seconds) before a reconnection will be attempted.
+;idlecheck => 3600
 
 ; Certain servers, such as MS SQL Server and Sybase use the TDS protocol, which
 ; limits the number of active queries per connection to 1.  By setting up pools
index aba2a24e83606d39c3f2c76080b330f120115168..7f1f55812076eb354565108011b431368ae3179b 100644 (file)
@@ -37,6 +37,7 @@ struct odbc_obj {
        ast_mutex_t lock;
        SQLHDBC  con;                   /* ODBC Connection Handle */
        struct odbc_class *parent;      /* Information about the connection is protected */
+       struct timeval last_used;
        unsigned int used:1;
        unsigned int up:1;
        AST_LIST_ENTRY(odbc_obj) list;
index 2d58ef9d302f7c300528883a33b648d7c4b5cf6c..7156341b461b90a663917cccebb42db48ea24e0c 100644 (file)
@@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/cli.h"
 #include "asterisk/lock.h"
 #include "asterisk/res_odbc.h"
+#include "asterisk/time.h"
 
 struct odbc_class
 {
@@ -67,6 +68,7 @@ struct odbc_class
        unsigned int count:10;          /* Running count of pooled connections */
        unsigned int delme:1;                   /* Purge the class */
        unsigned int backslash_is_escape:1;     /* On this database, the backslash is a native escape sequence */
+       unsigned int idlecheck;                 /* Recheck the connection if it is idle for this long */
        AST_LIST_HEAD(, odbc_obj) odbc_obj;
 };
 
@@ -121,7 +123,8 @@ SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_c
                                odbc_obj_disconnect(obj);
                                odbc_obj_connect(obj);
                                continue;
-                       }
+                       } else
+                               obj->last_used = ast_tvnow();
                        break;
                } else {
                        ast_log(LOG_WARNING, "SQL Prepare failed.  Attempting a reconnect...\n");
@@ -169,7 +172,8 @@ int ast_odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt)
                odbc_obj_connect(obj);
                res = SQLExecute(stmt);
 #endif
-       }
+       } else
+               obj->last_used = ast_tvnow();
        
        return res;
 }
@@ -214,6 +218,7 @@ static int load_odbc_config(void)
        struct ast_variable *v;
        char *cat, *dsn, *username, *password;
        int enabled, pooling, limit, bse;
+       unsigned int idlecheck;
        int connect = 0, res = 0;
 
        struct odbc_class *new;
@@ -233,7 +238,7 @@ static int load_odbc_config(void)
                        /* Reset all to defaults for each class of odbc connections */
                        dsn = username = password = NULL;
                        enabled = 1;
-                       connect = 0;
+                       connect = idlecheck = 0;
                        pooling = 0;
                        limit = 0;
                        bse = 1;
@@ -251,6 +256,8 @@ static int load_odbc_config(void)
                                                enabled = 0;
                                                break;
                                        }
+                               } else if (!strcasecmp(v->name, "idlecheck")) {
+                                       sscanf(v->value, "%d", &idlecheck);
                                } else if (!strcasecmp(v->name, "enabled")) {
                                        enabled = ast_true(v->value);
                                } else if (!strcasecmp(v->name, "pre-connect")) {
@@ -303,6 +310,7 @@ static int load_odbc_config(void)
                                }
 
                                new->backslash_is_escape = bse ? 1 : 0;
+                               new->idlecheck = idlecheck;
 
                                odbc_register_class(new, connect);
                                ast_log(LOG_NOTICE, "Registered ODBC class '%s' dsn->[%s]\n", cat, dsn);
@@ -465,7 +473,9 @@ struct odbc_obj *ast_odbc_request_obj(const char *name, int check)
 
        if (obj && check) {
                ast_odbc_sanity_check(obj);
-       }
+       } else if (obj->parent->idlecheck > 0 && ast_tvdiff_ms(ast_tvnow(), obj->last_used) / 1000 > obj->parent->idlecheck)
+               odbc_obj_connect(obj);
+
        return obj;
 }
 
@@ -533,6 +543,7 @@ static odbc_status odbc_obj_connect(struct odbc_obj *obj)
        } else {
                ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->parent->name, obj->parent->dsn);
                obj->up = 1;
+               obj->last_used = ast_tvnow();
        }
 
        ast_mutex_unlock(&obj->lock);
@@ -546,6 +557,7 @@ static int reload(void)
        struct ast_variable *v;
        char *cat, *dsn, *username, *password;
        int enabled, pooling, limit, bse;
+       unsigned int idlecheck;
        int connect = 0, res = 0;
 
        struct odbc_class *new, *class;
@@ -569,7 +581,7 @@ static int reload(void)
                                /* Reset all to defaults for each class of odbc connections */
                                dsn = username = password = NULL;
                                enabled = 1;
-                               connect = 0;
+                               connect = idlecheck = 0;
                                pooling = 0;
                                limit = 0;
                                bse = 1;
@@ -586,6 +598,8 @@ static int reload(void)
                                                        enabled = 0;
                                                        break;
                                                }
+                                       } else if (!strcasecmp(v->name, "idlecheck")) {
+                                               sscanf(v->value, "%ud", &idlecheck);
                                        } else if (!strcasecmp(v->name, "enabled")) {
                                                enabled = ast_true(v->value);
                                        } else if (!strcasecmp(v->name, "pre-connect")) {
@@ -653,6 +667,7 @@ static int reload(void)
                                        }
 
                                        new->backslash_is_escape = bse;
+                                       new->idlecheck = idlecheck;
 
                                        if (class) {
                                                ast_log(LOG_NOTICE, "Refreshing ODBC class '%s' dsn->[%s]\n", cat, dsn);