Limit the maximum number of queries over one SQL socket.
authorAlan T. DeKok <aland@freeradius.org>
Fri, 28 Nov 2008 10:42:59 +0000 (11:42 +0100)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 5 Jan 2009 15:04:39 +0000 (16:04 +0100)
Similar to the "lifetime" change.  If there are issues such as DB
memory leaks per client socket, then it is a good idea to periodically
close the client sockets.

raddb/sql.conf
src/modules/rlm_sql/conf.h
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h
src/modules/rlm_sql/sql.c

index 4cba389..690c3a2 100644 (file)
@@ -86,6 +86,11 @@ sql {
        # closed "lifetime" seconds after they were first opened.
        lifetime = 0
 
+       # Maximum number of queries used by an SQL socket.  If you are
+       # having issues with SQL sockets lasting "too long", you can
+       # limit the number of queries performed over one socket.  After
+       # "max_qeuries", the socket will be closed.  Use 0 for "no limit".
+       max_queries = 0
 
        # Set to 'yes' to read radius clients from the database ('nas' table)
        # Clients will ONLY be read on server startup.  For performance
index 646468b..98307ad 100644 (file)
@@ -43,6 +43,7 @@ typedef struct sql_config {
        int     deletestalesessions;
        int     num_sql_socks;
        int     lifetime;
+       int     max_queries;
        int     connect_failure_retry_delay;
        char   *postauth_query;
        char   *allowed_chars;
index bcfddf1..e6b44a5 100644 (file)
@@ -64,6 +64,8 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"},
        {"lifetime", PW_TYPE_INTEGER,
         offsetof(SQL_CONFIG,lifetime), NULL, "0"},
+       {"max_queries", PW_TYPE_INTEGER,
+        offsetof(SQL_CONFIG,max_queries), NULL, "0"},
        {"sql_user_name", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,query_user), NULL, ""},
        {"default_user_profile", PW_TYPE_STRING_PTR,
index 4847c46..3e85ab2 100644 (file)
@@ -38,6 +38,7 @@ typedef struct sql_socket {
        void    *conn;
        SQL_ROW row;
        time_t  connected;
+       int     queries;
 } SQLSOCK;
 
 typedef struct rlm_sql_module_t {
index f369985..894c1e5 100644 (file)
@@ -59,6 +59,7 @@ static int connect_single_socket(SQLSOCK *sqlsocket, SQL_INST *inst)
                       inst->config->xlat_name, sqlsocket->id);
                sqlsocket->state = sockconnected;
                if (inst->config->lifetime) time(&sqlsocket->connected);
+               sqlsocket->queries = 0;
                return(0);
        }
 
@@ -231,6 +232,17 @@ SQLSOCK * sql_get_socket(SQL_INST * inst)
                }
 
                /*
+                *      If we have performed too many queries over this
+                *      socket, then close it.
+                */
+               if (inst->config->max_queries && (cur->state == sockconnected) &&
+                   (cur->queries >= inst->config->max_queries)) {
+                       (inst->module->sql_close)(cur, inst->config);
+                       cur->state = sockunconnected;
+                       goto reconnect;
+               }
+
+               /*
                 *      If we happen upon an unconnected socket, and
                 *      this instance's grace period on
                 *      (re)connecting has expired, then try to
@@ -273,6 +285,7 @@ SQLSOCK * sql_get_socket(SQL_INST * inst)
                 *      as it's a pointer only used for reading.
                 */
                inst->last_used = cur->next;
+               cur->queries++;
                return cur;
 
                /* move along the list */