FreeBSD Bugzilla – Attachment 52560 Details for
Bug 79605
Update port: devel/gamin (fix and improve the kqueue backend)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 11.91 KB, created by
Jean-Yves Lefort
on 2005-04-06 18:20:05 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
Jean-Yves Lefort
Created:
2005-04-06 18:20:05 UTC
Size:
11.91 KB
patch
obsolete
>diff -ruN /usr/ports/devel/gamin/Makefile gamin/Makefile >--- /usr/ports/devel/gamin/Makefile Sat Apr 2 11:08:46 2005 >+++ gamin/Makefile Wed Apr 6 18:57:30 2005 >@@ -7,7 +7,7 @@ > > PORTNAME= gamin > PORTVERSION= 0.0.26 >-PORTREVISION?= 8 >+PORTREVISION?= 9 > CATEGORIES?= devel > MASTER_SITES= http://www.gnome.org/~veillard/gamin/sources/ > >diff -ruN /usr/ports/devel/gamin/files/patch-server_gam_kqueue.c gamin/files/patch-server_gam_kqueue.c >--- /usr/ports/devel/gamin/files/patch-server_gam_kqueue.c Sat Apr 2 11:08:47 2005 >+++ gamin/files/patch-server_gam_kqueue.c Wed Apr 6 18:57:11 2005 >@@ -1,8 +1,9 @@ >---- server/gam_kqueue.c.orig Thu Mar 31 20:39:54 2005 >-+++ server/gam_kqueue.c Fri Apr 1 01:09:11 2005 >-@@ -0,0 +1,636 @@ >+--- server/gam_kqueue.c.orig Wed Apr 6 18:21:46 2005 >++++ server/gam_kqueue.c Wed Apr 6 18:57:07 2005 >+@@ -0,0 +1,712 @@ > +/* > + * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org> >++ * Copyright (C) 2005 Jean-Yves Lefort <jylefort@brutele.be> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public >@@ -22,6 +23,7 @@ > + > +#include <config.h> > +#include <sys/types.h> >++#include <sys/stat.h> > +#include <sys/event.h> > +#include <sys/time.h> > +#include <fcntl.h> >@@ -47,6 +49,19 @@ > + GSList *dirlist; > +} KQueueData; > + >++typedef struct >++{ >++ time_t mtime; >++ time_t ctime; >++ off_t size; >++} MiniStat; >++ >++typedef struct { >++ char *filename; >++ char *pathname; >++ MiniStat sb; >++} FileData; >++ > +static GHashTable *dir_path_hash = NULL; > +static GHashTable *file_path_hash = NULL; > +static GHashTable *fd_hash = NULL; >@@ -80,70 +95,42 @@ > + return data; > +} > + >-+static GSList * >-+gam_kqueue_lsdir(const char *path) >++static void >++gam_kqueue_mini_stat (const char *pathname, MiniStat *mini_sb) > +{ >-+ GDir *dir; >-+ GSList *lst = NULL; >-+ const gchar *entry; >-+ >-+ if (!path) >-+ return NULL; >++ struct stat sb; > + >-+ dir = g_dir_open(path, 0, NULL); >-+ if (!dir) >-+ return NULL; >-+ >-+ entry = g_dir_read_name(dir); >-+ >-+ while (entry) { >-+ lst = g_slist_prepend(lst, g_strdup(entry)); >-+ entry = g_dir_read_name(dir); >++ if (stat(pathname, &sb) == 0) { >++ mini_sb->mtime = sb.st_mtime; >++ mini_sb->ctime = sb.st_ctime; >++ mini_sb->size = sb.st_size; >++ } else { >++ mini_sb->mtime = 0; >++ mini_sb->ctime = 0; >++ mini_sb->size = 0; > + } >-+ >-+ g_dir_close(dir); >-+ >-+ return lst; > +} > + >-+static void >-+gam_kqueue_cmplst(GSList *lst1, GSList *lst2, GSList **added, GSList **deleted) >++static FileData * >++gam_kqueue_file_data_new (const char *path, const char *filename) > +{ >-+ int found; >-+ GSList *l; >-+ >-+ if (!lst1 && !lst2) >-+ return; >++ FileData *fdata; >++ struct stat sb; > + >-+ if (!lst1) { >-+ *added = g_slist_copy(lst2); >-+ return; >-+ } >-+ >-+ if (!lst2) { >-+ *deleted = g_slist_copy(lst1); >-+ return; >-+ } >++ fdata = g_new(FileData, 1); >++ fdata->filename = g_strdup(filename); >++ fdata->pathname = g_build_filename(path, filename, NULL); >++ gam_kqueue_mini_stat(fdata->pathname, &fdata->sb); > + >-+ for (l = lst1; l; l = l->next) { >-+ found = 0; >-+ if (g_slist_find_custom(lst2, l->data, (GCompareFunc)strcmp)) { >-+ found = 1; >-+ } >-+ if (found == 0) { >-+ *deleted = g_slist_prepend(*deleted, l->data); >-+ } >-+ } >++ return fdata; >++} > + >-+ for (l = lst2; l; l = l->next) { >-+ found = 0; >-+ if (g_slist_find_custom(lst1, l->data, (GCompareFunc)strcmp)) { >-+ found = 1; >-+ } >-+ if (found == 0) { >-+ *added = g_slist_prepend(*added, l->data); >-+ } >-+ } >++static void >++gam_kqueue_file_data_free (FileData *fdata) >++{ >++ g_free(fdata->filename); >++ g_free(fdata->pathname); >++ g_free(fdata); > +} > + > +static void >@@ -151,7 +138,7 @@ > +{ > + g_free(data->path); > + if (data->dirlist) { >-+ g_slist_foreach(data->dirlist, (GFunc)g_free, NULL); >++ g_slist_foreach(data->dirlist, (GFunc)gam_kqueue_file_data_free, NULL); > + g_slist_free(data->dirlist); > + } > + if (data->subs) { >@@ -160,6 +147,12 @@ > + g_free(data); > +} > + >++static int >++gam_kqueue_dirlist_find (FileData *fdata, const char *filename) >++{ >++ return strcmp(fdata->filename, filename); >++} >++ > +static void > +gam_kqueue_add_rm_handler(const char *path, GamSubscription *sub, gboolean added, gboolean was_missing) > +{ >@@ -230,21 +223,29 @@ > + gam_server_emit_event (path, isdir, GAMIN_EVENT_CREATED, subs, 1); > + } > + if (gam_subscription_is_dir(sub) && isdir) { >-+ GSList *l; >++ GDir *dir; > + > + data->isdir = TRUE; >-+ data->dirlist = gam_kqueue_lsdir(path); >++ data->dirlist = NULL; > + >-+ for (l = data->dirlist; l; l = l->next) { >-+ char *tmpentry; >-+ >-+ tmpentry = g_build_filename(path, l->data, NULL); >-+ if (!was_missing) { >-+ gam_server_emit_event (tmpentry, >-+ g_file_test(tmpentry, G_FILE_TEST_IS_DIR), >-+ GAMIN_EVENT_EXISTS, subs, 1); >++ dir = g_dir_open(path, 0, NULL); >++ if (dir) { >++ const char *entry; >++ >++ while ((entry = g_dir_read_name(dir))) { >++ FileData *fdata; >++ >++ fdata = gam_kqueue_file_data_new(path, entry); >++ data->dirlist = g_slist_prepend(data->dirlist, fdata); >++ >++ if (!was_missing) { >++ gam_server_emit_event(fdata->pathname, >++ g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR), >++ GAMIN_EVENT_EXISTS, subs, 1); >++ } > + } >-+ g_free(tmpentry); >++ >++ g_dir_close(dir); > + } > + } > + >@@ -332,44 +333,50 @@ > + isdir = g_file_test(data->path, G_FILE_TEST_IS_DIR); > + > + if (gevent == GAMIN_EVENT_CHANGED && data->isdir) { >-+ GSList *dirlist = NULL, *added = NULL, *deleted = NULL; >++ GSList *dirlist = NULL; > + GSList *l; >++ GDir *dir; >++ >++ dir = g_dir_open(data->path, 0, NULL); >++ if (dir) { >++ const char *entry; > + >-+ dirlist = gam_kqueue_lsdir(data->path); >-+ gam_kqueue_cmplst(data->dirlist, dirlist, &added, &deleted); >-+ if (added || deleted) { >-+ for (l = deleted; l; l = l->next) { >-+ data->dirlist = g_slist_remove(data->dirlist, l->data); >-+ event_path = g_build_filename(data->path, l->data, NULL); >-+ g_free(l->data); >-+ isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR); >-+ >-+ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_DELETED) , event_path); >-+ >-+ gam_server_emit_event (event_path, isdir, >-+ GAMIN_EVENT_DELETED, data->subs, 1); >-+ g_free(event_path); >++ while ((entry = g_dir_read_name(dir))) { >++ dirlist = g_slist_prepend(dirlist, g_strdup(entry)); > + } > + >-+ for (l = added; l; l = l->next) { >-+ dirlist = g_slist_remove(dirlist, l->data); >-+ data->dirlist = g_slist_prepend(data->dirlist, >-+ g_strdup(l->data)); >-+ event_path = g_build_filename(data->path, l->data, NULL); >-+ g_free(l->data); >-+ isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR); >-+ >-+ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CREATED) , event_path); >-+ >-+ gam_server_emit_event (event_path, isdir, >-+ GAMIN_EVENT_CREATED, data->subs, 1); >-+ g_free(event_path); >++ g_dir_close(dir); >++ } >++ >++ for (l = dirlist; l; l = l->next) { >++ if (! g_slist_find_custom(data->dirlist, l->data, (GCompareFunc) gam_kqueue_dirlist_find)) { >++ FileData *fdata; >++ >++ fdata = gam_kqueue_file_data_new(data->path, l->data); >++ data->dirlist = g_slist_prepend(data->dirlist, fdata); >++ >++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CREATED), fdata->pathname); >++ gam_server_emit_event(fdata->pathname, >++ g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR), >++ GAMIN_EVENT_CREATED, data->subs, 1); > + } >++ } >++ >++ iterate: >++ for (l = data->dirlist; l; l = l->next) { >++ FileData *fdata = l->data; >++ >++ if (! g_slist_find_custom(dirlist, fdata->filename, (GCompareFunc) strcmp)) { >++ data->dirlist = g_slist_remove(data->dirlist, fdata); > + >-+ if (added) >-+ g_slist_free(added); >-+ if (deleted) >-+ g_slist_free(deleted); >++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_DELETED), fdata->pathname); >++ gam_server_emit_event(fdata->pathname, >++ g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR), >++ GAMIN_EVENT_DELETED, data->subs, 1); >++ >++ gam_kqueue_file_data_free(fdata); >++ goto iterate; /* list changed, start again */ >++ } > + } > + > + if (dirlist) { >@@ -380,6 +387,22 @@ > + } > + else { > + event_path = g_strdup (data->path); >++ >++ if (gevent == GAMIN_EVENT_DELETED >++ || gevent == GAMIN_EVENT_ENDEXISTS >++ || gevent == GAMIN_EVENT_MOVED) { >++ /* close and move to exist_list, to catch next creation */ >++ close(data->fd); >++ if (data->isdir) { >++ g_hash_table_remove(dir_path_hash, data->path); >++ } >++ else { >++ g_hash_table_remove(file_path_hash, data->path); >++ } >++ g_hash_table_remove(fd_hash, GINT_TO_POINTER(data->fd)); >++ >++ exist_list = g_slist_append(exist_list, data); >++ } > + } > + > + isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR); >@@ -418,8 +441,47 @@ > + return TRUE; > +} > + >++static void >++gam_kqueue_dirlist_check_cb (const char *path, KQueueData *data, gpointer user_data) >++{ >++ GSList *l; >++ >++ for (l = data->dirlist; l; l = l->next) { >++ FileData *fdata = l->data; >++ MiniStat sb; >++ >++ gam_kqueue_mini_stat(fdata->pathname, &sb); >++ >++ if (sb.mtime != fdata->sb.mtime >++ || sb.ctime != fdata->sb.ctime >++ || sb.size != fdata->sb.size) >++ { >++ memcpy(&fdata->sb, &sb, sizeof(sb)); >++ >++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CHANGED), fdata->pathname); >++ gam_server_emit_event(fdata->pathname, >++ g_file_test(fdata->pathname, G_FILE_TEST_IS_DIR), >++ GAMIN_EVENT_CHANGED, data->subs, 1); >++ } >++ } >++} >++ >++static gboolean >++gam_kqueue_dirlist_check (gpointer user_data) >++{ >++ G_LOCK(kqueue); >++ >++ GAM_DEBUG(DEBUG_INFO, "gam_kqueue_dirlist_check()\n"); >++ >++ g_hash_table_foreach(dir_path_hash, (GHFunc) gam_kqueue_dirlist_check_cb, NULL); >++ >++ G_UNLOCK(kqueue); >++ >++ return TRUE; >++} >++ > +static gboolean >-+gam_kqueue_event_handler (gpointer user_data) >++gam_kqueue_event_handler (GIOChannel *source, GIOCondition condition, gpointer user_data) > +{ > + KQueueData *data; > + struct kevent ev[1]; >@@ -531,6 +593,8 @@ > +gboolean > +gam_kqueue_init(void) > +{ >++ GIOChannel *channel; >++ > + kq = kqueue(); > + if (kq == -1) { > + GAM_DEBUG(DEBUG_INFO, "Could not initialize a new kqueue\n"); >@@ -538,11 +602,23 @@ > + } > + > + g_timeout_add(1000, gam_kqueue_exist_check, NULL); >-+ g_timeout_add(1000, gam_kqueue_event_handler, NULL); >++ >++ channel = g_io_channel_unix_new(kq); >++ g_io_add_watch(channel, G_IO_IN, gam_kqueue_event_handler, NULL); > + > + dir_path_hash = g_hash_table_new(g_str_hash, g_str_equal); > + file_path_hash = g_hash_table_new(g_str_hash, g_str_equal); > + fd_hash = g_hash_table_new(g_direct_hash, g_direct_equal); >++ >++ /* >++ * gam_kqueue_dirlist_check() has to stat() every file in every >++ * monitored directory. This can easily become an intensive task >++ * if a few large directories are monitored (for instance a mail >++ * checker monitoring a couple of Maildir folders), therefore we >++ * use a reasonable poll interval (6 seconds, same as FAM's >++ * default). >++ */ >++ g_timeout_add(6000, gam_kqueue_dirlist_check, NULL); > + > + GAM_DEBUG(DEBUG_INFO, "kqueue initialized\n"); > +
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 79605
: 52560