source: scripts/untested/blfs-patches/fam-2.7.0-dnotify-1.patch@ def3913

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since def3913 was 617118d, checked in by Jim Gifford <clfs@…>, 19 years ago

r561@server (orig r559): root | 2005-06-05 02:38:49 -0700
Fixed Directory Structure

  • Property mode set to 100644
File size: 26.6 KB
RevLine 
[617118d]1Submitted By: Jim Gifford (jim at linuxfromscratch dot org)
2Date: 2004-03-15
3Initial Package Version: Jim Gifford
4Origin: Debian Maintainer of FAM
5Description: Dnotify Patch for FAM 2.7.0
6
7$LastChangedBy: bdubbs $
8$Date: 2004-08-07 18:56:30 -0600 (Sat, 07 Aug 2004) $
9
10diff -Naur fam-2.7.0.orig/config.h.in fam-2.7.0/config.h.in
11--- fam-2.7.0.orig/config.h.in 2003-01-20 00:40:15.000000000 +0000
12+++ fam-2.7.0/config.h.in 2004-03-15 21:31:34.553059530 +0000
13@@ -180,3 +180,6 @@
14
15 /* Define to `int' if <sys/types.h> doesn't define. */
16 #undef uid_t
17+
18+/* Define to 1 if you have F_NOTIFY fcntl */
19+#undef USE_DNOTIFY
20diff -Naur fam-2.7.0.orig/configure.ac fam-2.7.0/configure.ac
21--- fam-2.7.0.orig/configure.ac 2003-11-26 19:47:59.000000000 +0000
22+++ fam-2.7.0/configure.ac 2004-03-15 21:31:34.556058981 +0000
23@@ -33,7 +33,26 @@
24 AC_HEADER_DIRENT
25 AC_CHECK_HEADERS([fcntl.h limits.h linux/imon.h netinet/in.h rpc/rpc.h rpcsvc/mount.h stddef.h stdlib.h string.h syslog.h sys/imon.h sys/param.h sys/select.h sys/statvfs.h sys/syssgi.h sys/time.h sys/types.h sys/un.h unistd.h])
26
27-if test "$have_sys_imon_h"; then
28+# Test for the linux dnotify fcntl
29+AC_MSG_CHECKING([for dnotify fcntl support])
30+AC_TRY_COMPILE([
31+#define _GNU_SOURCE
32+#include <fcntl.h>
33+#include <unistd.h>
34+],
35+[ int fd = 1;
36+ fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)
37+ |DN_MULTISHOT);
38+], have_dnotify=yes, have_dnotify=no)
39+
40+use_dnotify=false
41+AC_MSG_RESULT($have_dnotify)
42+
43+if test "$have_dnotify"; then
44+ MONITOR_FUNCS=IMonNone
45+ AC_DEFINE([USE_DNOTIFY], [], [Use dnotify])
46+ use_dnotify=true
47+elif test "$have_sys_imon_h"; then
48 MONITOR_FUNCS=IMonIRIX
49 elif test "$have_linux_imon_h"; then
50 MONITOR_FUNCS=IMonLinux
51@@ -41,6 +60,7 @@
52 MONITOR_FUNCS=IMonNone
53 fi
54 AC_SUBST(MONITOR_FUNCS)
55+AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify)
56
57 # Checks for typedefs, structures, and compiler characteristics.
58 AC_HEADER_STDBOOL
59diff -Naur fam-2.7.0.orig/src/DNotify.c++ fam-2.7.0/src/DNotify.c++
60--- fam-2.7.0.orig/src/DNotify.c++ 1970-01-01 00:00:00.000000000 +0000
61+++ fam-2.7.0/src/DNotify.c++ 2004-03-15 21:31:34.542061543 +0000
62@@ -0,0 +1,582 @@
63+// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
64+// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved.
65+//
66+// This program is free software; you can redistribute it and/or modify it
67+// under the terms of version 2 of the GNU General Public License as
68+// published by the Free Software Foundation.
69+//
70+// This program is distributed in the hope that it would be useful, but
71+// WITHOUT ANY WARRANTY; without even the implied warranty of
72+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
73+// license provided herein, whether implied or otherwise, is limited to
74+// this program in accordance with the express provisions of the GNU
75+// General Public License. Patent licenses, if any, provided herein do not
76+// apply to combinations of this program with other product or programs, or
77+// any other product whatsoever. This program is distributed without any
78+// warranty that the program is delivered free of the rightful claim of any
79+// third person by way of infringement or the like. See the GNU General
80+// Public License for more details.
81+//
82+// You should have received a copy of the GNU General Public License along
83+// with this program; if not, write the Free Software Foundation, Inc., 59
84+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
85+
86+#define _GNU_SOURCE
87+#include <fcntl.h>
88+
89+#include <string.h>
90+#include <signal.h>
91+#include <stdio.h>
92+#include <unistd.h>
93+#include <sys/types.h>
94+#include <sys/stat.h>
95+#include <libgen.h>
96+
97+#include "DNotify.h"
98+
99+#include "Interest.h"
100+#include "Log.h"
101+#include "Scheduler.h"
102+#include <memory>
103+
104+
105+int DNotify::pipe_write_fd = -2;
106+int DNotify::pipe_read_fd = -2;
107+volatile sig_atomic_t DNotify::queue_overflowed = 0;
108+volatile sig_atomic_t DNotify::queue_changed = 0;
109+int DNotify::change_queue[QUEUESIZE];
110+volatile int DNotify::queue_head = 0; // Only modified by read handler
111+volatile int DNotify::queue_tail = 0; // Only modified by signal handler
112+DNotify::EventHandler DNotify::ehandler;
113+
114+DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE];
115+DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE];
116+
117+struct DNotify::FileWatch
118+{
119+ DirWatch *dir_watch;
120+ dev_t file_dev;
121+ ino_t file_ino;
122+ FileWatch *next; // The DirWatch.watches list
123+ FileWatch *hash_link;
124+};
125+
126+struct DNotify::DirWatch
127+{
128+ int fd;
129+ dev_t dir_dev;
130+ ino_t dir_ino;
131+
132+ DirWatch *hash_link;
133+ FileWatch *watches;
134+};
135+
136+struct DNotify::ChangeEventData
137+{
138+ dev_t file_dev;
139+ ino_t file_ino;
140+};
141+
142+DNotify::DNotify(EventHandler h)
143+{
144+ assert(ehandler == NULL);
145+ ehandler = h;
146+}
147+
148+DNotify::~DNotify()
149+{
150+ if (pipe_read_fd >= 0)
151+ {
152+ // Tell the scheduler.
153+
154+ (void) Scheduler::remove_read_handler(pipe_read_fd);
155+
156+ // Close the pipe.
157+
158+ if (close(pipe_read_fd) < 0)
159+ Log::perror("can't pipe read end");
160+ else
161+ Log::debug("closed pipe read end");
162+
163+ if (close(pipe_write_fd) < 0)
164+ Log::perror("can't pipe write end");
165+ else
166+ Log::debug("closed pipe write end");
167+ pipe_read_fd = -1;
168+ }
169+ ehandler = NULL;
170+}
171+
172+void
173+DNotify::overflow_signal_handler(int sig, siginfo_t *si, void *data)
174+{
175+ char c = 'x';
176+
177+ {
178+ char *str = "*************** overflow sigqueue ***********************\n";
179+ write (STDERR_FILENO, str, strlen(str));
180+ }
181+
182+ if (!queue_overflowed)
183+ {
184+ queue_overflowed = 1;
185+ // Trigger the read handler
186+ write(pipe_write_fd, &c, 1);
187+ }
188+}
189+
190+void
191+DNotify::signal_handler(int sig, siginfo_t *si, void *data)
192+{
193+ int left;
194+ char c = 'x';
195+
196+ if (queue_head <= queue_tail)
197+ left = (QUEUESIZE + queue_head) - queue_tail;
198+ else
199+ left = queue_head - queue_tail;
200+
201+ // Must leave at least one item unused to see difference
202+ // Betweeen empty and full
203+ if (left <= 1)
204+ {
205+ queue_overflowed = 1;
206+ {
207+ char *str = "*************** overflow famqueue ****************\n";
208+ write (STDERR_FILENO, str, strlen(str));
209+ }
210+ }
211+ else
212+ {
213+ change_queue[queue_tail] = si->si_fd;
214+ queue_tail = (queue_tail + 1) % QUEUESIZE;
215+ }
216+
217+ if (!queue_changed)
218+ {
219+ queue_changed = 1;
220+ // Trigger the read handler
221+ write(pipe_write_fd, &c, 1);
222+ }
223+}
224+
225+bool
226+DNotify::is_active()
227+{
228+ if (pipe_read_fd == -2)
229+ {
230+ int filedes[2];
231+ int res;
232+
233+ res = pipe (filedes);
234+ if (res >= 0)
235+ { Log::debug("opened pipe");
236+ pipe_read_fd = filedes[0];
237+ pipe_write_fd = filedes[1];
238+
239+ // Setup signal handler:
240+ struct sigaction act;
241+
242+ act.sa_sigaction = signal_handler;
243+ sigemptyset(&act.sa_mask);
244+ act.sa_flags = SA_SIGINFO;
245+ sigaction(SIGRTMIN, &act, NULL);
246+
247+ // When the RT queue overflows we get a SIGIO
248+ act.sa_sigaction = overflow_signal_handler;
249+ sigemptyset(&act.sa_mask);
250+ sigaction(SIGIO, &act, NULL);
251+
252+ (void) Scheduler::install_read_handler(pipe_read_fd, read_handler, NULL);
253+ }
254+ }
255+ return pipe_read_fd >= 0;
256+}
257+
258+DNotify::DirWatch *
259+DNotify::lookup_dirwatch (int fd)
260+{
261+ DirWatch **p;
262+ DirWatch *w;
263+
264+ p = dir_hashchain (fd);
265+
266+ while (*p)
267+ {
268+ w = *p;
269+
270+ if (w->fd == fd)
271+ return w;
272+
273+ p = &w->hash_link;
274+ }
275+
276+ return *p;
277+}
278+
279+// This colud be made faster by using another hash table.
280+// But it's not that bad, since it is only used by express/revoke
281+DNotify::DirWatch *
282+DNotify::lookup_dirwatch (dev_t dir_dev, ino_t dir_ino)
283+{
284+ DirWatch *p;
285+ int i;
286+
287+ for (i=0;i<DIR_HASHSIZE;i++)
288+ {
289+ p = dir_hash[i];
290+
291+ while (p)
292+ {
293+ if (p->dir_dev == dir_dev && p->dir_ino == dir_ino)
294+ return p;
295+
296+ p = p->hash_link;
297+ }
298+ }
299+
300+ return NULL;
301+}
302+
303+DNotify::FileWatch *
304+DNotify::lookup_filewatch (dev_t dev, ino_t ino)
305+{
306+ FileWatch **p;
307+ FileWatch *w;
308+
309+ p = file_hashchain (dev, ino);
310+
311+ while (*p)
312+ {
313+ w = *p;
314+
315+ if (w->file_dev == dev && w->file_ino == ino)
316+ return w;
317+
318+ p = &w->hash_link;
319+ }
320+
321+ return *p;
322+}
323+
324+// Make sure w is not already in the hash table before calling
325+// this function.
326+void
327+DNotify::hash_dirwatch(DirWatch *w)
328+{
329+ DirWatch **p;
330+ p = dir_hashchain (w->fd);
331+ w->hash_link = *p;
332+ *p = w;
333+}
334+
335+// Make sure w is not already in the hash table before calling
336+// this function.
337+void
338+DNotify::hash_filewatch(FileWatch *w)
339+{
340+ FileWatch **p;
341+ p = file_hashchain (w->file_dev, w->file_ino);
342+ w->hash_link = *p;
343+ *p = w;
344+}
345+
346+void
347+DNotify::unhash_dirwatch(DirWatch *w)
348+{
349+ DirWatch **p;
350+
351+ p = dir_hashchain (w->fd);
352+
353+ while (*p)
354+ {
355+ if (*p == w)
356+ {
357+ *p = w->hash_link;
358+ break;
359+ }
360+ p = &(*p)->hash_link;
361+ }
362+ w->hash_link = NULL;
363+}
364+
365+void
366+DNotify::unhash_filewatch(FileWatch *w)
367+{
368+ FileWatch **p;
369+
370+ p = file_hashchain (w->file_dev, w->file_ino);
371+
372+ while (*p)
373+ {
374+ if (*p == w)
375+ {
376+ *p = w->hash_link;
377+ break;
378+ }
379+ p = &(*p)->hash_link;
380+ }
381+ w->hash_link = NULL;
382+}
383+
384+DNotify::Status
385+DNotify::watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino)
386+{
387+ struct stat stat;
388+ dev_t dir_dev;
389+ ino_t dir_ino;
390+ DirWatch *dwatch;
391+ FileWatch *fw;
392+
393+ if (lstat (notify_dir, &stat) == -1)
394+ return BAD;
395+
396+ dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino);
397+ if (!dwatch)
398+ {
399+ Log::debug ("New DirWatch for %s (%x %x)\n",
400+ notify_dir, (int)stat.st_dev, (int)stat.st_ino);
401+ dwatch = new DirWatch;
402+ dwatch->watches = NULL;
403+ dwatch->hash_link = NULL;
404+ dwatch->dir_dev = stat.st_dev;
405+ dwatch->dir_ino = stat.st_ino;
406+
407+ dwatch->fd = open(notify_dir, O_RDONLY);
408+ fcntl (dwatch->fd, F_SETSIG, SIGRTMIN);
409+ if (fcntl (dwatch->fd, F_NOTIFY,
410+ (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)
411+ | DN_MULTISHOT) == -1) {
412+ return BAD;
413+ }
414+ hash_dirwatch (dwatch);
415+ }
416+
417+ fw = lookup_filewatch (file_dev, file_ino);
418+ if (fw && fw->dir_watch == dwatch)
419+ return OK;
420+
421+ // No old FileWatch, need to add one:
422+ Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino);
423+ fw = new FileWatch;
424+ fw->next = dwatch->watches;
425+ dwatch->watches = fw;
426+ fw->file_dev = file_dev;
427+ fw->file_ino = file_ino;
428+ fw->dir_watch = dwatch;
429+ hash_filewatch(fw);
430+ return OK;
431+}
432+
433+char *
434+dirname_dup (const char *name)
435+{
436+ char *copy = strdup(name);
437+ char *res = dirname(copy);
438+ res = strdup(res);
439+ free (copy);
440+ return res;
441+}
442+
443+DNotify::Status
444+DNotify::express(const char *name, struct stat *status)
445+{
446+ struct stat stat;
447+ char *notify_dir;
448+ int res;
449+ Status s;
450+ dev_t dev;
451+ ino_t ino;
452+
453+ Log::debug("express() name: %s\n", name);
454+
455+ if (!is_active())
456+ return BAD;
457+
458+ if (::lstat (name, &stat) == -1)
459+ return BAD;
460+
461+ dev = stat.st_dev;
462+ ino = stat.st_ino;
463+
464+ if ((stat.st_mode & S_IFMT) != S_IFDIR)
465+ notify_dir = dirname_dup (name);
466+ else
467+ notify_dir = (char *)name;
468+
469+ s = watch_dir (notify_dir, dev, ino);
470+ if (notify_dir != name)
471+ free (notify_dir);
472+ if (s)
473+ return s;
474+
475+ // Check for a race condition; if someone removed or changed the
476+ // file at the same time that we are expressing interest in it,
477+ // revoke the interest so we don't get notifications about changes
478+ // to a recycled inode that we don't otherwise care about.
479+ //
480+ struct stat st;
481+ if (status == NULL) {
482+ status = &st;
483+ }
484+ if (::lstat(name, status) == -1) {
485+ Log::perror("stat on \"%s\" failed", name);
486+ revoke(name, stat.st_dev, stat.st_ino);
487+ return BAD;
488+ }
489+ if (status->st_dev != stat.st_dev
490+ || status->st_ino != stat.st_ino) {
491+ Log::error("File \"%s\" changed between express and stat",
492+ name);
493+ revoke(name, stat.st_dev, stat.st_ino);
494+ return BAD;
495+ }
496+
497+ Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name,
498+ major(status->st_dev), minor(status->st_dev),
499+ status->st_ino);
500+ return OK;
501+}
502+
503+DNotify::Status
504+DNotify::revoke(const char *name, dev_t dev, ino_t ino)
505+{
506+ FileWatch *fwatch;
507+ DirWatch *dwatch;
508+
509+ Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino);
510+
511+ if (!is_active())
512+ return BAD;
513+
514+ // Lookup FileWatch by dev:ino, and its DirWatch.
515+ fwatch = lookup_filewatch (dev, ino);
516+ if (fwatch == NULL)
517+ return BAD;
518+
519+ dwatch = fwatch->dir_watch;
520+
521+ // delete FileWatch, if last FileWatch: close fd, delete DirWatch
522+ Log::debug ("Destroying FileWatch for (%x %x)\n",
523+ (int)fwatch->file_dev, (int)fwatch->file_ino);
524+ FileWatch **p;
525+ for (p=&dwatch->watches; *p; p=&(*p)->next)
526+ {
527+ if (*p == fwatch)
528+ {
529+ *p = (*p)->next;
530+ break;
531+ }
532+ }
533+ unhash_filewatch(fwatch);
534+ delete fwatch;
535+ if (dwatch->watches == NULL)
536+ {
537+ Log::debug ("Destroying DirWatch for (%x %x)\n",
538+ (int)dwatch->dir_dev, (int)dwatch->dir_ino);
539+ close(dwatch->fd);
540+ unhash_dirwatch(dwatch);
541+ delete dwatch;
542+ }
543+
544+ return OK;
545+}
546+
547+
548+void
549+DNotify::all_watches_changed(void)
550+{
551+ int i;
552+ FileWatch *fw;
553+
554+ for (i=0; i<FILE_HASHSIZE; i++)
555+ {
556+ fw = file_hash[i];
557+ while (fw)
558+ {
559+ (*ehandler)(fw->file_dev, fw->file_ino, CHANGE);
560+
561+ fw = fw->hash_link;
562+ }
563+ }
564+}
565+
566+
567+void
568+DNotify::read_handler(int fd, void *)
569+{
570+ static char readbuf[5000];
571+ DirWatch *dw;
572+ FileWatch *fw;
573+ int snap_queue_tail;
574+ int last_fd;
575+
576+ int rc = read(fd, readbuf, sizeof readbuf);
577+ queue_changed = 0;
578+ if (rc < 0)
579+ Log::perror("pipe read");
580+ else if (queue_overflowed)
581+ {
582+ // There is a *slight* race condition here. Between reading
583+ // the queue_overflow flag and resetting it. But it doesn't
584+ // matter, since I'm gonna handle the overflow after reseting
585+ // anyway.
586+ queue_overflowed = false;
587+
588+ // We're soon gonna check all watches anyway, so
589+ // get rid of the current queue
590+ queue_head = queue_tail;
591+
592+ all_watches_changed ();
593+ }
594+ else
595+ {
596+ // Don't read events that happen later than
597+ // the initial read. (Otherwise skipping fd's
598+ // might miss some changes).
599+ snap_queue_tail = queue_tail;
600+ last_fd = -1;
601+ while (queue_head != snap_queue_tail)
602+ {
603+ fd = change_queue[queue_head];
604+ queue_head = (queue_head + 1) % QUEUESIZE;
605+
606+ // Skip multiple changes to the same fd
607+ if (fd != last_fd)
608+ {
609+ dw = lookup_dirwatch (fd);
610+ if (dw)
611+ {
612+ int n_watches, i;
613+ ChangeEventData *data;
614+
615+ Log::debug("dnotify said dev %d/%d, ino %ld changed",
616+ major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino);
617+
618+ n_watches = 0;
619+ for (fw=dw->watches; fw; fw=fw->next)
620+ n_watches++;
621+
622+ data = new ChangeEventData[n_watches];
623+
624+ i = 0;
625+ for (fw=dw->watches; fw; fw=fw->next)
626+ {
627+ data[i].file_dev = fw->file_dev;
628+ data[i].file_ino = fw->file_ino;
629+ i++;
630+ }
631+
632+ for (i = 0; i < n_watches; i++)
633+ {
634+ (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE);
635+ }
636+
637+ delete[] data;
638+ }
639+ }
640+ last_fd = fd;
641+ }
642+ }
643+}
644+
645diff -Naur fam-2.7.0.orig/src/DNotify.h fam-2.7.0/src/DNotify.h
646--- fam-2.7.0.orig/src/DNotify.h 1970-01-01 00:00:00.000000000 +0000
647+++ fam-2.7.0/src/DNotify.h 2004-03-15 21:31:34.546060811 +0000
648@@ -0,0 +1,98 @@
649+// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
650+// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved.
651+//
652+// This program is free software; you can redistribute it and/or modify it
653+// under the terms of version 2 of the GNU General Public License as
654+// published by the Free Software Foundation.
655+//
656+// This program is distributed in the hope that it would be useful, but
657+// WITHOUT ANY WARRANTY; without even the implied warranty of
658+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
659+// license provided herein, whether implied or otherwise, is limited to
660+// this program in accordance with the express provisions of the GNU
661+// General Public License. Patent licenses, if any, provided herein do not
662+// apply to combinations of this program with other product or programs, or
663+// any other product whatsoever. This program is distributed without any
664+// warranty that the program is delivered free of the rightful claim of any
665+// third person by way of infringement or the like. See the GNU General
666+// Public License for more details.
667+//
668+// You should have received a copy of the GNU General Public License along
669+// with this program; if not, write the Free Software Foundation, Inc., 59
670+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
671+
672+#ifndef DNotify_included
673+#define DNotify_included
674+
675+#include "config.h"
676+#include "Monitor.h"
677+#include <signal.h>
678+
679+// DNotify is an object encapsulating the dnotify linux fcntl.
680+// It "emulates" the IMon interface.
681+// There can only be one instantiation of the DNotify object.
682+//
683+// The user of this object uses express() and revoke() to
684+// express/revoke interest in a file. There is also
685+// a callback, the EventHandler. When an dnotify event comes in,
686+// the EventHandler is called.
687+//
688+// The user of the DNotify object is the Interest class.
689+
690+class DNotify : public Monitor {
691+public:
692+ DNotify(EventHandler h);
693+ ~DNotify();
694+
695+ static bool is_active();
696+
697+ virtual Status express(const char *name, struct stat *stat_return);
698+ virtual Status revoke(const char *name, dev_t dev, ino_t ino);
699+
700+private:
701+ struct FileWatch;
702+ struct DirWatch;
703+ struct ChangeEventData;
704+
705+ // Class Variables
706+ enum { QUEUESIZE = 1024 };
707+ static int pipe_write_fd;
708+ static int pipe_read_fd;
709+ static int change_queue[QUEUESIZE];
710+ static volatile sig_atomic_t DNotify::queue_overflowed;
711+ static volatile sig_atomic_t DNotify::queue_changed;
712+ static volatile int queue_head; // Only modified by read handler
713+ static volatile int queue_tail; // Only modified by signal handler
714+ static EventHandler ehandler;
715+ static void overflow_signal_handler(int sig, siginfo_t *si, void *data);
716+ static void signal_handler(int sig, siginfo_t *si, void *data);
717+ static void read_handler(int fd, void *closure);
718+
719+ enum { DIR_HASHSIZE = 367 };
720+ static DirWatch *dir_hash[DIR_HASHSIZE];
721+ enum { FILE_HASHSIZE = 823 };
722+ static FileWatch *file_hash[FILE_HASHSIZE];
723+
724+ static DirWatch **dir_hashchain(int fd)
725+ { return &dir_hash[(unsigned) (fd) % DIR_HASHSIZE]; }
726+ static FileWatch **file_hashchain(dev_t d, ino_t i)
727+ { return &file_hash[(unsigned) (d+i) % FILE_HASHSIZE]; }
728+
729+ static DirWatch *lookup_dirwatch (int fd);
730+ static DirWatch *lookup_dirwatch (dev_t dir_dev, ino_t dir_ino);
731+ static FileWatch *lookup_filewatch (dev_t file_dev, ino_t file_ino);
732+ static void hash_dirwatch(DirWatch *w);
733+ static void hash_filewatch(FileWatch *w);
734+ static void unhash_dirwatch(DirWatch *w);
735+ static void unhash_filewatch(FileWatch *w);
736+ static Status watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino);
737+
738+ static void all_watches_changed(void);
739+
740+ DNotify(const DNotify&); // Do not copy
741+ DNotify & operator = (const DNotify&); // or assign.
742+};
743+
744+#endif /* !IMon_included */
745+
746+
747diff -Naur fam-2.7.0.orig/src/IMon.h fam-2.7.0/src/IMon.h
748--- fam-2.7.0.orig/src/IMon.h 2003-01-18 14:18:12.000000000 +0000
749+++ fam-2.7.0/src/IMon.h 2004-03-15 21:31:34.558058615 +0000
750@@ -24,10 +24,7 @@
751 #define IMon_included
752
753 #include "config.h"
754-#include <sys/stat.h>
755-#include <sys/types.h>
756-
757-#include "Boolean.h"
758+#include "Monitor.h"
759
760 struct stat;
761
762@@ -41,25 +38,18 @@
763 //
764 // The user of the IMon object is the Interest class.
765
766-class IMon {
767+class IMon : public Monitor {
768
769 public:
770-
771- enum Status { OK = 0, BAD = -1 };
772- enum Event { EXEC, EXIT, CHANGE };
773-
774- typedef void (*EventHandler)(dev_t, ino_t, int event);
775-
776 IMon(EventHandler h);
777 ~IMon();
778
779 static bool is_active();
780
781- Status express(const char *name, struct stat *stat_return);
782- Status revoke(const char *name, dev_t dev, ino_t ino);
783+ virtual Status express(const char *name, struct stat *stat_return);
784+ virtual Status revoke(const char *name, dev_t dev, ino_t ino);
785
786 private:
787-
788 // Class Variables
789
790 static int imonfd;
791diff -Naur fam-2.7.0.orig/src/Interest.c++ fam-2.7.0/src/Interest.c++
792--- fam-2.7.0.orig/src/Interest.c++ 2003-01-18 14:18:12.000000000 +0000
793+++ fam-2.7.0/src/Interest.c++ 2004-03-15 21:31:34.550060079 +0000
794@@ -42,12 +42,21 @@
795 #include "Event.h"
796 #include "FileSystem.h"
797 #include "IMon.h"
798+#include "DNotify.h"
799 #include "Log.h"
800 #include "Pollster.h"
801 #include "timeval.h"
802
803 Interest *Interest::hashtable[];
804-IMon Interest::imon(imon_handler);
805+
806+#ifdef USE_DNOTIFY
807+static DNotify dnotify(Interest::monitor_handler);
808+Monitor * Interest::monitor = &dnotify;
809+#else
810+static IMon imon(Interest::monitor_handler);
811+Monitor * Interest::monitor = &imon;
812+#endif
813+
814 bool Interest::xtab_verification = true;
815
816 Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev)
817@@ -60,10 +69,10 @@
818 mypath_exported_to_host(ev == NO_VERIFY_EXPORTED)
819 {
820 memset(&old_stat, 0, sizeof(old_stat));
821- IMon::Status s = IMon::BAD;
822
823- s = imon.express(name, &old_stat);
824- if (s != IMon::OK)
825+ Monitor::Status s = Monitor::BAD;
826+ s = monitor->express(name, &old_stat);
827+ if (s != Monitor::OK)
828 { int rc = lstat(name, &old_stat);
829 if (rc < 0)
830 { Log::info("can't lstat %s", name);
831@@ -100,7 +109,7 @@
832 }
833 #endif
834
835- if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK);
836+ if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK);
837 }
838
839 Interest::~Interest()
840@@ -128,7 +137,7 @@
841 pp = &p->hashlink; // move to next element
842 }
843 if (!found_same)
844- (void) imon.revoke(name(), dev, ino);
845+ (void) monitor->revoke(name(), dev, ino);
846 }
847 }
848
849@@ -147,7 +156,7 @@
850
851 // Express interest.
852 IMon::Status s = IMon::BAD;
853- s = imon.express(name(), NULL);
854+ s = monitor->express(name(), NULL);
855 if (s != IMon::OK) {
856 return true;
857 }
858@@ -248,23 +257,23 @@
859 }
860
861 void
862-Interest::imon_handler(dev_t device, ino_t inumber, int event)
863+Interest::monitor_handler(dev_t device, ino_t inumber, int event)
864 {
865 assert(device || inumber);
866
867 for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next)
868 { next = p->hashlink;
869 if (p->ino == inumber && p->dev == device)
870- { if (event == IMon::EXEC)
871+ { if (event == Monitor::EXEC)
872 { p->cur_exec_state = EXECUTING;
873 (void) p->report_exec_state();
874 }
875- else if (event == IMon::EXIT)
876+ else if (event == Monitor::EXIT)
877 { p->cur_exec_state = NOT_EXECUTING;
878 (void) p->report_exec_state();
879 }
880 else
881- { assert(event == IMon::CHANGE);
882+ { assert(event == Monitor::CHANGE);
883 p->scan();
884 }
885 }
886diff -Naur fam-2.7.0.orig/src/Interest.h fam-2.7.0/src/Interest.h
887--- fam-2.7.0.orig/src/Interest.h 2003-01-18 14:18:12.000000000 +0000
888+++ fam-2.7.0/src/Interest.h 2004-03-15 21:31:34.560058249 +0000
889@@ -32,7 +32,7 @@
890
891 class Event;
892 class FileSystem;
893-class IMon;
894+class Monitor;
895 struct stat;
896
897 // Interest -- abstract base class for filesystem entities of interest.
898@@ -74,7 +74,7 @@
899
900 // Public Class Method
901
902- static void imon_handler(dev_t, ino_t, int event);
903+ static void monitor_handler(dev_t, ino_t, int event);
904
905 static void enable_xtab_verification(bool enable);
906
907@@ -121,7 +121,7 @@
908
909 // Class Variables
910
911- static IMon imon;
912+ static Monitor *monitor;
913 static Interest *hashtable[HASHSIZE];
914 static bool xtab_verification;
915
916diff -Naur fam-2.7.0.orig/src/Makefile.am fam-2.7.0/src/Makefile.am
917--- fam-2.7.0.orig/src/Makefile.am 2003-01-19 12:00:17.000000000 +0000
918+++ fam-2.7.0/src/Makefile.am 2004-03-15 21:31:34.562057882 +0000
919@@ -71,7 +71,11 @@
920 main.c++ \
921 timeval.c++ \
922 timeval.h \
923- @MONITOR_FUNCS@.c++
924+ Monitor.h \
925+ DNotify.h \
926+ DNotify.c++ \
927+ @MONITOR_FUNCS@.c++
928
929-EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++
930+EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ \
931+ DNotify.h Monitor.h
932
933diff -Naur fam-2.7.0.orig/src/Monitor.h fam-2.7.0/src/Monitor.h
934--- fam-2.7.0.orig/src/Monitor.h 1970-01-01 00:00:00.000000000 +0000
935+++ fam-2.7.0/src/Monitor.h 2004-03-15 21:31:34.564057516 +0000
936@@ -0,0 +1,57 @@
937+// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
938+// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved.
939+//
940+// This program is free software; you can redistribute it and/or modify it
941+// under the terms of version 2 of the GNU General Public License as
942+// published by the Free Software Foundation.
943+//
944+// This program is distributed in the hope that it would be useful, but
945+// WITHOUT ANY WARRANTY; without even the implied warranty of
946+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
947+// license provided herein, whether implied or otherwise, is limited to
948+// this program in accordance with the express provisions of the GNU
949+// General Public License. Patent licenses, if any, provided herein do not
950+// apply to combinations of this program with other product or programs, or
951+// any other product whatsoever. This program is distributed without any
952+// warranty that the program is delivered free of the rightful claim of any
953+// third person by way of infringement or the like. See the GNU General
954+// Public License for more details.
955+//
956+// You should have received a copy of the GNU General Public License along
957+// with this program; if not, write the Free Software Foundation, Inc., 59
958+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
959+
960+#ifndef Monitor_included
961+#define Monitor_included
962+
963+#include "config.h"
964+#include <sys/stat.h>
965+#include <sys/types.h>
966+
967+struct stat;
968+
969+// Monitor is an abstract baseclass for differend file monitoring
970+// systems. The original system used was IMon, and the Montor API
971+// is heavily influenced by that.
972+// There can only be one instantiation of the Monitor object.
973+//
974+// The user of this object uses express() and revoke() to
975+// express/revoke interest in a file to imon. There is also
976+// a callback, the EventHandler. When an event comes in,
977+// the EventHandler is called.
978+//
979+// The main implementers of the Monitor class is IMon and DNotify
980+
981+class Monitor {
982+public:
983+
984+ enum Status { OK = 0, BAD = -1 };
985+ enum Event { EXEC, EXIT, CHANGE };
986+
987+ typedef void (*EventHandler)(dev_t, ino_t, int event);
988+
989+ virtual Status express(const char *name, struct stat *stat_return) = 0;
990+ virtual Status revoke(const char *name, dev_t dev, ino_t ino) = 0;
991+};
992+
993+#endif /* !Monitor_included */
Note: See TracBrowser for help on using the repository browser.