[gamin] Make gamin sleep when nothing changes in the filesystem



Hi,

I'm working on Linux 2.6.15 with inotify support enabled, so I couldn't
understand why gam_server sometimes shows on "top" even if the machine is
idle and the filesystem doesn't change at all (at least in directories that
gamin clients may be interested in).
After running strace I found out that that gam_server wakes up tens times
per second (because of calling poll(2) with very short timeouts) when
nothing changes in the filesystem!

The attached patches (with included ChangeLog entries) fix this behaviour
by switching from static registrations of timeout functions to more dynamic
approach (executing timeout function that processes some queue makes sense
only if the queue is not empty).

gamin-inotify.diff:
Introduces dynamic handling for events_to_process, missing_list and
links_list.

gamin-connections.diff:
Dynamic handling of per-connection GamConnDataPtr->eq queue and detection
of idle period.
As a side effect this change improves idle detection mechanism. With this
patch the server quits if the connections queue is really empty for 30
seconds. Previously the timeout function was only "sampling" state of the
queue so it could miss a client connection shorter than 1 second.

gamin-pool-basic.diff:
Dynamic handling of lists of resources from gam_poll_generic.c used inside
gam_poll_basic.c. Registering gam_poll_basic_scan_callback statically makes
no sense because it seems that with inotify this code is not used at all
(anyway, the timeout function will be registered dynamically if needed).

Additionally I attached a simple patch (gamin-time-syscall.diff) that lets
you avoid calling time(2) syscall too often (twice per each stat(2) on
symlink or missing file).


Regards
Zbigniew

diff -rup gamin.orig/ChangeLog gamin/ChangeLog
--- gamin.orig/ChangeLog	2005-11-24 17:16:08.000000000 +0100
+++ gamin/ChangeLog	2006-01-17 20:21:36.000000000 +0100
@@ -0,0 +1,42 @@
+2006-01-17  Zbigniew Chyla  <mail zbigniew chyla pl>
+
+	* server/gam_connection.h:
+	(gam_connections_check): removed, now idle timeout is fully handled
+	inside server/gam_connection.c.
+	(gam_connections_init): return TRUE/FALSE instead of 0/-1; accept
+	with_idle_timeout parameter that turns on idle timeout handling.
+
+	* server/gam_server.c:
+	(gam_server_init): don't register timeout function for checking idle
+	connections, gam_connection.c will take care of this; call
+	gam_connections_init() passing negated value of no_timeout (derived
+	from "--notimeout" option) to it.
+
+	* server/gam_connection.c:
+	Added constants with periods of timeout functions (EQ_FLUSH_TIME for
+	gam_connection_eq_flush, MAX_IDLE_TIMEOUT for gam_idle_shutdown).
+	Added variable for storing id of the gam_idle_shutdown timeout
+	function in case it's registered (idle_shutdown_src_id).
+	Added boolean flag that enables shutting down the server on idle
+	timeout (idle_timeout_enabled)
+	(gam_connections_init): copy with_idle_timeout setting to
+	idle_timeout_enabled, in case the parameter is enabled, register
+	timeout function that shuts down the server (it's idle at startup).
+	(gam_connection_close): remove the timeout function conditionally,
+	i.e. only if it's registered (conn->eq_source != 0); in case the
+	connections list becomes empty and idle_timeout_enabled is TRUE,
+	register gam_idle_shutdown timeout function (unless it's already
+	registered).
+	(gam_connection_eq_flush): set conn->eq_source to 0 and return FALSE
+	to stop calling the function until registering it again (the
+	connection's event queue is currently empty).
+	(gam_connection_new): don't register gam_connection_eq_flush timeout
+	function, we'll register it on demand (when some event is added to
+	this connection's queue); in case gam_idle_shutdown timeout function
+	is registered, deregister it (the server is no longer idle).
+	(gam_queue_event): if gam_connection_eq_flush timeout function is
+	not registered yet, register it (we have events to push to a client)
+	(gam_connections_check): removed; we don't need to "sample" the
+	state of connections list any longer.
+	(gam_idle_shutdown): new timeout function that shuts down the server.
+
diff -rup gamin.orig/server/gam_connection.h gamin/server/gam_connection.h
--- gamin.orig/server/gam_connection.h	2005-08-04 21:08:38.000000000 +0200
+++ gamin/server/gam_connection.h	2006-01-16 20:22:49.000000000 +0100
@@ -23,9 +23,8 @@ typedef enum {
     GAM_STATE_CLOSED		/* the connection was closed by server */
 } GamConnState;
 
-int		gam_connections_init	(void);
+gboolean	gam_connections_init	(gboolean with_idle_timeout);
 int		gam_connections_close	(void);
-gboolean	gam_connections_check	(void);
 
 GamConnDataPtr	gam_connection_new	(GMainLoop *loop,
 					 GIOChannel *source);
diff -rup gamin.orig/server/gam_server.c gamin/server/gam_server.c
--- gamin.orig/server/gam_server.c	2005-09-21 18:21:05.000000000 +0200
+++ gamin/server/gam_server.c	2006-01-16 21:07:57.000000000 +0100
@@ -529,11 +529,10 @@ gam_server_init(GMainLoop * loop, const 
     g_io_add_watch(socket, G_IO_HUP | G_IO_NVAL | G_IO_ERR, gam_conn_error,
                    NULL);
 
-    /*
-     * Register the timeout checking function
-     */
-    if (no_timeout == 0)
-	g_timeout_add(1000, (GSourceFunc) gam_connections_check, NULL);
+    if (!gam_connections_init(!no_timeout)) {
+        GAM_DEBUG(DEBUG_INFO, "Could not initialize the connections system.\n");
+        return FALSE;
+    }
 #ifdef GAM_DEBUG_ENABLED
     g_timeout_add(1000, (GSourceFunc) gam_error_check, NULL);
 #endif
diff -rup gamin.orig/server/gam_connection.c gamin/server/gam_connection.c
--- gamin.orig/server/gam_connection.c	2005-09-22 10:10:55.000000000 +0200
+++ gamin/server/gam_connection.c	2006-01-16 21:26:53.000000000 +0100
@@ -26,8 +26,17 @@
  *									*
  ************************************************************************/
 
+#define EQ_FLUSH_TIME 100 /* 10 Hz */
+
+#define MAX_IDLE_TIMEOUT (30 * 1000)
+
+
 static GList *gamConnList;
 
+static guint idle_shutdown_src_id = 0;
+
+static gboolean idle_timeout_enabled = FALSE;
+
 struct GamConnData {
     GamConnState state;         /* the state for the connection */
     int fd;                     /* the file descriptor */
@@ -60,17 +69,23 @@ gam_reqtype_to_string (GAMReqType type)
 	return "";
 }
 
+static gboolean gam_idle_shutdown(gpointer userdata);
+
 /**
  * gam_connections_init:
  *
  * Initialize the connections data layer
  *
- * Returns 0 on success; -1 on failure
+ * Returns TRUE on success; FALSE on failure
  */
-int
-gam_connections_init(void)
+gboolean
+gam_connections_init(gboolean with_idle_timeout)
 {
-    return (0);
+    idle_timeout_enabled = with_idle_timeout;
+    if (idle_timeout_enabled) {
+        idle_shutdown_src_id = g_timeout_add(MAX_IDLE_TIMEOUT, gam_idle_shutdown, NULL);
+    }
+    return TRUE;
 }
 
 /**
@@ -105,7 +120,9 @@ gam_connection_close(GamConnDataPtr conn
     g_assert(conn->source);
 
     /* Kill the queue event source */
-    g_source_remove (conn->eq_source);
+    if (conn->eq_source != 0) {
+        g_source_remove (conn->eq_source);
+    }
     /* Flush the event queue */
     gam_eq_flush (conn->eq, conn);
     /* Kill the event queue */
@@ -122,6 +139,9 @@ gam_connection_close(GamConnDataPtr conn
 
     g_io_channel_unref(conn->source);
     gamConnList = g_list_remove(gamConnList, conn);
+    if (gamConnList == NULL && idle_timeout_enabled && idle_shutdown_src_id == 0) {
+        idle_shutdown_src_id = g_timeout_add(MAX_IDLE_TIMEOUT, gam_idle_shutdown, NULL);
+    }
     g_assert (!g_list_find(gamConnList, conn));
     g_free(conn->pidname);
     g_free(conn);
@@ -164,7 +184,10 @@ gam_connection_eq_flush (gpointer data)
 		return FALSE;
 
 	gam_eq_flush (conn->eq, conn);
-	return TRUE;
+
+	conn->eq_source = 0;
+
+	return FALSE;
 }
 
 /**
@@ -193,8 +216,12 @@ gam_connection_new(GMainLoop *loop, GIOC
     ret->loop = loop;
     ret->source = source;
     ret->eq = gam_eq_new ();
-    ret->eq_source = g_timeout_add (100 /* ms */, gam_connection_eq_flush, ret);
+    ret->eq_source = 0;
     gamConnList = g_list_prepend(gamConnList, ret);
+    if (idle_shutdown_src_id != 0) {
+        g_source_remove(idle_shutdown_src_id);
+        idle_shutdown_src_id = 0;
+    }
 
     GAM_DEBUG(DEBUG_INFO, "Created connection %d\n", ret->fd);
 
@@ -620,6 +647,10 @@ gam_queue_event(GamConnDataPtr conn, int
 	g_assert (conn->eq);
 
 	gam_eq_queue (conn->eq, reqno, event, path, len);
+
+	if (conn->eq_source == 0) {
+		conn->eq_source = g_timeout_add (EQ_FLUSH_TIME, gam_connection_eq_flush, conn);
+	}
 }
 
 
@@ -683,38 +714,22 @@ gam_send_ack(GamConnDataPtr conn, int re
  *									*
  ************************************************************************/
 
-#define MAX_IDLE_TIMEOUT 30
-
 /**
- * gam_connections_check:
+ * gam_idle_shutdown:
  *
- * This function can be called periodically by e.g. g_timeout_add and
- * shuts the server down if there have been no outstanding connections
- * for a while.
+ * This timeout function will be called if there have been no outstanding
+ * connections for MAX_IDLE_TIMEOUT milliseconds.
  */
-gboolean
-gam_connections_check(void)
+static gboolean
+gam_idle_shutdown(gpointer userdata)
 {
-    static time_t timeout;
-
-    if (g_list_first(gamConnList) != NULL) {
-        if (timeout != 0) {
-            GAM_DEBUG(DEBUG_INFO, "New active connection\n");
-        }
-        timeout = 0;
-        return (TRUE);
-    }
-    if (timeout == 0) {
-        GAM_DEBUG(DEBUG_INFO, "No more active connections\n");
-        timeout = time(NULL);
-    } else if (time(NULL) - timeout > MAX_IDLE_TIMEOUT) {
-        GAM_DEBUG(DEBUG_INFO, "Exiting on timeout\n");
-	gam_shutdown();
-        exit(0);
-    }
-    return (TRUE);
+    GAM_DEBUG(DEBUG_INFO, "Exiting on timeout\n");
+    gam_shutdown();
+    exit(0);
+    return FALSE;
 }
 
+
 /**
  * gam_connections_debug:
  *
diff -rup gamin.orig/ChangeLog gamin/ChangeLog
--- gamin.orig/ChangeLog	2005-11-24 17:16:08.000000000 +0100
+++ gamin/ChangeLog	2006-01-16 23:08:14.000000000 +0100
@@ -0,0 +1,30 @@
+2006-01-17  Zbigniew Chyla  <mail zbigniew chyla pl>
+
+	Register gam_inotify_scan_missing, gam_inotify_scan_links and
+	gam_inotify_process_event_queue timeouts on demand so that gamin
+	doesn't wake up if there's nothing to do.
+
+	* server/gam_inotify.c:
+	Added boolean flags (scan_missing_registered, scan_links_registered,
+	process_events_registered) that store current registration status of
+	..._scan_missing, ..._scan_links and ..._process_event_queue timeout
+	functions).
+	(gam_inotify_process_event_queue): set process_events_registered to
+	FALSE and return FALSE to stop calling the function until registering
+	it again.
+	(gam_inotify_read_handler): if there're some new events and 
+	..._process_event_queue timeout function is not registered yet,
+	register it.
+	(gam_inotify_init): don't register timeout functions statically,
+	we'll register them later on demand.
+	(gam_inotify_add_missing): if ..._scan_missing timeout function is
+	not registered yet, register it (missing_list is not empty)
+	(gam_inotify_scan_missing): if missing_list is empty after
+	processing, set scan_missing_registered to FALSE and return FALSE
+	to stop calling the function.
+	(gam_inotify_add_link): if ..._scan_links timeout function is not
+	registered yet, register it (links_list is not empty)
+	(gam_inotify_scan_links): if links_list is empty after processing,
+	set scan_links_registered to FALSE and return FALSE to stop calling
+	the function.
+
diff -rup gamin.orig/server/gam_inotify.c gamin/server/gam_inotify.c
--- gamin.orig/server/gam_inotify.c	2005-10-25 16:16:28.000000000 +0200
+++ gamin/server/gam_inotify.c	2006-01-16 21:28:19.000000000 +0100
@@ -117,10 +117,13 @@ typedef struct {
 static GHashTable *	path_hash = NULL;
 static GHashTable *	wd_hash = NULL;
 static GList *		missing_list = NULL;
+static gboolean		scan_missing_registered = FALSE;
 static GList *		links_list = NULL;
+static gboolean		scan_links_registered = FALSE;
 static GHashTable *	cookie_hash = NULL;
 static GQueue *		event_queue = NULL;
 static GQueue *		events_to_process = NULL;
+static gboolean		process_events_registered = FALSE;
 static GIOChannel *	inotify_read_ioc = NULL;
 static int		inotify_device_fd = -1;
 
@@ -674,7 +677,9 @@ gam_inotify_process_event_queue (gpointe
 		gam_inotify_event_free (event);
 	}
 
-	return TRUE;
+	process_events_registered = FALSE;
+
+	return FALSE;
 }
 
 static gboolean
@@ -698,6 +703,11 @@ gam_inotify_read_handler(gpointer user_d
                 events++;
         }
 
+        if (events > 0 && !process_events_registered) {
+                g_timeout_add (PROCESS_EVENTS_TIME, gam_inotify_process_event_queue, NULL);
+                process_events_registered = TRUE;
+        }
+
 	GAM_DEBUG(DEBUG_INFO, "inotify recieved %d events\n", events);
         return TRUE;
 }
@@ -967,9 +977,6 @@ gam_inotify_init(void)
     g_source_set_callback(source, gam_inotify_read_handler, NULL, NULL);
     g_source_attach(source, NULL);
     g_source_unref (source);
-    g_timeout_add (SCAN_MISSING_TIME, gam_inotify_scan_missing, NULL);
-    g_timeout_add (SCAN_LINKS_TIME, gam_inotify_scan_links, NULL);
-    g_timeout_add (PROCESS_EVENTS_TIME, gam_inotify_process_event_queue, NULL);
 
     path_hash = g_hash_table_new(g_str_hash, g_str_equal);
     wd_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -1153,6 +1160,11 @@ static void gam_inotify_add_missing (con
 	GAM_DEBUG (DEBUG_INFO, "inotify-missing: add - %s\n", path);
 
 	missing_list = g_list_prepend (missing_list, missing);
+
+	if (!scan_missing_registered) {
+		g_timeout_add (SCAN_MISSING_TIME, gam_inotify_scan_missing, NULL);
+		scan_missing_registered = TRUE;
+	}
 }
 
 static void gam_inotify_rm_missing (const char *path)
@@ -1264,7 +1278,10 @@ static gboolean gam_inotify_scan_missing
 	}
 
 	gam_inotify_sanity_check ();
-	return TRUE;
+
+	scan_missing_registered = (missing_list != NULL);
+
+	return scan_missing_registered;
 }
 
 
@@ -1375,6 +1392,11 @@ gam_inotify_add_link (const char *path)
 	lstat(path, &sbuf);
 	links->sbuf = sbuf;
 	links_list = g_list_prepend (links_list, links);
+
+	if (!scan_links_registered) {
+		g_timeout_add (SCAN_LINKS_TIME, gam_inotify_scan_links, NULL);
+		scan_links_registered = TRUE;
+	}
 }
 
 static void
@@ -1431,7 +1455,10 @@ gam_inotify_scan_links (gpointer userdat
 	}
 
 	gam_inotify_sanity_check ();
-	return TRUE;
+
+	scan_links_registered = (links_list != NULL);
+
+	return scan_links_registered;
 }
 
 static gboolean
diff -rup gamin.orig/ChangeLog gamin/ChangeLog
--- gamin.orig/ChangeLog	2005-11-24 17:16:08.000000000 +0100
+++ gamin/ChangeLog	2006-01-17 22:43:09.000000000 +0100
@@ -0,0 +1,31 @@
+2006-01-17  Zbigniew Chyla  <mail zbigniew chyla pl>
+
+	* server/gam_poll_generic.h:
+	(gam_pool_generic_set_notify_nonempty_list_callback): added new
+	function declaration.
+	* server/gam_poll_generic.c:
+	(notify_nonempty_list_callback): added static variable that stores a
+	pointer to function called when some of the internal lists of
+	resources becomes non-empty.
+	(gam_pool_generic_set_notify_nonempty_list_callback): added public
+	function for setting notify_nonempty_list_callback.
+	(gam_poll_generic_add_missing, gam_poll_generic_add_busy,
+	gam_poll_generic_add): if the list was empty before adding the
+	element and notify_nonempty_list_callback is not NULL, call a
+	function that it points to.
+	* server/gam_poll_basic.c:
+	Added boolean flag (scan_callback_registered) that informs whether
+	gam_poll_basic_scan_callback timeout function is registered.
+	(register_scan_callback): added function to call when some of lists
+	of resources from gamin_pool_generic.c becomes non-empty, it
+	registers gam_poll_basic_scan_callback timeout function (unless it's
+	already registered)
+	(gam_poll_basic_init): don't register gam_poll_basic_scan_callback
+	timeout function, instead set register_scan_callback as a function
+	to call when calling gam_poll_basic_scan_callback makes sense, i.e.
+	when some of resources lists it's interested to becomes non-empty.
+	(gam_poll_basic_scan_callback): return TRUE only if ..._all_list
+	or ..._missing_list is non-empty, otherwise wasting time for calling
+	this function again doesn't make sense (it will be re-registered
+	when needed).
+
diff -rup gamin.orig/server/gam_poll_generic.h gamin/server/gam_poll_generic.h
--- gamin.orig/server/gam_poll_generic.h	2005-08-15 21:34:58.000000000 +0200
+++ gamin/server/gam_poll_generic.h	2006-01-17 22:36:58.000000000 +0100
@@ -8,6 +8,7 @@
 G_BEGIN_DECLS
 
 gboolean	gam_poll_generic_init			(void);
+void		gam_pool_generic_set_notify_nonempty_list_callback(GVoidFunc cb);
 void		gam_poll_generic_debug			(void);
 
 void		gam_poll_generic_add_missing	(GamNode * node);
diff -rup gamin.orig/server/gam_poll_generic.c gamin/server/gam_poll_generic.c
--- gamin.orig/server/gam_poll_generic.c	2005-08-22 18:30:29.000000000 +0200
+++ gamin/server/gam_poll_generic.c	2006-01-17 22:40:04.000000000 +0100
@@ -48,6 +48,11 @@ static GList *		all_resources = NULL;
 static GList *		dead_resources = NULL;
 static time_t		current_time = 0;
 
+// this function is called after adding an element to one of the above list
+// if the list was empty before
+static GVoidFunc notify_nonempty_list_callback = NULL;
+
+
 gboolean
 gam_poll_generic_init()
 {
@@ -56,6 +61,19 @@ gam_poll_generic_init()
 	return TRUE;
 }
 
+/**
+ * gam_pool_generic_set_notify_nonempty_list_callback:
+ * @cb: callback function
+ *
+ * Sets the function that will be called every time one of the resources lists
+ * changes its state from empty to non-empty.
+ */
+void
+gam_pool_generic_set_notify_nonempty_list_callback(GVoidFunc cb)
+{
+	notify_nonempty_list_callback = cb;
+}
+
 static void
 gam_poll_debug_node(GamNode * node, gpointer user_data)
 {
@@ -100,8 +118,12 @@ void
 gam_poll_generic_add_missing(GamNode * node)
 {
 	if (g_list_find(missing_resources, node) == NULL) {
+		GList *old_missing_resources = missing_resources;
 		missing_resources = g_list_prepend(missing_resources, node);
 		GAM_DEBUG(DEBUG_INFO, "Poll: adding missing node %s\n", gam_node_get_path(node));
+		if (old_missing_resources == NULL && notify_nonempty_list_callback != NULL) {
+			notify_nonempty_list_callback();
+		}
 	}
 }
 
@@ -133,8 +155,12 @@ void
 gam_poll_generic_add_busy(GamNode * node)
 {
 	if (g_list_find(busy_resources, node) == NULL) {
+		GList *old_busy_resources = busy_resources;
 		busy_resources = g_list_prepend(busy_resources, node);
 		GAM_DEBUG(DEBUG_INFO, "Poll: adding busy node %s\n", gam_node_get_path(node));
+		if (old_busy_resources == NULL && notify_nonempty_list_callback != NULL) {
+			notify_nonempty_list_callback();
+		}
 	}
 }
 
@@ -159,8 +185,12 @@ gam_poll_generic_add (GamNode * node)
 {
 	if (g_list_find (all_resources, node) == NULL)
 	{
+		GList *old_all_resources = all_resources;
 		all_resources = g_list_prepend(all_resources, node);
 		GAM_DEBUG(DEBUG_INFO, "Poll: Adding node %s\n", gam_node_get_path (node));
+		if (old_all_resources == NULL && notify_nonempty_list_callback != NULL) {
+			notify_nonempty_list_callback();
+		}
 	}
 }
 
diff -rup gamin.orig/server/gam_poll_basic.c gamin/server/gam_poll_basic.c
--- gamin.orig/server/gam_poll_basic.c	2005-08-22 18:30:29.000000000 +0200
+++ gamin/server/gam_poll_basic.c	2006-01-17 22:36:58.000000000 +0100
@@ -46,17 +46,29 @@ static gboolean gam_poll_basic_remove_al
 static GaminEventType gam_poll_basic_poll_file(GamNode * node);
 static gboolean gam_poll_basic_scan_callback(gpointer data);
 
+#define SCAN_CALLBACK_TIME 1000
+
+static gboolean scan_callback_registered = FALSE;
+
+static void
+register_scan_callback()
+{
+	if (!scan_callback_registered) {
+		g_timeout_add(SCAN_CALLBACK_TIME, gam_poll_basic_scan_callback, NULL);
+		scan_callback_registered = TRUE;
+	}
+}
+
 gboolean
 gam_poll_basic_init ()
 {
 	gam_poll_generic_init ();
+	gam_pool_generic_set_notify_nonempty_list_callback(register_scan_callback);
 	gam_server_install_poll_hooks (GAMIN_P_BASIC,
 				       gam_poll_basic_add_subscription,
 				       gam_poll_basic_remove_subscription,
 				       gam_poll_basic_remove_all_for,
 				       gam_poll_basic_poll_file);
-
-	g_timeout_add(1000, gam_poll_basic_scan_callback, NULL);
 	GAM_DEBUG(DEBUG_INFO, "basic poll backend initialized\n");
 	return TRUE;
 }
@@ -412,5 +424,8 @@ gam_poll_basic_scan_callback(gpointer da
 		}
 	}
 
-	return TRUE;
+	scan_callback_registered = gam_poll_generic_get_all_list() != NULL
+	                           || gam_poll_generic_get_missing_list() != NULL;
+
+	return scan_callback_registered;
 }
diff -rup gamin.orig/ChangeLog gamin/ChangeLog
--- gamin.orig/ChangeLog	2005-11-24 17:16:08.000000000 +0100
+++ gamin/ChangeLog	2006-01-16 23:15:24.000000000 +0100
@@ -0,0 +1,7 @@
+2006-01-17  Zbigniew Chyla  <mail zbigniew chyla pl>
+
+	* server/gam_inotify.c:
+	(gam_inotify_scan_missing, gam_inotify_scan_links): avoid using
+	time() syscall too often (twice per loop iteration!) - read the
+	current time before entering the loop and keep it in local variable.
+
diff -rup gamin.orig/server/gam_inotify.c gamin/server/gam_inotify.c
--- gamin.orig/server/gam_inotify.c	2005-10-25 16:16:28.000000000 +0200
+++ gamin/server/gam_inotify.c	2006-01-16 21:28:19.000000000 +0100
@@ -1238,6 +1250,8 @@ static gboolean gam_inotify_scan_missing
 	guint i;
 
 	gam_inotify_sanity_check ();
+
+	time_t now = time(NULL);
 	/* We have to walk the list like this because entries might be removed while we walk the list */
 	for (i = 0; ; i++)
 	{
@@ -1247,10 +1261,10 @@ static gboolean gam_inotify_scan_missing
 			break;
 
 		/* Not enough time has passed since the last scan */
-		if (time(NULL) - missing->last_scan_time < missing->scan_interval)
+		if (now - missing->last_scan_time < missing->scan_interval)
 			continue;
 		
-		missing->last_scan_time = time(NULL);
+		missing->last_scan_time = now;
 		if (!gam_inotify_is_missing (missing->path))
 		{
 			if (gam_inotify_nolonger_missing (missing->path))
@@ -1405,6 +1427,8 @@ gam_inotify_scan_links (gpointer userdat
 	guint i;
 
 	gam_inotify_sanity_check ();
+
+	time_t now = time(NULL);
 	/* We have to walk the list like this because entries might be removed while we walk the list */
 	for (i = 0; ; i++)
 	{
@@ -1414,10 +1438,10 @@ gam_inotify_scan_links (gpointer userdat
 			break;
 
 		/* Not enough time has passed since the last scan */
-		if (time(NULL) - links->last_scan_time < links->scan_interval)
+		if (now - links->last_scan_time < links->scan_interval)
 			continue;
 		
-		links->last_scan_time = time(NULL);
+		links->last_scan_time = now;
 		if (!gam_inotify_is_link (links->path))
 		{
 			if (gam_inotify_nolonger_link (links->path))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]