]> git.pld-linux.org Git - packages/gamin.git/blame - gamin-inotify-redux-3.patch
- 0.1.0, inotify-redux-3 patch removed (included in sources)
[packages/gamin.git] / gamin-inotify-redux-3.patch
CommitLineData
99960865 1Index: server/gam_debugging.h
2===================================================================
3RCS file: /cvs/gnome/gamin/server/gam_debugging.h,v
4retrieving revision 1.2
5diff -u -r1.2 gam_debugging.h
6--- server/gam_debugging.h 23 Mar 2005 09:50:11 -0000 1.2
7+++ server/gam_debugging.h 14 Apr 2005 16:44:34 -0000
8@@ -12,7 +12,12 @@
9 GAMDnotifyDelete=2,
10 GAMDnotifyChange=3,
11 GAMDnotifyFlowOn=4,
12- GAMDnotifyFlowOff=5
13+ GAMDnotifyFlowOff=5,
14+ GAMinotifyCreate=6,
15+ GAMinotifyDelete=7,
16+ GAMinotifyChange=8,
17+ GAMinotifyFlowOn=9,
18+ GAMinotifyFlowOff=10
19 } GAMDebugEvent;
20
21 void gam_debug_add(GamConnDataPtr conn, const char *value, int options);
22Index: server/gam_inotify.c
23===================================================================
24RCS file: /cvs/gnome/gamin/server/gam_inotify.c,v
25retrieving revision 1.17
26diff -u -r1.17 gam_inotify.c
27--- server/gam_inotify.c 7 Apr 2005 09:11:17 -0000 1.17
28+++ server/gam_inotify.c 14 Apr 2005 16:44:34 -0000
29@@ -1,5 +1,8 @@
30-/*
31- * Copyright (C) 2004 John McCutchan, James Willcox, Corey Bowers
32+/* gamin inotify backend
33+ * Copyright (C) 2005 John McCutchan
34+ *
35+ * Based off of code,
36+ * Copyright (C) 2003 James Willcox, Corey Bowers
37 *
38 * This library is free software; you can redistribute it and/or
39 * modify it under the terms of the GNU Lesser General Public
40@@ -14,261 +17,404 @@
41 * You should have received a copy of the GNU Lesser General Public
42 * License along with this library; if not, write to the Free
43 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44- * TODO:
45- * - *properly* Handle removal of subscriptions when we get IGNORE event
46- * - this backend does not produce the same events as the dnotify/poll backend.
47- * for example, the dp backend allows for watching non-exist files/folders,
48- * and be notified when they are created. there are more places where
49- * the events are not consistent.
50 */
51
52
53 #include <config.h>
54 #define _GNU_SOURCE
55 #include <fcntl.h>
56-#include <sys/ioctl.h>
57 #include <signal.h>
58 #include <unistd.h>
59+#include <sys/ioctl.h>
60 #include <stdio.h>
61-#include <string.h>
62 #include <glib.h>
63+#include "gam_error.h"
64+#include "gam_poll.h"
65 #ifdef HAVE_LINUX_INOTIFY_H
66 #include <linux/inotify.h>
67 #else
68 #include "local_inotify.h"
69 #endif
70-#include "gam_error.h"
71 #include "gam_inotify.h"
72 #include "gam_tree.h"
73 #include "gam_event.h"
74 #include "gam_server.h"
75 #include "gam_event.h"
76+#ifdef GAMIN_DEBUG_API
77+#include "gam_debugging.h"
78+#endif
79+
80+#define MIN_POLL_TIME 1.0
81
82 typedef struct {
83 char *path;
84- char *path_file;
85 int wd;
86 int refcount;
87 GList *subs;
88-} INotifyData;
89+ int busy;
90+
91+ gboolean dirty;
92+ GTimer *poll_timer;
93+} inotify_data_t;
94
95 static GHashTable *path_hash = NULL;
96 static GHashTable *wd_hash = NULL;
97-
98-static GList *new_subs = NULL;
99-
100-G_LOCK_DEFINE_STATIC(new_subs);
101-static GList *removed_subs = NULL;
102-
103-G_LOCK_DEFINE_STATIC(removed_subs);
104+static GList *dirty_list = NULL;
105
106 G_LOCK_DEFINE_STATIC(inotify);
107+
108 static GIOChannel *inotify_read_ioc = NULL;
109
110 static gboolean have_consume_idler = FALSE;
111
112-int fd = -1; // the device fd
113+static int inotify_device_fd = -1;
114+
115+static guint should_poll_mask = IN_MODIFY|IN_ATTRIB|IN_CLOSE_WRITE|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE_SUBDIR|IN_DELETE_FILE|IN_CREATE_SUBDIR|IN_CREATE_FILE|IN_DELETE_SELF|IN_UNMOUNT;
116+
117+static void print_mask(int mask)
118+{
119+ if (mask & IN_ACCESS)
120+ {
121+ GAM_DEBUG(DEBUG_INFO, "ACCESS\n");
122+ }
123+ if (mask & IN_MODIFY)
124+ {
125+ GAM_DEBUG(DEBUG_INFO, "MODIFY\n");
126+ }
127+ if (mask & IN_ATTRIB)
128+ {
129+ GAM_DEBUG(DEBUG_INFO, "ATTRIB\n");
130+ }
131+ if (mask & IN_CLOSE_WRITE)
132+ {
133+ GAM_DEBUG(DEBUG_INFO, "CLOSE_WRITE\n");
134+ }
135+ if (mask & IN_CLOSE_NOWRITE)
136+ {
137+ GAM_DEBUG(DEBUG_INFO, "CLOSE_WRITE\n");
138+ }
139+ if (mask & IN_OPEN)
140+ {
141+ GAM_DEBUG(DEBUG_INFO, "OPEN\n");
142+ }
143+ if (mask & IN_MOVED_FROM)
144+ {
145+ GAM_DEBUG(DEBUG_INFO, "MOVE_FROM\n");
146+ }
147+ if (mask & IN_MOVED_TO)
148+ {
149+ GAM_DEBUG(DEBUG_INFO, "MOVE_TO\n");
150+ }
151+ if (mask & IN_DELETE_SUBDIR)
152+ {
153+ GAM_DEBUG(DEBUG_INFO, "DELETE_SUBDIR\n");
154+ }
155+ if (mask & IN_DELETE_FILE)
156+ {
157+ GAM_DEBUG(DEBUG_INFO, "DELETE_FILE\n");
158+ }
159+ if (mask & IN_CREATE_SUBDIR)
160+ {
161+ GAM_DEBUG(DEBUG_INFO, "CREATE_SUBDIR\n");
162+ }
163+ if (mask & IN_CREATE_FILE)
164+ {
165+ GAM_DEBUG(DEBUG_INFO, "CREATE_FILE\n");
166+ }
167+ if (mask & IN_DELETE_SELF)
168+ {
169+ GAM_DEBUG(DEBUG_INFO, "DELETE_SELF\n");
170+ }
171+ if (mask & IN_UNMOUNT)
172+ {
173+ GAM_DEBUG(DEBUG_INFO, "UNMOUNT\n");
174+ }
175+ if (mask & IN_Q_OVERFLOW)
176+ {
177+ GAM_DEBUG(DEBUG_INFO, "Q_OVERFLOW\n");
178+ }
179+ if (mask & IN_IGNORED)
180+ {
181+ GAM_DEBUG(DEBUG_INFO, "IGNORED\n");
182+ }
183+}
184
185-static INotifyData *
186-gam_inotify_data_new(const char *path, char *path_file, int wd)
187+static inotify_data_t *
188+gam_inotify_data_new(const char *path, int wd)
189 {
190- INotifyData *data;
191+ inotify_data_t *data;
192
193- data = g_new0(INotifyData, 1);
194+ data = g_new0(inotify_data_t, 1);
195 data->path = g_strdup(path);
196- data->path_file = path_file;
197 data->wd = wd;
198+ data->busy = 0;
199 data->refcount = 1;
200- data->subs = NULL;
201+ data->dirty = FALSE;
202+ data->poll_timer = g_timer_new ();
203
204 return data;
205 }
206
207 static void
208-gam_inotify_data_free(INotifyData * data)
209+gam_inotify_data_free(inotify_data_t * data)
210 {
211+ if (data->refcount != 0)
212+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_data_free called with reffed data.\n");
213 g_free(data->path);
214- g_free(data->path_file);
215+ g_timer_destroy (data->poll_timer);
216 g_free(data);
217 }
218
219 static void
220-gam_inotify_add_rm_handler(const char *path, GamSubscription * sub,
221- pollHandlerMode mode)
222+gam_inotify_directory_handler_internal(const char *path, pollHandlerMode mode)
223 {
224- INotifyData *data;
225+ inotify_data_t *data;
226+ int path_fd;
227+ int path_wd;
228 struct inotify_watch_request iwr;
229- struct stat st;
230- char *path_file;
231- char *path_t;
232- int wd, r;
233
234+
235+ switch (mode) {
236+ case GAMIN_ACTIVATE:
237+ GAM_DEBUG(DEBUG_INFO, "Adding %s to inotify\n", path);
238+ break;
239+ case GAMIN_DESACTIVATE:
240+ GAM_DEBUG(DEBUG_INFO, "Removing %s from inotify\n", path);
241+ break;
242+ case GAMIN_FLOWCONTROLSTART:
243+ GAM_DEBUG(DEBUG_INFO, "Start flow control for %s\n", path);
244+ break;
245+ case GAMIN_FLOWCONTROLSTOP:
246+ GAM_DEBUG(DEBUG_INFO, "Stop flow control for %s\n", path);
247+ break;
248+ default:
249+ gam_error(DEBUG_INFO, "Unknown inotify operation %d for %s\n",
250+ mode, path);
251+ return;
252+ }
253 G_LOCK(inotify);
254
255 if (mode == GAMIN_ACTIVATE) {
256- GList *subs;
257-
258- subs = NULL;
259- subs = g_list_append(subs, sub);
260-
261 if ((data = g_hash_table_lookup(path_hash, path)) != NULL) {
262 data->refcount++;
263- data->subs = g_list_prepend(data->subs, sub);
264+ GAM_DEBUG(DEBUG_INFO, " found incremented refcount: %d\n",
265+ data->refcount);
266 G_UNLOCK(inotify);
267+#ifdef GAMIN_DEBUG_API
268+ gam_debug_report(GAMinotifyChange, path, data->refcount);
269+#endif
270 GAM_DEBUG(DEBUG_INFO, "inotify updated refcount\n");
271- /*
272- * hum might need some work to check if the path is a dir,
273- * setting 0 and forcing to bypass checks right now.
274- */
275- gam_server_emit_event(path, 0, GAMIN_EVENT_EXISTS, subs, 1);
276- gam_server_emit_event(path, 0, GAMIN_EVENT_ENDEXISTS, subs, 1);
277 return;
278 }
279
280- {
281- if (stat(path, &st)) {
282- G_UNLOCK(inotify);
283- return;
284- }
285-
286- path_t = g_strdup(path);
287- path_file = NULL;
288-
289- if (S_ISREG(st.st_mode)) {
290- char *ch;
291-
292- ch = strrchr(path_t, '/');
293- if (!ch) {
294- g_free(path_t);
295- G_UNLOCK(inotify);
296- return;
297- }
298- path_file = g_strdup(++ch);
299- *ch = '\0';
300- }
301-
302-
303- int file_fd = open(path_t, O_RDONLY);
304+ path_fd = open(path, O_RDONLY);
305
306- g_free(path_t);
307- if (file_fd < 0) {
308- G_UNLOCK(inotify);
309- return;
310- }
311-
312- iwr.fd = file_fd;
313- iwr.mask = 0xffffffff; // all events
314- wd = ioctl(fd, INOTIFY_WATCH, &iwr);
315- close(file_fd);
316- }
317-
318- if (wd < 0) {
319+ if (path_fd < 0) {
320 G_UNLOCK(inotify);
321 return;
322 }
323
324- data = gam_inotify_data_new(path, path_file, wd);
325- path_file = NULL;
326- data->subs = g_list_prepend(data->subs, sub);
327+ iwr.fd = path_fd;
328+ iwr.mask = should_poll_mask;
329+ path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
330+ close (path_fd);
331+
332+ data = gam_inotify_data_new(path, path_wd);
333 g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), data);
334 g_hash_table_insert(path_hash, data->path, data);
335
336- GAM_DEBUG(DEBUG_INFO, "added inotify watch for %s\n", path);
337-
338- gam_server_emit_event(path, 0, GAMIN_EVENT_EXISTS, subs, 1);
339- gam_server_emit_event(path, 0, GAMIN_EVENT_ENDEXISTS, subs, 1);
340+ GAM_DEBUG(DEBUG_INFO, "activated inotify for %s\n", path);
341+#ifdef GAMIN_DEBUG_API
342+ gam_debug_report(GAMinotifyCreate, path, 0);
343+#endif
344 } else if (mode == GAMIN_DESACTIVATE) {
345- data = g_hash_table_lookup(path_hash, path);
346+ char *dir = (char *) path;
347
348- if (!data) {
349- G_UNLOCK(inotify);
350- return;
351- }
352+ data = g_hash_table_lookup(path_hash, path);
353+
354+ if (!data) {
355+ dir = g_path_get_dirname(path);
356+ data = g_hash_table_lookup(path_hash, dir);
357+
358+ if (!data) {
359+ GAM_DEBUG(DEBUG_INFO, " not found !!!\n");
360+
361+ if (dir != NULL)
362+ g_free(dir);
363+
364+ G_UNLOCK(inotify);
365+ return;
366+ }
367+ GAM_DEBUG(DEBUG_INFO, " not found using parent\n");
368+ }
369
370- if (g_list_find(data->subs, sub)) {
371- data->subs = g_list_remove_all(data->subs, sub);
372- }
373 data->refcount--;
374 GAM_DEBUG(DEBUG_INFO, "inotify decremeneted refcount for %s\n",
375 path);
376
377 if (data->refcount == 0) {
378- r = ioctl(fd, INOTIFY_IGNORE, &data->wd);
379- if (r < 0) {
380- GAM_DEBUG(DEBUG_INFO,
381- "INOTIFY_IGNORE failed for %s (wd = %d)\n",
382- data->path, data->wd);
383+ int wd = data->wd;
384+
385+ GAM_DEBUG(DEBUG_INFO, "removed inotify watch for %s\n", data->path);
386+
387+ g_hash_table_remove(path_hash, data->path);
388+ g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
389+ gam_inotify_data_free(data);
390+
391+ if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &wd) < 0) {
392+ GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
393+ }
394+#ifdef GAMIN_DEBUG_API
395+ gam_debug_report(GAMinotifyDelete, dir, 0);
396+#endif
397+ } else {
398+ GAM_DEBUG(DEBUG_INFO, " found decremented refcount: %d\n",
399+ data->refcount);
400+#ifdef GAMIN_DEBUG_API
401+ gam_debug_report(GAMinotifyChange, dir, data->refcount);
402+#endif
403+ }
404+ if ((dir != path) && (dir != NULL))
405+ g_free(dir);
406+ } else if ((mode == GAMIN_FLOWCONTROLSTART) ||
407+ (mode == GAMIN_FLOWCONTROLSTOP)) {
408+ char *dir = (char *) path;
409+
410+ data = g_hash_table_lookup(path_hash, path);
411+ if (!data) {
412+ dir = g_path_get_dirname(path);
413+ data = g_hash_table_lookup(path_hash, dir);
414+
415+ if (!data) {
416+ GAM_DEBUG(DEBUG_INFO, " not found !!!\n");
417+
418+ if (dir != NULL)
419+ g_free(dir);
420+ G_UNLOCK(inotify);
421+ return;
422 }
423- GAM_DEBUG(DEBUG_INFO, "removed inotify watch for %s\n",
424- data->path);
425- g_hash_table_remove(path_hash, data->path);
426- g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
427- gam_inotify_data_free(data);
428+ GAM_DEBUG(DEBUG_INFO, " not found using parent\n");
429 }
430+ if (data != NULL) {
431+ if (mode == GAMIN_FLOWCONTROLSTART) {
432+ if (data->wd >= 0) {
433+ if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &data->wd) < 0) {
434+ GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
435+ }
436+ g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
437+ data->wd = -1;
438+ GAM_DEBUG(DEBUG_INFO, "deactivated inotify for %s\n",
439+ data->path);
440+#ifdef GAMIN_DEBUG_API
441+ gam_debug_report(GAMinotifyFlowOn, dir, 0);
442+#endif
443+ }
444+ data->busy++;
445+ } else {
446+ if (data->busy > 0) {
447+ data->busy--;
448+ if (data->busy == 0) {
449+ path_fd = open(data->path, O_RDONLY);
450+ if (path_fd < 0) {
451+ G_UNLOCK(inotify);
452+ GAM_DEBUG(DEBUG_INFO,
453+ "Failed to reactivate inotify for %s\n",
454+ data->path);
455+
456+ if ((dir != path) && (dir != NULL))
457+ g_free(dir);
458+ return;
459+ }
460+
461+ iwr.fd = path_fd;
462+ iwr.mask = 0xffffffff;
463+ path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
464+ close (path_fd);
465+
466+ data->wd = path_wd;
467+
468+ g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd),
469+ data);
470+ GAM_DEBUG(DEBUG_INFO, "Reactivated inotify for %s\n",
471+ data->path);
472+#ifdef GAMIN_DEBUG_API
473+ gam_debug_report(GAMinotifyFlowOff, path, 0);
474+#endif
475+ }
476+ }
477+ }
478+ }
479+ if ((dir != path) && (dir != NULL))
480+ g_free(dir);
481 } else {
482- GAM_DEBUG(DEBUG_INFO, "Inotify: unimplemented mode request %d\n",
483- mode);
484+ GAM_DEBUG(DEBUG_INFO, "Unimplemented operation\n");
485 }
486+
487 G_UNLOCK(inotify);
488 }
489
490-static GaminEventType
491-inotify_event_to_gamin_event(int mask)
492+static void
493+gam_inotify_directory_handler(const char *path, pollHandlerMode mode)
494 {
495- switch (mask) {
496- case IN_ATTRIB:
497- case IN_MODIFY:
498- return GAMIN_EVENT_CHANGED;
499- break;
500- case IN_MOVED_TO:
501- case IN_CREATE_SUBDIR:
502- case IN_CREATE_FILE:
503- return GAMIN_EVENT_CREATED;
504- break;
505- case IN_MOVED_FROM:
506- case IN_DELETE_SUBDIR:
507- case IN_DELETE_FILE:
508- return GAMIN_EVENT_DELETED;
509- break;
510- default:
511- return GAMIN_EVENT_UNKNOWN;
512+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_directory_handler %s : %d\n",
513+ path, mode);
514+
515+ if ((mode == GAMIN_DESACTIVATE) ||
516+ (g_file_test(path, G_FILE_TEST_IS_DIR))) {
517+ gam_inotify_directory_handler_internal(path, mode);
518+ } else {
519+ char *dir;
520+
521+ dir = g_path_get_dirname(path);
522+ GAM_DEBUG(DEBUG_INFO, " not a dir using parent %s\n", dir);
523+ gam_inotify_directory_handler_internal(dir, mode);
524+ g_free(dir);
525 }
526 }
527
528 static void
529-gam_inotify_emit_event(INotifyData * data, struct inotify_event *event)
530+gam_inotify_file_handler(const char *path, pollHandlerMode mode)
531 {
532- GaminEventType gevent;
533- char *event_path;
534-
535- if (!data || !event)
536- return;
537- gevent = inotify_event_to_gamin_event(event->mask);
538+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_file_handler %s : %d\n", path, mode);
539+
540+ if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
541+ gam_inotify_directory_handler_internal(path, mode);
542+ } else {
543+ char *dir;
544
545- // gamins event vocabulary is very small compared to inotify
546- // so we often will receieve events that have no equivelant
547- // in gamin
548- if (gevent == GAMIN_EVENT_UNKNOWN) {
549- return;
550+ dir = g_path_get_dirname(path);
551+ GAM_DEBUG(DEBUG_INFO, " not a dir using parent %s\n", dir);
552+ gam_inotify_directory_handler_internal(dir, mode);
553+ g_free(dir);
554 }
555- if (event->name[0] != '\0' && !data->path_file) {
556- int pathlen = strlen(data->path);
557+}
558
559- if (data->path[pathlen - 1] == '/') {
560- event_path = g_strconcat(data->path, event->name, NULL);
561- } else {
562- event_path = g_strconcat(data->path, "/", event->name, NULL);
563- }
564- } else {
565- event_path = g_strdup(data->path);
566- }
567+/* Must be called with inotify lock locked */
568+static void
569+gam_inotify_dirty_list_cleaner ()
570+{
571+ GList *l;
572+
573+ /* Here we walk the old dirty list and create a new one.
574+ * if we don't poll a node on the old list, we add it to the new one */
575+
576+ l = dirty_list;
577+ dirty_list = NULL;
578
579- GAM_DEBUG(DEBUG_INFO, "inotify emitting event %s for %s\n",
580- gam_event_to_string(gevent), event_path);
581+ for (l = l; l; l = l->next) {
582+ inotify_data_t *data = l->data;
583
584- gam_server_emit_event(event_path, 0, gevent, data->subs, 1);
585+ g_assert (data->dirty);
586+
587+ if (g_timer_elapsed (data->poll_timer, NULL) >= MIN_POLL_TIME) {
588+ data->dirty = FALSE;
589+ gam_poll_scan_directory (data->path);
590+ } else {
591+ dirty_list = g_list_append (dirty_list, data);
592+ }
593+ }
594
595- g_free(event_path);
596+ g_list_free (l);
597 }
598
599 static gboolean
600@@ -276,71 +422,76 @@
601 {
602 char *buffer;
603 int buffer_size;
604+ int events;
605 gsize buffer_i, read_size;
606
607 G_LOCK(inotify);
608
609- if (ioctl(fd, FIONREAD, &buffer_size) < 0) {
610- G_UNLOCK(inotify);
611- GAM_DEBUG(DEBUG_INFO, "inotify FIONREAD < 0. kaboom!\n");
612- return FALSE;
613+#if 0
614+ gam_inotify_dirty_list_cleaner ();
615+#endif
616+
617+ if (ioctl(inotify_device_fd, FIONREAD, &buffer_size) < 0) {
618+ G_UNLOCK(inotify);
619+ GAM_DEBUG(DEBUG_INFO, "inotify FIONREAD < 0. kaboom!\n");
620+ return FALSE;
621 }
622
623 buffer = g_malloc(buffer_size);
624
625- if (g_io_channel_read_chars
626- (inotify_read_ioc, (char *) buffer, buffer_size, &read_size,
627- NULL) != G_IO_STATUS_NORMAL) {
628- G_UNLOCK(inotify);
629- GAM_DEBUG(DEBUG_INFO,
630- "inotify failed to read events from inotify fd.\n");
631- g_free(buffer);
632- return FALSE;
633+ if (g_io_channel_read_chars(inotify_read_ioc, (char *)buffer, buffer_size, &read_size, NULL) != G_IO_STATUS_NORMAL) {
634+ G_UNLOCK(inotify);
635+ GAM_DEBUG(DEBUG_INFO, "inotify failed to read events from inotify fd.\n");
636+ g_free (buffer);
637+ return FALSE;
638 }
639
640 buffer_i = 0;
641+ events = 0;
642 while (buffer_i < read_size) {
643- struct inotify_event *event;
644- gsize event_size;
645- INotifyData *data;
646-
647- event = (struct inotify_event *) &buffer[buffer_i];
648- event_size = sizeof(struct inotify_event) + event->len;
649-
650- data = g_hash_table_lookup(wd_hash, GINT_TO_POINTER(event->wd));
651- if (!data) {
652- GAM_DEBUG(DEBUG_INFO, "inotify can't find wd %d\n", event->wd);
653- GAM_DEBUG(DEBUG_INFO,
654- "weird things have happened to inotify.\n");
655- } else {
656- /* Do the shit with the event */
657- if (event->mask == IN_IGNORED) {
658- GList *l;
659-
660- l = data->subs;
661- data->subs = NULL;
662- for (l = l; l; l = l->next) {
663- GamSubscription *sub = l->data;
664-
665- gam_inotify_remove_subscription(sub);
666- }
667- } else {
668- if (data->path_file) {
669- if (event->name[0] != '\0') {
670- int pathlen = strlen(data->path_file);
671-
672- if (strcmp(data->path_file, event->name)) {
673- buffer_i += event_size;
674- continue;
675- }
676- }
677- }
678- gam_inotify_emit_event(data, event);
679- }
680- }
681+ struct inotify_event *event;
682+ gsize event_size;
683+ inotify_data_t *data;
684+
685+ event = (struct inotify_event *)&buffer[buffer_i];
686+ event_size = sizeof(struct inotify_event) + event->len;
687+
688+ data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd));
689+ if (!data) {
690+ GAM_DEBUG(DEBUG_INFO, "inotify can't find wd %d\n", event->wd);
691+ } else {
692+ if (event->mask == IN_IGNORED || event->mask == IN_UNMOUNT) {
693+ GList *l;
694+
695+ l = data->subs;
696+ data->subs = NULL;
697+ for (l = l; l; l = l->next) {
698+ GamSubscription *sub = l->data;
699+ gam_inotify_remove_subscription (sub);
700+ }
701+ } else if (event->mask != IN_Q_OVERFLOW) {
702+ if (event->mask & should_poll_mask) {
703+ GAM_DEBUG(DEBUG_INFO, "inotify requesting poll for %s\n", data->path);
704+ GAM_DEBUG(DEBUG_INFO, "poll was requested for event = ");
705+ print_mask (event->mask);
706+ gam_poll_scan_directory (data->path);
707+#if 0
708+ /* if node isn't dirty */
709+ if (!data->dirty) {
710+ /* Put this node on the dirty list */
711+ data->dirty = TRUE;
712+ g_timer_start(data->poll_timer);
713+ dirty_list = g_list_append (dirty_list, data);
714+ }
715+#endif
716+ }
717+ }
718+ }
719
720 buffer_i += event_size;
721+ events++;
722 }
723+ GAM_DEBUG(DEBUG_INFO, "inotify recieved %d events\n", events);
724
725 g_free(buffer);
726 G_UNLOCK(inotify);
727@@ -348,48 +499,12 @@
728 return TRUE;
729 }
730
731+
732 static gboolean
733 gam_inotify_consume_subscriptions_real(gpointer data)
734 {
735- GList *subs, *l;
736-
737- G_LOCK(new_subs);
738- if (new_subs) {
739- subs = new_subs;
740- new_subs = NULL;
741- G_UNLOCK(new_subs);
742-
743- for (l = subs; l; l = l->next) {
744- GamSubscription *sub = l->data;
745-
746- GAM_DEBUG(DEBUG_INFO, "called gam_inotify_add_handler()\n");
747- gam_inotify_add_rm_handler(gam_subscription_get_path(sub), sub,
748- TRUE);
749- }
750-
751- } else {
752- G_UNLOCK(new_subs);
753- }
754-
755- G_LOCK(removed_subs);
756- if (removed_subs) {
757- subs = removed_subs;
758- removed_subs = NULL;
759- G_UNLOCK(removed_subs);
760-
761- for (l = subs; l; l = l->next) {
762- GamSubscription *sub = l->data;
763-
764- GAM_DEBUG(DEBUG_INFO, "called gam_inotify_rm_handler()\n");
765- gam_inotify_add_rm_handler(gam_subscription_get_path(sub), sub,
766- FALSE);
767- }
768- } else {
769- G_UNLOCK(removed_subs);
770- }
771-
772- GAM_DEBUG(DEBUG_INFO, "gam_inotify_consume_subscriptions()\n");
773-
774+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_consume_subscriptions_real()\n");
775+ gam_poll_consume_subscriptions();
776 have_consume_idler = FALSE;
777 return FALSE;
778 }
779@@ -402,30 +517,31 @@
780 if (have_consume_idler)
781 return;
782
783+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_consume_subscriptions()\n");
784 have_consume_idler = TRUE;
785-
786 source = g_idle_source_new();
787 g_source_set_callback(source, gam_inotify_consume_subscriptions_real,
788 NULL, NULL);
789-
790 g_source_attach(source, NULL);
791 }
792
793 /**
794- * @defgroup inotify inotify backend
795+ * @defgroup inotify inotify Backend
796 * @ingroup Backends
797 * @brief inotify backend API
798 *
799 * Since version 2.6.X, Linux kernels have included the Linux Inode
800 * Notification system (inotify). This backend uses inotify to know when
801- * files are changed/created/deleted.
802+ * files are changed/created/deleted. Since inotify can't watch files/dirs that
803+ * don't exist we still have to cache stat() information. For this,
804+ * we can just use the code in the polling backend.
805 *
806 * @{
807 */
808
809
810 /**
811- * Initializes the inotify system. This must be called before
812+ * Initializes the inotify backend. This must be called before
813 * any other functions in this module.
814 *
815 * @returns TRUE if initialization succeeded, FALSE otherwise
816@@ -435,14 +551,16 @@
817 {
818 GSource *source;
819
820- fd = open("/dev/inotify", O_RDONLY);
821+ inotify_device_fd = open("/dev/inotify", O_RDONLY);
822
823- if (fd < 0) {
824- GAM_DEBUG(DEBUG_INFO, "Could not open /dev/inotify\n");
825- return FALSE;
826+ if (inotify_device_fd < 0) {
827+ GAM_DEBUG(DEBUG_INFO, "Could not open /dev/inotify\n");
828+ return FALSE;
829 }
830
831- inotify_read_ioc = g_io_channel_unix_new(fd);
832+ g_return_val_if_fail(gam_poll_init_full(FALSE), FALSE);
833+
834+ inotify_read_ioc = g_io_channel_unix_new(inotify_device_fd);
835
836 /* For binary data */
837 g_io_channel_set_encoding(inotify_read_ioc, NULL, NULL);
838@@ -450,13 +568,15 @@
839 g_io_channel_set_flags(inotify_read_ioc, G_IO_FLAG_NONBLOCK, NULL);
840
841 source = g_io_create_watch(inotify_read_ioc,
842- G_IO_IN | G_IO_HUP | G_IO_ERR);
843+ G_IO_IN | G_IO_HUP | G_IO_ERR);
844 g_source_set_callback(source, gam_inotify_read_handler, NULL, NULL);
845
846 g_source_attach(source, NULL);
847
848 path_hash = g_hash_table_new(g_str_hash, g_str_equal);
849 wd_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
850+ gam_poll_set_directory_handler(gam_inotify_directory_handler);
851+ gam_poll_set_file_handler(gam_inotify_file_handler);
852
853 GAM_DEBUG(DEBUG_INFO, "inotify initialized\n");
854
855@@ -476,15 +596,14 @@
856 gboolean
857 gam_inotify_add_subscription(GamSubscription * sub)
858 {
859- gam_listener_add_subscription(gam_subscription_get_listener(sub), sub);
860-
861- G_LOCK(new_subs);
862- new_subs = g_list_prepend(new_subs, sub);
863- G_UNLOCK(new_subs);
864-
865- GAM_DEBUG(DEBUG_INFO, "inotify_add_sub\n");
866+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_add_subscription\n");
867+ if (!gam_poll_add_subscription(sub)) {
868+ return FALSE;
869+ }
870
871 gam_inotify_consume_subscriptions();
872+
873+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_add_subscription: done\n");
874 return TRUE;
875 }
876
877@@ -497,26 +616,15 @@
878 gboolean
879 gam_inotify_remove_subscription(GamSubscription * sub)
880 {
881- G_LOCK(new_subs);
882- if (g_list_find(new_subs, sub)) {
883- GAM_DEBUG(DEBUG_INFO, "removed sub found on new_subs\n");
884- new_subs = g_list_remove_all(new_subs, sub);
885- G_UNLOCK(new_subs);
886- return TRUE;
887- }
888- G_UNLOCK(new_subs);
889-
890- gam_subscription_cancel(sub);
891- gam_listener_remove_subscription(gam_subscription_get_listener(sub),
892- sub);
893-
894- G_LOCK(removed_subs);
895- removed_subs = g_list_prepend(removed_subs, sub);
896- G_UNLOCK(removed_subs);
897+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_remove_subscription\n");
898+
899+ if (!gam_poll_remove_subscription(sub)) {
900+ return FALSE;
901+ }
902
903- GAM_DEBUG(DEBUG_INFO, "inotify_remove_sub\n");
904 gam_inotify_consume_subscriptions();
905
906+ GAM_DEBUG(DEBUG_INFO, "gam_inotify_remove_subscription: done\n");
907 return TRUE;
908 }
909
910@@ -529,26 +637,13 @@
911 gboolean
912 gam_inotify_remove_all_for(GamListener * listener)
913 {
914- GList *subs, *l = NULL;
915-
916- subs = gam_listener_get_subscriptions(listener);
917-
918- for (l = subs; l; l = l->next) {
919- GamSubscription *sub = l->data;
920-
921- g_assert(sub != NULL);
922-
923- gam_inotify_remove_subscription(sub);
924-
925- }
926-
927- if (subs) {
928- g_list_free(subs);
929- gam_inotify_consume_subscriptions();
930- return TRUE;
931- } else {
932+ if (!gam_poll_remove_all_for(listener)) {
933 return FALSE;
934 }
935+
936+ gam_inotify_consume_subscriptions();
937+
938+ return TRUE;
939 }
940
941 /** @} */
942Index: server/gam_inotify.h
943===================================================================
944RCS file: /cvs/gnome/gamin/server/gam_inotify.h,v
945retrieving revision 1.1
946diff -u -r1.1 gam_inotify.h
947--- server/gam_inotify.h 27 Jul 2004 10:24:43 -0000 1.1
948+++ server/gam_inotify.h 14 Apr 2005 16:44:34 -0000
949@@ -1,6 +1,5 @@
950-
951-#ifndef __MD_INOTIFY_H__
952-#define __MD_INOTIFY_H__
953+#ifndef __GAM_INOTIFY_H__
954+#define __GAM_INOTIFY_H__
955
956 #include <glib.h>
957 #include "gam_poll.h"
958@@ -15,4 +14,4 @@
959
960 G_END_DECLS
961
962-#endif /* __MD_INOTIFY_H__ */
963+#endif /* __GAM_INOTIFY_H__ */
964
This page took 0.123705 seconds and 4 git commands to generate.