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

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