[pisa-src] r1232 - in trunk: include/conmgr.h libpisa/conmgr.c pisacd/cdderegister.c pisacd/cdmain.c pisacd/cdregister.c pisacd/cdtimeout.c pisacd/cdtun.c

  • From: Thomas Jansen <mithi@xxxxxxxxx>
  • To: pisa-src@xxxxxxxxxxxxx
  • Date: Mon, 19 Oct 2009 15:07:27 +0200

Author: tjansen
Date: Mon Oct 19 15:07:26 2009
New Revision: 1232

Log:
Rewrote timeout handling.

Instead of relying on a central function checking all connections, we have
individual tasks for each connection now. This means that we don't check for
connections in the disconnected state and don't wake up for timeout checks on
idle systems at all.

The change benefits performance, as we no longer store the exact time the last
packet was transfered but only a flag, _if_ a packet was transfered since the
last check. If the flag is set, we wait for the delay again until we check for
a timeout. This changes the semantics of the delay from an absolute time to a
iguaranteed minimum time the connection is kept open after the last packet was
transfered.

Modified:
   trunk/include/conmgr.h
   trunk/libpisa/conmgr.c
   trunk/pisacd/cdderegister.c
   trunk/pisacd/cdmain.c
   trunk/pisacd/cdregister.c
   trunk/pisacd/cdtimeout.c
   trunk/pisacd/cdtun.c

Modified: trunk/include/conmgr.h
==============================================================================
--- trunk/include/conmgr.h      Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/include/conmgr.h      Mon Oct 19 15:07:26 2009        (r1232)
@@ -20,6 +20,7 @@
 #include "global.h"
 #include "time.h"
 #include "packet.h"
+#include "scheduler.h"
 
 typedef enum {
        PISA_CON_DISCONNECTED = 1,
@@ -66,10 +67,14 @@
        time_t timeout_heartbeat;
 
        /**
-        * Last time the client sent data. The client will disconnect if a
-        * connection wasn't used for a while.
+        * 0 if no data was transfered since last check, 1 otherwise.
         */
-       time_t timeout_client;
+       int timeout_flag;
+
+       /**
+        * Current task for the timeout
+        */
+       pisa_sched_task *timeout_task;
 
        /** Hash handles for the different keys. Provided by uthash.h. */
        UT_hash_handle hh;

Modified: trunk/libpisa/conmgr.c
==============================================================================
--- trunk/libpisa/conmgr.c      Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/libpisa/conmgr.c      Mon Oct 19 15:07:26 2009        (r1232)
@@ -148,7 +148,8 @@
        entry->control_port = ctrl_port;
        pisa_ipv6_copy(&entry->hit, hit);
        time(&entry->timeout_heartbeat);
-       time(&entry->timeout_client);
+       entry->timeout_flag = 0;
+       entry->timeout_task = NULL;
        entry->status = PISA_CON_DISCONNECTED;
 
        HASH_ADD_KEYPTR(hh, conlist->hash_ipv6, &entry->hit,
@@ -206,6 +207,8 @@
                HASH_DELETE(hh_ipv4, conlist->hash_ipv4, entry);
        if (conlist->connection_remove_callback != NULL)
                conlist->connection_remove_callback(entry);
+       if (entry->timeout_task)
+               pisa_sched_remove(entry->timeout_task);
        pisa_conmgr_free(entry);
 }
 

Modified: trunk/pisacd/cdderegister.c
==============================================================================
--- trunk/pisacd/cdderegister.c Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/pisacd/cdderegister.c Mon Oct 19 15:07:26 2009        (r1232)
@@ -28,6 +28,9 @@
        if (entry == cd_ctx.defaultroute)
                pisa_remove_default_route();
        entry->status = PISA_CON_DISCONNECTED;
+
+       pisa_sched_remove(entry->timeout_task);
+       entry->timeout_task = NULL;
 }
 
 /**

Modified: trunk/pisacd/cdmain.c
==============================================================================
--- trunk/pisacd/cdmain.c       Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/pisacd/cdmain.c       Mon Oct 19 15:07:26 2009        (r1232)
@@ -279,8 +279,6 @@
        pisa_sched_init(cd_ctx.fd_scheduler);
        pisa_sched_add_now(pisa_task_heartbeat, NULL);
        pisa_sched_add_now(pisa_task_pending, NULL);
-       if (cd_cfg.idle_disconnect_delay > 0)
-               pisa_sched_add_now(pisa_task_timeout, NULL);
 }
 
 static void cd_deinit(void)

Modified: trunk/pisacd/cdregister.c
==============================================================================
--- trunk/pisacd/cdregister.c   Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/pisacd/cdregister.c   Mon Oct 19 15:07:26 2009        (r1232)
@@ -15,6 +15,7 @@
 #include "cdctx.h"
 #include "cdconf.h"
 #include "cdpending.h"
+#include "cdtimeout.h"
 
 /**
  * Handle a pending request of type REGISTER:
@@ -126,6 +127,7 @@
        char buffer[INET6_ADDRSTRLEN];
        pisa_pending *pend;
        pisa_conmgr_entry *entry;
+       struct timeval delay;
 
        entry = pisa_conmgr_findby_address(cd_ctx.conlist, &addr->sin6_addr);
        if (entry == NULL) {
@@ -154,7 +156,12 @@
                cd_ctx.defaultroute = entry;
        }
 
-       time(&entry->timeout_client);
+       /* Start the timeout task. */
+       entry->timeout_flag = 0;
+       delay.tv_sec = cd_cfg.idle_disconnect_delay;
+       delay.tv_usec = 0;
+       entry->timeout_task = pisa_sched_add(pisa_task_timeout, &delay, entry);
+
        inet_ntop(AF_INET6, &addr->sin6_addr, buffer, sizeof(buffer));
        PISA_DEBUG(PL_REGISTER, "Connected to PISA server %s\n", buffer);
 

Modified: trunk/pisacd/cdtimeout.c
==============================================================================
--- trunk/pisacd/cdtimeout.c    Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/pisacd/cdtimeout.c    Mon Oct 19 15:07:26 2009        (r1232)
@@ -6,7 +6,6 @@
 /**
  * @file cdtimeout.c
  * @brief Timeout checking task for the PISA client daemon.
- * @author Wolfram Fischer <papierfalter@xxxxxxxxx>
  * @author Thomas Jansen <mithi@xxxxxxxxx>
  * @date Oct. 2009
  */
@@ -16,41 +15,46 @@
 #include "cdderegister.h"
 #include "scheduler.h"
 
-/* TODO: Start an update task for each connection.
- *       Get rid of entry->timeout_client */
-
 /**
- * Check if a connection was idle for too long and disconnect.
- * @param data  pointer to the current time (only provided this way to avoid
- *             having to call time() several times)
- * @param entry  entry connection which is to be examined
+ * Check if a connection has been idle for too long and disconnect.
+ * We guarantee to keep the connection open for at least
+ * cd_cfg.idle_disconnect_delay seconds after the last data packet. Depending
+ * on where in the window data transfer stops, the delay until we actually
+ * disconnect may be twice that time.
  */
-static void pisa_cd_check_timeout(void* data, pisa_conmgr_entry* entry)
+void pisa_task_timeout(void *data)
 {
-       char buffer[INET6_ADDRSTRLEN];
-       time_t currentTime = *((time_t*)data);
+       struct timeval delay;
+       pisa_conmgr_entry *e = (pisa_conmgr_entry *)data;
 
-       /* We do not want to drop our relay connection */
-       if (entry->type == PISA_CONTYPE_RELAY)
+       /* This event is being processed and therefore removed from the queue,
+        * delete the reference. */
+       e->timeout_task = NULL;
+
+       /* We do not want to drop our relay connection.
+        * Note that we don't reschedule in that case. */
+       if (e->type == PISA_CONTYPE_RELAY)
                return;
 
-       if ((entry->timeout_client + cd_cfg.idle_disconnect_delay) < 
currentTime) {
-               inet_ntop(AF_INET6, &entry->hit, buffer, sizeof(buffer));
+       /* Wait for 5 seconds if we do not currently have a disconnect delay,
+        * because it could be changed in the future. */
+       delay.tv_usec = 0;
+       if (cd_cfg.idle_disconnect_delay != 0)
+               delay.tv_sec = cd_cfg.idle_disconnect_delay;
+       else
+               delay.tv_sec = 5;
+
+       /* Disconnect if no activity took place since the last time we
+        * checked. Not that we don't reschedule in that case. */
+       if (e->timeout_flag == 0 && cd_cfg.idle_disconnect_delay > 0) {
+               char buffer[INET6_ADDRSTRLEN];
+               inet_ntop(AF_INET6, &e->hit, buffer, sizeof(buffer));
                PISA_INFO("Removing idle connection to %s\n", buffer);
-               pisa_client_disconnect_from_server(NULL, entry);
+               pisa_client_disconnect_from_server(NULL, e);
+               return;
        }
-}
-
-/**
- * Disconnect idle connections. Checked every second.
- */
-void pisa_task_timeout(void *data)
-{
-       struct timeval delay = {1, 0};
-       time_t current;
-
-       time(&current);
-       pisa_conmgr_iterate_connected(cd_ctx.conlist, pisa_cd_check_timeout, 
&current);
 
-       pisa_sched_add(pisa_task_timeout, &delay, NULL);
+       /* Reset the timeout flag and reschedule */
+       e->timeout_flag = 0;
+       e->timeout_task = pisa_sched_add(pisa_task_timeout, &delay, e);
 }

Modified: trunk/pisacd/cdtun.c
==============================================================================
--- trunk/pisacd/cdtun.c        Mon Oct 19 13:28:00 2009        (r1231)
+++ trunk/pisacd/cdtun.c        Mon Oct 19 15:07:26 2009        (r1232)
@@ -82,7 +82,7 @@
                        /* Keep track of the last time this connection was
                         * used. Disconnect after a timeout to save
                         * resources. */
-                       time(&entry->timeout_client);
+                       entry->timeout_flag = 1;
 
                        PISA_DEBUG(PL_DATA, "remote -> local: %i bytes\n", len 
- 6);
                }
@@ -166,7 +166,7 @@
                        /* Keep track of the last time this connection was
                         * used. Disconnect after a timeout to save
                         * resources. */
-                       time(&entry->timeout_client);
+                       entry->timeout_flag = 1;
 
                        PISA_DEBUG(PL_DATA, "local -> remote: %i bytes\n", len);
                }

Other related posts:

  • » [pisa-src] r1232 - in trunk: include/conmgr.h libpisa/conmgr.c pisacd/cdderegister.c pisacd/cdmain.c pisacd/cdregister.c pisacd/cdtimeout.c pisacd/cdtun.c - Thomas Jansen