[gamin] support for inotify 0.18



yo,

here is a patch that updates inotify support to 0.18. the patch has four
distinct bits.

	1) fix for new inotify read loop.
	2) performance boost by using FIONREAD and grabbing all events at once
instead of one at a time.
	3) update gamin internal inotify header.
	4) general cleanup.

compile tested only.

-- 
John McCutchan <ttb tentacle dhs org>
? Makefile
? Makefile.in
? aclocal.m4
? autom4te.cache
? config.h
? config.h.in
? config.log
? config.status
? configure
? gamin.pc
? gamin.spec
? libtool
? stamp-h1
? doc/Makefile
? doc/Makefile.in
? lib/Makefile
? lib/Makefile.in
? libgamin/Makefile
? libgamin/Makefile.in
? libgamin/gam_error.c
? libgamin/gam_event.c
? libgamin/gamin
? python/Makefile
? python/Makefile.in
? server/Makefile
? server/Makefile.in
? server/gam_server
? tests/Makefile
? tests/Makefile.in
? tests/testgam
Index: server/gam_inotify.c
===================================================================
RCS file: /cvs/gnome/gamin/server/gam_inotify.c,v
retrieving revision 1.10
diff -u -r1.10 gam_inotify.c
--- server/gam_inotify.c	26 Jan 2005 09:27:23 -0000	1.10
+++ server/gam_inotify.c	27 Jan 2005 05:33:31 -0000
@@ -15,8 +15,11 @@
  * License along with this library; if not, write to the Free
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * TODO:
- * 	Handle removal of subscriptions when we get IGNORE event
- * 	The dnotify/poll hybrid backend produces more events
+ * 	- *properly* Handle removal of subscriptions when we get IGNORE event
+ * 	- this backend does not produce the same events as the dnotify/poll backend.
+ * 	for example, the dp backend allows for watching non-exist files/folders, 
+ * 	and be notified when they are created. there are more places where
+ * 	the events are not consistent.
  */
 
 
@@ -61,7 +64,6 @@
 
 static gboolean have_consume_idler = FALSE;
 
-
 int fd = -1; // the device fd
 
 static INotifyData *
@@ -117,8 +119,8 @@
 	iwr.dirname = g_strdup(path);
 	iwr.mask = 0xffffffff; // all events
 
-        wd = ioctl(fd, INOTIFY_WATCH,&iwr);
-        g_free(iwr.dirname);	
+        wd = ioctl(fd, INOTIFY_WATCH, &iwr);
+        g_free(iwr.dirname);
 
         if (wd < 0) {
             G_UNLOCK(inotify);
@@ -130,7 +132,7 @@
         g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), data);
         g_hash_table_insert(path_hash, data->path, data);
 
-        GAM_DEBUG(DEBUG_INFO, "activated INotify for %s\n", path);
+        GAM_DEBUG(DEBUG_INFO, "added inotify watch for %s\n", path);
 
 	gam_server_emit_event (path, 0, GAMIN_EVENT_EXISTS, subs, 1);
 	gam_server_emit_event (path, 0, GAMIN_EVENT_ENDEXISTS, subs, 1);
@@ -146,25 +148,22 @@
 		data->subs = g_list_remove_all (data->subs, sub);
 	}
         data->refcount--;
-	    GAM_DEBUG(DEBUG_INFO, "inotify decremeneted refcount\n");
+	    GAM_DEBUG(DEBUG_INFO, "inotify decremeneted refcount for %s\n", path);
 
         if (data->refcount == 0) {
             r = ioctl (fd, INOTIFY_IGNORE, &data->wd); 
 	    if (r < 0) {
-                GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s\n", data->path);
+                GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
             }
-            GAM_DEBUG(DEBUG_INFO, "deactivated INotify for %s\n",
-                      data->path);
+            GAM_DEBUG(DEBUG_INFO, "removed inotify watch for %s\n", data->path);
             g_hash_table_remove(path_hash, data->path);
             g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
             gam_inotify_data_free(data);
         }
     }
-
     G_UNLOCK(inotify);
 }
 
-
 static GaminEventType inotify_event_to_gamin_event (int mask) 
 {
 	switch (mask)
@@ -187,6 +186,7 @@
 			return GAMIN_EVENT_UNKNOWN;
 	}
 }
+
 static void gam_inotify_emit_event (INotifyData *data, struct inotify_event *event)
 {
 	GaminEventType gevent;
@@ -196,92 +196,103 @@
 		return;
 
 	gevent = inotify_event_to_gamin_event (event->mask);
-	// we got some event that GAMIN doesn't understand
+
+	// gamins event vocabulary is very small compared to inotify
+	// so we often will receieve events that have no equivelant 
+	// in gamin
 	if (gevent == GAMIN_EVENT_UNKNOWN) {
-		GAM_DEBUG(DEBUG_INFO, "inotify_emit_event got unknown event %x\n", event->mask);
 		return;
 	}
 
 	if (event->filename[0] != '\0') {
 		int pathlen = strlen(data->path);
-		GAM_DEBUG(DEBUG_INFO, "Got filename with event\n");
 		if (data->path[pathlen-1] == '/') {
 			event_path = g_strconcat (data->path, event->filename, NULL);
 		} else {
 			event_path = g_strconcat (data->path, "/", event->filename, NULL);
 		}
 	} else {
-		GAM_DEBUG(DEBUG_INFO, "Got no filename with event\n");
 		event_path = g_strdup (data->path);
 	}
 
-	GAM_DEBUG(DEBUG_INFO, "gam_inotify_emit_event() %s\n", event_path);
+	GAM_DEBUG(DEBUG_INFO, "inotify emitting event %s for %s\n", gam_event_to_string(gevent) , event_path);
 
 	gam_server_emit_event (event_path, 0, gevent, data->subs, 1);
 }
 
 static gboolean
-gam_inotify_read_handler(gpointer user_data)
+gam_inotify_read_handler (gpointer user_data)
 {
-    char buffer[sizeof(struct inotify_event) + INOTIFY_FILENAME_MAX];
-    struct inotify_event *event;
-    INotifyData *data;
+    char *buffer;
+    int buffer_size;
+    gsize buffer_i;
+    gsize read_size;
 
-    GAM_DEBUG(DEBUG_INFO, "gam_inotify_read_handler()\n");
     G_LOCK(inotify);
 
-    if (g_io_channel_read_chars(inotify_read_ioc, buffer, sizeof(struct inotify_event), NULL, NULL) != G_IO_STATUS_NORMAL) {
+    buffer_size = ioctl(fd, FIONREAD);
+
+    buffer = g_malloc(buffer_size);
+
+
+    if (g_io_channel_read_chars(inotify_read_ioc, (char *)buffer, buffer_size, &read_size, NULL) != G_IO_STATUS_NORMAL) {
 	G_UNLOCK(inotify);
-        GAM_DEBUG(DEBUG_INFO, "gam_inotify_read_handler failed\n");
+        GAM_DEBUG(DEBUG_INFO, "inotify failed to read events from inotify fd.\n");
 	return FALSE;
     }
-    event = (struct inotify_event *)buffer;
-    if (event->len > 0) {
-        if ((event->len > INOTIFY_FILENAME_MAX) ||
-            (g_io_channel_read_chars(inotify_read_ioc, event->filename, event->len, NULL, NULL) != G_IO_STATUS_NORMAL)) {
-	    G_UNLOCK(inotify);
-            GAM_DEBUG(DEBUG_INFO, "gam_inotify_read_handler failed\n");
-	    return FALSE;
-        }
-    } else {
-        event->filename[0] = '\0';
-    }
 
-    /* When we get an ignore event, we 
-     * remove all the subscriptions for this wd
-     */
-    if (event->mask == IN_IGNORED) {
-	    GList *l;
-	    data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd));
+    buffer_i = 0;
+    while (buffer_i < read_size) {
+	struct inotify_event *bevent, *event;
+	gsize event_size;
+
+	bevent = (struct inotify_event *)&buffer[buffer_i];
+	event_size = sizeof(struct inotify_event) + bevent->len;
+	event = g_malloc(event_size);
+	g_memmove (event, bevent, event_size);
+
+	/* Do the shit with the event */
+	{
+	    if (event->mask == IN_IGNORED) {
+		GList *l;
+		INotifyData *data;
+		data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd));
 
-	    if (!data) {
+		if (!data) {
 		    G_UNLOCK(inotify);
 		    return TRUE;
 		}
 
-	    l = data->subs;
-	    data->subs = NULL;
-	    for (l = l; l; l = l->next) {
+		l = data->subs;
+		data->subs = NULL;
+		for (l = l; l; l = l->next) {
 		    GamSubscription *sub = l->data;
 		    gam_inotify_remove_subscription (sub);
-	    }
-	    G_UNLOCK(inotify);
-	    return TRUE;
-    }
+		}
 
-    data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd));
+		G_UNLOCK(inotify);
+		return TRUE;
+	    } else {
+		INotifyData *data;
 
-    if (!data) {
-	GAM_DEBUG(DEBUG_INFO, "Could not find WD %d in hash\n", event->wd);
-        G_UNLOCK(inotify);
-        return TRUE;
-    }
+		data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd));
+		
+		if (!data) {
+		    GAM_DEBUG(DEBUG_INFO, "inotify can't find wd %d\n", event->wd);
+		    GAM_DEBUG(DEBUG_INFO, "weird things have happened to inotify.\n");
+		    G_UNLOCK(inotify);
+		    return TRUE;
+		}
+
+		gam_inotify_emit_event (data, event);
+
+	    }
 
-    gam_inotify_emit_event (data, event);
+	}
 
-    GAM_DEBUG(DEBUG_INFO, "gam_inotify event for %s (%x) %s\n", data->path, event->mask, event->filename);
+	buffer_i += event_size;
 
-    GAM_DEBUG(DEBUG_INFO, "gam_inotify_read_handler() done\n");
+    }
 
     G_UNLOCK(inotify);
 
@@ -347,9 +358,9 @@
 }
 
 /**
- * @defgroup INotify INotify Backend
+ * @defgroup inotify inotify backend
  * @ingroup Backends
- * @brief INotify backend API
+ * @brief inotify backend API
  *
  * Since version 2.6.X, Linux kernels have included the Linux Inode
  * Notification system (inotify).  This backend uses inotify to know when


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