Magellan Linux

Contents of /trunk/fam/patches/fam-2.7.0-dnotify.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 144 - (show annotations) (download)
Tue May 8 20:06:05 2007 UTC (17 years ago) by niro
File size: 26419 byte(s)
-import

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 */