View | Details | Raw Unified | Return to bug 79605
Collapse All | Expand All

(-)gamin/Makefile (-1 / +1 lines)
Lines 7-13 Link Here
7
7
8
PORTNAME=	gamin
8
PORTNAME=	gamin
9
PORTVERSION=	0.0.26
9
PORTVERSION=	0.0.26
10
PORTREVISION?=	8
10
PORTREVISION?=	9
11
CATEGORIES?=	devel
11
CATEGORIES?=	devel
12
MASTER_SITES=	http://www.gnome.org/~veillard/gamin/sources/
12
MASTER_SITES=	http://www.gnome.org/~veillard/gamin/sources/
13
13
(-)gamin/files/patch-server_gam_kqueue.c (-104 / +180 lines)
Lines 1-8 Link Here
1
--- server/gam_kqueue.c.orig	Thu Mar 31 20:39:54 2005
1
--- server/gam_kqueue.c.orig	Wed Apr  6 18:21:46 2005
2
+++ server/gam_kqueue.c	Fri Apr  1 01:09:11 2005
2
+++ server/gam_kqueue.c	Wed Apr  6 18:57:07 2005
3
@@ -0,0 +1,636 @@
3
@@ -0,0 +1,712 @@
4
+/*
4
+/*
5
+ * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org>
5
+ * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org>
6
+ * Copyright (C) 2005 Jean-Yves Lefort <jylefort@brutele.be>
6
+ *
7
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * modify it under the terms of the GNU Lesser General Public
Lines 22-27 Link Here
22
+
23
+
23
+#include <config.h>
24
+#include <config.h>
24
+#include <sys/types.h>
25
+#include <sys/types.h>
26
+#include <sys/stat.h>
25
+#include <sys/event.h>
27
+#include <sys/event.h>
26
+#include <sys/time.h>
28
+#include <sys/time.h>
27
+#include <fcntl.h>
29
+#include <fcntl.h>
Lines 47-52 Link Here
47
+    GSList *dirlist;
49
+    GSList *dirlist;
48
+} KQueueData;
50
+} KQueueData;
49
+
51
+
52
+typedef struct
53
+{
54
+    time_t mtime;
55
+    time_t ctime;
56
+    off_t size;
57
+} MiniStat;
58
+
59
+typedef struct {
60
+    char *filename;
61
+    char *pathname;
62
+    MiniStat sb;
63
+} FileData;
64
+  
50
+static GHashTable *dir_path_hash = NULL;
65
+static GHashTable *dir_path_hash = NULL;
51
+static GHashTable *file_path_hash = NULL;
66
+static GHashTable *file_path_hash = NULL;
52
+static GHashTable *fd_hash = NULL;
67
+static GHashTable *fd_hash = NULL;
Lines 80-149 Link Here
80
+    return data;
95
+    return data;
81
+}
96
+}
82
+
97
+
83
+static GSList *
98
+static void
84
+gam_kqueue_lsdir(const char *path)
99
+gam_kqueue_mini_stat (const char *pathname, MiniStat *mini_sb)
85
+{
100
+{
86
+    GDir *dir;
101
+    struct stat sb;
87
+    GSList *lst = NULL;
88
+    const gchar *entry;
89
+
90
+    if (!path)
91
+        return NULL;
92
+
102
+
93
+    dir = g_dir_open(path, 0, NULL);
103
+    if (stat(pathname, &sb) == 0) {
94
+    if (!dir)
104
+        mini_sb->mtime = sb.st_mtime;
95
+        return NULL;
105
+	mini_sb->ctime = sb.st_ctime;
96
+
106
+	mini_sb->size = sb.st_size;
97
+    entry = g_dir_read_name(dir);
107
+    } else {
98
+
108
+        mini_sb->mtime = 0;
99
+    while (entry) {
109
+	mini_sb->ctime = 0;
100
+        lst = g_slist_prepend(lst, g_strdup(entry));
110
+	mini_sb->size = 0;
101
+        entry = g_dir_read_name(dir);
102
+    }
111
+    }
103
+
104
+    g_dir_close(dir);
105
+
106
+    return lst;
107
+}
112
+}
108
+
113
+
109
+static void
114
+static FileData *
110
+gam_kqueue_cmplst(GSList *lst1, GSList *lst2, GSList **added, GSList **deleted)
115
+gam_kqueue_file_data_new (const char *path, const char *filename)
111
+{
116
+{
112
+    int found;
117
+    FileData *fdata;
113
+    GSList *l;
118
+    struct stat sb;
114
+
115
+    if (!lst1 && !lst2)
116
+        return;
117
+
119
+
118
+    if (!lst1) {
120
+    fdata = g_new(FileData, 1);
119
+        *added = g_slist_copy(lst2);
121
+    fdata->filename = g_strdup(filename);
120
+        return;
122
+    fdata->pathname = g_build_filename(path, filename, NULL);
121
+    }
123
+    gam_kqueue_mini_stat(fdata->pathname, &fdata->sb);
122
+
123
+    if (!lst2) {
124
+        *deleted = g_slist_copy(lst1);
125
+        return;
126
+    }
127
+
124
+
128
+    for (l = lst1; l; l = l->next) {
125
+    return fdata;
129
+        found = 0;
126
+}
130
+        if (g_slist_find_custom(lst2, l->data, (GCompareFunc)strcmp)) {
131
+            found = 1;
132
+        }
133
+        if (found == 0) {
134
+            *deleted = g_slist_prepend(*deleted, l->data);
135
+        }
136
+    }
137
+
127
+
138
+    for (l = lst2; l; l = l->next) {
128
+static void
139
+        found = 0;
129
+gam_kqueue_file_data_free (FileData *fdata)
140
+        if (g_slist_find_custom(lst1, l->data, (GCompareFunc)strcmp)) {
130
+{
141
+            found = 1;
131
+    g_free(fdata->filename);
142
+        }
132
+    g_free(fdata->pathname);
143
+        if (found == 0) {
133
+    g_free(fdata);
144
+            *added = g_slist_prepend(*added, l->data);
145
+        }
146
+    }
147
+}
134
+}
148
+
135
+
149
+static void
136
+static void
Lines 151-157 Link Here
151
+{
138
+{
152
+    g_free(data->path);
139
+    g_free(data->path);
153
+    if (data->dirlist) {
140
+    if (data->dirlist) {
154
+        g_slist_foreach(data->dirlist, (GFunc)g_free, NULL);
141
+        g_slist_foreach(data->dirlist, (GFunc)gam_kqueue_file_data_free, NULL);
155
+        g_slist_free(data->dirlist);
142
+        g_slist_free(data->dirlist);
156
+    }
143
+    }
157
+    if (data->subs) {
144
+    if (data->subs) {
Lines 160-165 Link Here
160
+    g_free(data);
147
+    g_free(data);
161
+}
148
+}
162
+
149
+
150
+static int
151
+gam_kqueue_dirlist_find (FileData *fdata, const char *filename)
152
+{
153
+    return strcmp(fdata->filename, filename);
154
+}
155
+
163
+static void
156
+static void
164
+gam_kqueue_add_rm_handler(const char *path, GamSubscription *sub, gboolean added, gboolean was_missing)
157
+gam_kqueue_add_rm_handler(const char *path, GamSubscription *sub, gboolean added, gboolean was_missing)
165
+{
158
+{
Lines 230-250 Link Here
230
+            gam_server_emit_event (path, isdir, GAMIN_EVENT_CREATED, subs, 1);
223
+            gam_server_emit_event (path, isdir, GAMIN_EVENT_CREATED, subs, 1);
231
+	}
224
+	}
232
+        if (gam_subscription_is_dir(sub) && isdir) {
225
+        if (gam_subscription_is_dir(sub) && isdir) {
233
+	    GSList *l;
226
+	    GDir *dir;
234
+
227
+
235
+            data->isdir = TRUE;
228
+            data->isdir = TRUE;
236
+            data->dirlist = gam_kqueue_lsdir(path);
229
+	    data->dirlist = NULL;
237
+
230
+
238
+	    for (l = data->dirlist; l; l = l->next) {
231
+	    dir = g_dir_open(path, 0, NULL);
239
+                char *tmpentry;
232
+	    if (dir) {
240
+
233
+	        const char *entry;
241
+                tmpentry = g_build_filename(path, l->data, NULL);
234
+
242
+		if (!was_missing) {
235
+		while ((entry = g_dir_read_name(dir))) {
243
+		    gam_server_emit_event (tmpentry,
236
+		    FileData *fdata;
244
+                        g_file_test(tmpentry, G_FILE_TEST_IS_DIR),
237
+
245
+		        GAMIN_EVENT_EXISTS, subs, 1);
238
+		    fdata = gam_kqueue_file_data_new(path, entry);
239
+		    data->dirlist = g_slist_prepend(data->dirlist, fdata);
240
+
241
+		    if (!was_missing) {
242
+		        gam_server_emit_event(fdata->pathname,
243
+					      g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR),
244
+					      GAMIN_EVENT_EXISTS, subs, 1);
245
+		    }
246
+		}
246
+		}
247
+		g_free(tmpentry);
247
+
248
+		g_dir_close(dir);
248
+	    }
249
+	    }
249
+	}
250
+	}
250
+
251
+
Lines 332-375 Link Here
332
+	isdir = g_file_test(data->path, G_FILE_TEST_IS_DIR);
333
+	isdir = g_file_test(data->path, G_FILE_TEST_IS_DIR);
333
+
334
+
334
+	if (gevent == GAMIN_EVENT_CHANGED && data->isdir) {
335
+	if (gevent == GAMIN_EVENT_CHANGED && data->isdir) {
335
+	    GSList *dirlist = NULL, *added = NULL, *deleted = NULL;
336
+	    GSList *dirlist = NULL;
336
+	    GSList *l;
337
+	    GSList *l;
338
+	    GDir *dir;
339
+
340
+	    dir = g_dir_open(data->path, 0, NULL);
341
+	    if (dir) {
342
+	        const char *entry;
337
+
343
+
338
+	    dirlist = gam_kqueue_lsdir(data->path);
344
+		while ((entry = g_dir_read_name(dir))) {
339
+	    gam_kqueue_cmplst(data->dirlist, dirlist, &added, &deleted);
345
+		    dirlist = g_slist_prepend(dirlist, g_strdup(entry));
340
+	    if (added || deleted) {
341
+	        for (l = deleted; l; l = l->next) {
342
+                    data->dirlist = g_slist_remove(data->dirlist, l->data);
343
+		    event_path = g_build_filename(data->path, l->data, NULL);
344
+		    g_free(l->data);
345
+		    isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
346
+
347
+                    GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_DELETED) , event_path);
348
+
349
+                    gam_server_emit_event (event_path, isdir,
350
+                        GAMIN_EVENT_DELETED, data->subs, 1);
351
+		    g_free(event_path);
352
+		}
346
+		}
353
+
347
+
354
+		for (l = added; l; l = l->next) {
348
+		g_dir_close(dir);
355
+                    dirlist = g_slist_remove(dirlist, l->data);
349
+	    }
356
+		    data->dirlist = g_slist_prepend(data->dirlist,
350
+
357
+                        g_strdup(l->data));
351
+	    for (l = dirlist; l; l = l->next) {
358
+		    event_path = g_build_filename(data->path, l->data, NULL);
352
+	        if (! g_slist_find_custom(data->dirlist, l->data, (GCompareFunc) gam_kqueue_dirlist_find)) {
359
+		    g_free(l->data);
353
+		    FileData *fdata;
360
+		    isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
354
+
361
+
355
+		    fdata = gam_kqueue_file_data_new(data->path, l->data);
362
+		    GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CREATED) , event_path);
356
+		    data->dirlist = g_slist_prepend(data->dirlist, fdata);
363
+
357
+
364
+		    gam_server_emit_event (event_path, isdir,
358
+		    GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CREATED), fdata->pathname);
365
+                        GAMIN_EVENT_CREATED, data->subs, 1);
359
+		    gam_server_emit_event(fdata->pathname,
366
+		    g_free(event_path);
360
+					  g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR),
361
+					  GAMIN_EVENT_CREATED, data->subs, 1);
367
+		}
362
+		}
363
+	    }
364
+
365
+	iterate:
366
+	    for (l = data->dirlist; l; l = l->next) {
367
+	        FileData *fdata = l->data;
368
+
369
+	        if (! g_slist_find_custom(dirlist, fdata->filename, (GCompareFunc) strcmp)) {
370
+		    data->dirlist = g_slist_remove(data->dirlist, fdata);
368
+
371
+
369
+		if (added)
372
+                    GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_DELETED), fdata->pathname);
370
+                  g_slist_free(added);
373
+		    gam_server_emit_event(fdata->pathname,
371
+		if (deleted)
374
+					  g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR),
372
+                  g_slist_free(deleted);
375
+					  GAMIN_EVENT_DELETED, data->subs, 1);
376
+
377
+		    gam_kqueue_file_data_free(fdata);
378
+		    goto iterate; /* list changed, start again */
379
+		}
373
+	    }
380
+	    }
374
+
381
+
375
+	    if (dirlist) {
382
+	    if (dirlist) {
Lines 380-385 Link Here
380
+	}
387
+	}
381
+	else {
388
+	else {
382
+	    event_path = g_strdup (data->path);
389
+	    event_path = g_strdup (data->path);
390
+
391
+	    if (gevent == GAMIN_EVENT_DELETED
392
+		|| gevent == GAMIN_EVENT_ENDEXISTS
393
+		|| gevent == GAMIN_EVENT_MOVED) {
394
+	      /* close and move to exist_list, to catch next creation */
395
+	      close(data->fd);
396
+	      if (data->isdir) {
397
+		  g_hash_table_remove(dir_path_hash, data->path);
398
+	      }
399
+	      else {
400
+		  g_hash_table_remove(file_path_hash, data->path);
401
+	      }
402
+	      g_hash_table_remove(fd_hash, GINT_TO_POINTER(data->fd));
403
+
404
+	      exist_list = g_slist_append(exist_list, data);
405
+	    }
383
+	}
406
+	}
384
+
407
+
385
+        isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
408
+        isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
Lines 418-425 Link Here
418
+    return TRUE;
441
+    return TRUE;
419
+}
442
+}
420
+
443
+
444
+static void
445
+gam_kqueue_dirlist_check_cb (const char *path, KQueueData *data, gpointer user_data)
446
+{
447
+    GSList *l;
448
+
449
+    for (l = data->dirlist; l; l = l->next) {
450
+        FileData *fdata = l->data;
451
+	MiniStat sb;
452
+
453
+	gam_kqueue_mini_stat(fdata->pathname, &sb);
454
+
455
+	if (sb.mtime != fdata->sb.mtime
456
+	    || sb.ctime != fdata->sb.ctime
457
+	    || sb.size != fdata->sb.size)
458
+	  {
459
+	      memcpy(&fdata->sb, &sb, sizeof(sb));
460
+
461
+	      GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CHANGED), fdata->pathname);
462
+	      gam_server_emit_event(fdata->pathname,
463
+				    g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR),
464
+				    GAMIN_EVENT_CHANGED, data->subs, 1);
465
+	  }
466
+    }
467
+}
468
+
469
+static gboolean
470
+gam_kqueue_dirlist_check (gpointer user_data)
471
+{
472
+    G_LOCK(kqueue);
473
+
474
+    GAM_DEBUG(DEBUG_INFO, "gam_kqueue_dirlist_check()\n");
475
+
476
+    g_hash_table_foreach(dir_path_hash, (GHFunc) gam_kqueue_dirlist_check_cb, NULL);
477
+
478
+    G_UNLOCK(kqueue);
479
+
480
+    return TRUE;
481
+}
482
+
421
+static gboolean
483
+static gboolean
422
+gam_kqueue_event_handler (gpointer user_data)
484
+gam_kqueue_event_handler (GIOChannel *source, GIOCondition condition, gpointer user_data)
423
+{
485
+{
424
+    KQueueData *data;
486
+    KQueueData *data;
425
+    struct kevent ev[1];
487
+    struct kevent ev[1];
Lines 531-536 Link Here
531
+gboolean
593
+gboolean
532
+gam_kqueue_init(void)
594
+gam_kqueue_init(void)
533
+{
595
+{
596
+    GIOChannel *channel;
597
+
534
+    kq = kqueue();
598
+    kq = kqueue();
535
+    if (kq == -1) {
599
+    if (kq == -1) {
536
+	GAM_DEBUG(DEBUG_INFO, "Could not initialize a new kqueue\n");
600
+	GAM_DEBUG(DEBUG_INFO, "Could not initialize a new kqueue\n");
Lines 538-548 Link Here
538
+    }
602
+    }
539
+
603
+
540
+    g_timeout_add(1000, gam_kqueue_exist_check, NULL);
604
+    g_timeout_add(1000, gam_kqueue_exist_check, NULL);
541
+    g_timeout_add(1000, gam_kqueue_event_handler, NULL);
605
+
606
+    channel = g_io_channel_unix_new(kq);
607
+    g_io_add_watch(channel, G_IO_IN, gam_kqueue_event_handler, NULL);
542
+
608
+
543
+    dir_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
609
+    dir_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
544
+    file_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
610
+    file_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
545
+    fd_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
611
+    fd_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
612
+
613
+    /*
614
+     * gam_kqueue_dirlist_check() has to stat() every file in every
615
+     * monitored directory. This can easily become an intensive task
616
+     * if a few large directories are monitored (for instance a mail
617
+     * checker monitoring a couple of Maildir folders), therefore we
618
+     * use a reasonable poll interval (6 seconds, same as FAM's
619
+     * default).
620
+     */
621
+    g_timeout_add(6000, gam_kqueue_dirlist_check, NULL);
546
+
622
+
547
+    GAM_DEBUG(DEBUG_INFO, "kqueue initialized\n");
623
+    GAM_DEBUG(DEBUG_INFO, "kqueue initialized\n");
548
+
624
+

Return to bug 79605