Changeset: 19c920ee76ea for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/19c920ee76ea
Modified Files:
        ChangeLog.Mar2025
        monetdb5/mal/mal_client.c
        monetdb5/mal/mal_client.h
        monetdb5/mal/mal_session.c
        sql/backends/monet5/sql_scenario.c
        tools/mserver/mserver5.1.in
Branch: Mar2025
Log Message:

Implemented an idle timeout.  See mserver5 manual.
(grafted from 233ef8b71026e64b3d7d6b3d925af9fb84e63537)


diffs (142 lines):

diff --git a/ChangeLog.Mar2025 b/ChangeLog.Mar2025
--- a/ChangeLog.Mar2025
+++ b/ChangeLog.Mar2025
@@ -1,3 +1,9 @@
 # ChangeLog file for devel
 # This file is updated with Maddlog
 
+* Thu May  8 2025 Sjoerd Mullender <[email protected]>
+- It is now possible to specify an idle timeout using --set
+  idle_timeout=<seconds> (see mserver5 manual page) which gets triggered
+  if a connection to the server is idle (i.e. does not send any queries
+  to the server) while there is a SQL transaction active.
+
diff --git a/monetdb5/mal/mal_client.c b/monetdb5/mal/mal_client.c
--- a/monetdb5/mal/mal_client.c
+++ b/monetdb5/mal/mal_client.c
@@ -265,6 +265,7 @@ MCinitClientRecord(Client c, oid user, b
        c->querytimeout = 0;
        c->sessiontimeout = 0;
        c->logical_sessiontimeout = 0;
+       c->idletimeout = 0;
        c->qryctx.starttime = 0;
        c->qryctx.endtime = 0;
        ATOMIC_SET(&c->qryctx.datasize, 0);
@@ -399,6 +400,7 @@ MCcloseClient(Client c)
        c->qryctx.endtime = 0;
        c->sessiontimeout = 0;
        c->logical_sessiontimeout = 0;
+       c->idletimeout = 0;
        c->user = oid_nil;
        if (c->username) {
                GDKfree(c->username);
diff --git a/monetdb5/mal/mal_client.h b/monetdb5/mal/mal_client.h
--- a/monetdb5/mal/mal_client.h
+++ b/monetdb5/mal/mal_client.h
@@ -79,6 +79,7 @@ typedef struct CLIENT {
        lng maxmem;                                     /* max_memory from 
db_user_info table */
        lng sessiontimeout;                     /* session abort after x usec, 
0 = no limit */
        lng logical_sessiontimeout;     /* logical session timeout, client 
defined */
+       lng idletimeout;                        /* idle in active transaction 
timeout */
        lng querytimeout;                       /* timeout per query in usec, 0 
= no limit */
        QryCtx qryctx;                          /* per query limitations */
 
diff --git a/monetdb5/mal/mal_session.c b/monetdb5/mal/mal_session.c
--- a/monetdb5/mal/mal_session.c
+++ b/monetdb5/mal/mal_session.c
@@ -361,6 +361,7 @@ MSscheduleClient(str command, str peer, 
        c->protocol = protocol;
        c->blocksize = blocksize;
 
+       mnstr_settimeout(c->fdin->s, 50, is_exiting, NULL);
        if (c->initClient) {
                if ((msg = c->initClient(c, passwd, challenge, algo)) != 
MAL_SUCCEED) {
                        mnstr_printf(fout, "!%s\n", msg);
@@ -373,7 +374,6 @@ MSscheduleClient(str command, str peer, 
        }
        GDKfree(command);
 
-       mnstr_settimeout(c->fdin->s, 50, is_exiting, NULL);
        msg = MSserveClient(c);
        if (msg != MAL_SUCCEED) {
                freeException(msg);
diff --git a/sql/backends/monet5/sql_scenario.c 
b/sql/backends/monet5/sql_scenario.c
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -936,11 +936,37 @@ SQLtrans(mvc *m)
        return MAL_SUCCEED;
 }
 
+static bool
+shouldStop(void *data)
+{
+       if (GDKexiting())
+               return true;
+       Client c = data;
+       if (c) {
+               if (c->idletimeout &&
+                       c->idle &&
+                       c->sqlcontext &&
+                       ((backend *) c->sqlcontext)->mvc &&
+                       ((backend *) c->sqlcontext)->mvc->session &&
+                       ((backend *) c->sqlcontext)->mvc->session->tr &&
+                       ((backend *) c->sqlcontext)->mvc->session->tr->active &&
+                       time(NULL)- c->idle > c->idletimeout)
+                       return true;
+               if (c->sessiontimeout &&
+                       c->session &&
+                       (GDKusec() - c->session) > c->sessiontimeout)
+                       return true;
+       }
+       return false;
+}
+
 str
 SQLinitClient(Client c, const char *passwd, const char *challenge, const char 
*algo)
 {
        str msg = MAL_SUCCEED;
 
+       mnstr_settimeout(c->fdin->s, 50, shouldStop, c);
+       c->idletimeout = GDKgetenv_int("idle_timeout", 0);
        MT_lock_set(&sql_contextLock);
        if (!SQLstore) {
                MT_lock_unset(&sql_contextLock);
@@ -1192,6 +1218,21 @@ SQLreader(Client c, backend *be)
                MT_lock_unset(&mal_contextLock);
                return msg;
        }
+       if (msg == MAL_SUCCEED &&
+               c->idletimeout &&
+               c->idle &&
+               c->sqlcontext &&
+               ((backend *) c->sqlcontext)->mvc &&
+               ((backend *) c->sqlcontext)->mvc->session &&
+               ((backend *) c->sqlcontext)->mvc->session->tr &&
+               ((backend *) c->sqlcontext)->mvc->session->tr->active &&
+               GDKusec() - c->idle > c->idletimeout) {
+               in->pos = in->len;      /* skip rest of the input */
+               MT_lock_set(&mal_contextLock);
+               c->mode = FINISHCLIENT;
+               MT_lock_unset(&mal_contextLock);
+               throw(SQL, "SQLreader", "Session aborted due to idle timeout");
+       }
        MT_lock_set(&mal_contextLock);
        c->idle = 0;
        MT_lock_unset(&mal_contextLock);
diff --git a/tools/mserver/mserver5.1.in b/tools/mserver/mserver5.1.in
--- a/tools/mserver/mserver5.1.in
+++ b/tools/mserver/mserver5.1.in
@@ -510,6 +510,13 @@ therefore able to read and modify all da
 access to.  In addition, if the C code causes a crash, all bets are
 off.
 .TP
+\fBidle_timeout=\fP\fIseconds\fP
+Set the idle timeout.
+If there is an active transaction, and the client has not provided any
+input to the server for the specified amount of time, the server will
+close the connection and abort (rollback) the transaction.
+The default is \fB0\fP which means no timeout.
+.TP
 .B raw_strings=true
 The boolean option raw_strings controls how the sql scanner interprets string
 literals. If the value is
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to