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