--- fam-2.6.9/include/BTree.h.dnotify 2002-07-16 07:23:25.000000000 +0200 +++ fam-2.6.9/include/BTree.h 2003-01-31 22:23:09.000000000 +0100 @@ -271,7 +271,7 @@ n += that->n + 1; link[n] = that->link[that->n]; that->n = 0; - that->link[0] = NULL; + that->link[0] = 0; } /////////////////////////////////////////////////////////////////////////////// @@ -280,7 +280,7 @@ template BTree::BTree() - : root(NULL), npairs(0) + : root(0), npairs(0) { assert(!(fanout % 2)); } @@ -407,7 +407,7 @@ BTree::Closure BTree::insert(Node *p, const Key& key, const Value& value) { - if (!p) return Closure(key, value, NULL); + if (!p) return Closure(key, value, 0); // If you're running Purify on a client linking with libfam, and it says // that line is causing a 3-byte UMR for BTree::insert() in // FAMNextEvent() ("Reading 8 bytes from 0x... on the stack (3 bytes at @@ -475,7 +475,7 @@ case UNDER: if (root->n == 0) { Node *nr = root->link[0]; - root->link[0] = NULL; // don't delete subtree + root->link[0] = 0; // don't delete subtree delete root; root = nr; } @@ -507,8 +507,8 @@ Node *cp = p->link[i]; assert(cp); - Node *rp = i < p->n ? p->link[i + 1] : NULL; - Node *lp = i > 0 ? p->link[i - 1] : NULL; + Node *rp = i < p->n ? p->link[i + 1] : 0; + Node *lp = i > 0 ? p->link[i - 1] : 0; assert(!rp || rp->n >= fanout / 2); assert(!lp || lp->n >= fanout / 2); --- fam-2.6.9/fam/DNotify.c++.dnotify 2003-01-31 22:23:09.000000000 +0100 +++ fam-2.6.9/fam/DNotify.c++ 2003-01-31 22:23:09.000000000 +0100 @@ -0,0 +1,583 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "DNotify.h" + +#include "Interest.h" +#include "Log.h" +#include "Scheduler.h" +#include "alloc.h" + + +int DNotify::pipe_write_fd = -2; +int DNotify::pipe_read_fd = -2; +volatile sig_atomic_t DNotify::queue_overflowed = 0; +volatile sig_atomic_t DNotify::queue_changed = 0; +int DNotify::change_queue[QUEUESIZE]; +volatile int DNotify::queue_head = 0; // Only modified by read handler +volatile int DNotify::queue_tail = 0; // Only modified by signal handler +DNotify::EventHandler DNotify::ehandler; + +DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE]; +DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE]; + +struct DNotify::FileWatch +{ + DirWatch *dir_watch; + dev_t file_dev; + ino_t file_ino; + FileWatch *next; // The DirWatch.watches list + FileWatch *hash_link; +}; + +struct DNotify::DirWatch +{ + int fd; + dev_t dir_dev; + ino_t dir_ino; + + DirWatch *hash_link; + FileWatch *watches; +}; + +struct DNotify::ChangeEventData +{ + dev_t file_dev; + ino_t file_ino; +}; + +DNotify::DNotify(EventHandler h) +{ + assert(ehandler == NULL); + ehandler = h; +} + +DNotify::~DNotify() +{ + if (pipe_read_fd >= 0) + { + // Tell the scheduler. + + (void) Scheduler::remove_read_handler(pipe_read_fd); + + // Close the pipe. + + if (close(pipe_read_fd) < 0) + Log::perror("can't pipe read end"); + else + Log::debug("closed pipe read end"); + + if (close(pipe_write_fd) < 0) + Log::perror("can't pipe write end"); + else + Log::debug("closed pipe write end"); + pipe_read_fd = -1; + } + ehandler = NULL; +} + +void +DNotify::overflow_signal_handler(int sig, siginfo_t *si, void *data) +{ + char c = 'x'; + + { + char *str = "*************** overflow sigqueue ***********************\n"; + write (STDERR_FILENO, str, strlen(str)); + } + + if (!queue_overflowed) + { + queue_overflowed = 1; + // Trigger the read handler + write(pipe_write_fd, &c, 1); + } +} + +void +DNotify::signal_handler(int sig, siginfo_t *si, void *data) +{ + int left; + char c = 'x'; + + if (queue_head <= queue_tail) + left = (QUEUESIZE + queue_head) - queue_tail; + else + left = queue_head - queue_tail; + + // Must leave at least one item unused to see difference + // Betweeen empty and full + if (left <= 1) + { + queue_overflowed = 1; + { + char *str = "*************** overflow famqueue ****************\n"; + write (STDERR_FILENO, str, strlen(str)); + } + } + else + { + change_queue[queue_tail] = si->si_fd; + queue_tail = (queue_tail + 1) % QUEUESIZE; + } + + if (!queue_changed) + { + queue_changed = 1; + // Trigger the read handler + write(pipe_write_fd, &c, 1); + } +} + +bool +DNotify::is_active() +{ + if (pipe_read_fd == -2) + { + int filedes[2]; + int res; + + res = pipe (filedes); + if (res >= 0) + { Log::debug("opened pipe"); + pipe_read_fd = filedes[0]; + pipe_write_fd = filedes[1]; + + // Setup signal handler: + struct sigaction act; + + act.sa_sigaction = signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGRTMIN, &act, NULL); + + // When the RT queue overflows we get a SIGIO + act.sa_sigaction = overflow_signal_handler; + sigemptyset(&act.sa_mask); + sigaction(SIGIO, &act, NULL); + + (void) Scheduler::install_read_handler(pipe_read_fd, read_handler, NULL); + } + } + return pipe_read_fd >= 0; +} + +DNotify::DirWatch * +DNotify::lookup_dirwatch (int fd) +{ + DirWatch **p; + DirWatch *w; + + p = dir_hashchain (fd); + + while (*p) + { + w = *p; + + if (w->fd == fd) + return w; + + p = &w->hash_link; + } + + return *p; +} + +// This colud be made faster by using another hash table. +// But it's not that bad, since it is only used by express/revoke +DNotify::DirWatch * +DNotify::lookup_dirwatch (dev_t dir_dev, ino_t dir_ino) +{ + DirWatch *p; + int i; + + for (i=0;idir_dev == dir_dev && p->dir_ino == dir_ino) + return p; + + p = p->hash_link; + } + } + + return NULL; +} + +DNotify::FileWatch * +DNotify::lookup_filewatch (dev_t dev, ino_t ino) +{ + FileWatch **p; + FileWatch *w; + + p = file_hashchain (dev, ino); + + while (*p) + { + w = *p; + + if (w->file_dev == dev && w->file_ino == ino) + return w; + + p = &w->hash_link; + } + + return *p; +} + +// Make sure w is not already in the hash table before calling +// this function. +void +DNotify::hash_dirwatch(DirWatch *w) +{ + DirWatch **p; + p = dir_hashchain (w->fd); + w->hash_link = *p; + *p = w; +} + +// Make sure w is not already in the hash table before calling +// this function. +void +DNotify::hash_filewatch(FileWatch *w) +{ + FileWatch **p; + p = file_hashchain (w->file_dev, w->file_ino); + w->hash_link = *p; + *p = w; +} + +void +DNotify::unhash_dirwatch(DirWatch *w) +{ + DirWatch **p; + + p = dir_hashchain (w->fd); + + while (*p) + { + if (*p == w) + { + *p = w->hash_link; + break; + } + p = &(*p)->hash_link; + } + w->hash_link = NULL; +} + +void +DNotify::unhash_filewatch(FileWatch *w) +{ + FileWatch **p; + + p = file_hashchain (w->file_dev, w->file_ino); + + while (*p) + { + if (*p == w) + { + *p = w->hash_link; + break; + } + p = &(*p)->hash_link; + } + w->hash_link = NULL; +} + +DNotify::Status +DNotify::watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino) +{ + struct stat stat; + dev_t dir_dev; + ino_t dir_ino; + DirWatch *dwatch; + FileWatch **p; + FileWatch *fw; + + if (lstat (notify_dir, &stat) == -1) + return BAD; + + dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino); + if (!dwatch) + { + Log::debug ("New DirWatch for %s (%x %x)\n", + notify_dir, (int)stat.st_dev, (int)stat.st_ino); + dwatch = new DirWatch; + dwatch->watches = NULL; + dwatch->hash_link = NULL; + dwatch->dir_dev = stat.st_dev; + dwatch->dir_ino = stat.st_ino; + + dwatch->fd = open(notify_dir, O_RDONLY); + fcntl (dwatch->fd, F_SETSIG, SIGRTMIN); + fcntl (dwatch->fd, F_NOTIFY, + (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB) | DN_MULTISHOT); + hash_dirwatch (dwatch); + } + + for (p=&dwatch->watches; *p; p=&(*p)->next) + { + fw = *p; + if (fw->file_dev == file_dev && fw->file_ino == file_ino) + return OK; + } + + // No old FileWatch, need to add one: + Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino); + *p = new FileWatch; + fw = *p; + fw->next = NULL; + fw->file_dev = file_dev; + fw->file_ino = file_ino; + fw->dir_watch = dwatch; + hash_filewatch(fw); + return OK; +} + +char * +dirname_dup (const char *name) +{ + char *copy = strdup(name); + char *res = dirname(copy); + res = strdup(res); + free (copy); + return res; +} + +DNotify::Status +DNotify::express(const char *name, struct stat *status) +{ + struct stat stat; + char *notify_dir; + int res; + Status s; + dev_t dev; + ino_t ino; + + Log::debug("express() name: %s\n", name); + + if (!is_active()) + return BAD; + + if (::lstat (name, &stat) == -1) + return BAD; + + dev = stat.st_dev; + ino = stat.st_ino; + + if ((stat.st_mode & S_IFMT) != S_IFDIR) + notify_dir = dirname_dup (name); + else + notify_dir = (char *)name; + + s = watch_dir (notify_dir, dev, ino); + if (notify_dir != name) + free (notify_dir); + if (s) + return s; + + // Check for a race condition; if someone removed or changed the + // file at the same time that we are expressing interest in it, + // revoke the interest so we don't get notifications about changes + // to a recycled inode that we don't otherwise care about. + // + struct stat st; + if (status == NULL) { + status = &st; + } + if (::lstat(name, status) == -1) { + Log::perror("stat on \"%s\" failed", name); + revoke(name, stat.st_dev, stat.st_ino); + return BAD; + } + if (status->st_dev != stat.st_dev + || status->st_ino != stat.st_ino) { + Log::error("File \"%s\" changed between express and stat", + name); + revoke(name, stat.st_dev, stat.st_ino); + return BAD; + } + + Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name, + major(status->st_dev), minor(status->st_dev), + status->st_ino); + return OK; +} + +DNotify::Status +DNotify::revoke(const char *name, dev_t dev, ino_t ino) +{ + FileWatch *fwatch; + DirWatch *dwatch; + + Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino); + + if (!is_active()) + return BAD; + + // Lookup FileWatch by dev:ino, and its DirWatch. + fwatch = lookup_filewatch (dev, ino); + if (fwatch == NULL) + return BAD; + + dwatch = fwatch->dir_watch; + + // delete FileWatch, if last FileWatch: close fd, delete DirWatch + Log::debug ("Destroying FileWatch for (%x %x)\n", + (int)fwatch->file_dev, (int)fwatch->file_ino); + FileWatch **p; + for (p=&dwatch->watches; *p; p=&(*p)->next) + { + if (*p == fwatch) + { + *p = (*p)->next; + break; + } + } + unhash_filewatch(fwatch); + delete fwatch; + if (dwatch->watches == NULL) + { + Log::debug ("Destroying DirWatch for (%x %x)\n", + (int)dwatch->dir_dev, (int)dwatch->dir_ino); + close(dwatch->fd); + unhash_dirwatch(dwatch); + delete dwatch; + } + + return OK; +} + + +void +DNotify::all_watches_changed(void) +{ + int i; + FileWatch *fw; + + for (i=0; ifile_dev, fw->file_ino, CHANGE); + + fw = fw->hash_link; + } + } +} + + +void +DNotify::read_handler(int fd, void *) +{ + static char readbuf[5000]; + DirWatch *dw; + FileWatch *fw; + int snap_queue_tail; + int last_fd; + + int rc = read(fd, readbuf, sizeof readbuf); + queue_changed = 0; + if (rc < 0) + Log::perror("pipe read"); + else if (queue_overflowed) + { + // There is a *slight* race condition here. Between reading + // the queue_overflow flag and resetting it. But it doesn't + // matter, since I'm gonna handle the overflow after reseting + // anyway. + queue_overflowed = false; + + // We're soon gonna check all watches anyway, so + // get rid of the current queue + queue_head = queue_tail; + + all_watches_changed (); + } + else + { + // Don't read events that happen later than + // the initial read. (Otherwise skipping fd's + // might miss some changes). + snap_queue_tail = queue_tail; + last_fd = -1; + while (queue_head != snap_queue_tail) + { + fd = change_queue[queue_head]; + queue_head = (queue_head + 1) % QUEUESIZE; + + // Skip multiple changes to the same fd + if (fd != last_fd) + { + dw = lookup_dirwatch (fd); + if (dw) + { + int n_watches, i; + ChangeEventData *data; + + Log::debug("dnotify said dev %d/%d, ino %ld changed", + major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino); + + n_watches = 0; + for (fw=dw->watches; fw; fw=fw->next) + n_watches++; + + data = new ChangeEventData[n_watches]; + + i = 0; + for (fw=dw->watches; fw; fw=fw->next) + { + data[i].file_dev = fw->file_dev; + data[i].file_ino = fw->file_ino; + i++; + } + + for (i = 0; i < n_watches; i++) + { + (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE); + } + + delete[] data; + } + } + last_fd = fd; + } + } +} + --- fam-2.6.9/fam/DNotify.h.dnotify 2003-01-31 22:23:09.000000000 +0100 +++ fam-2.6.9/fam/DNotify.h 2003-01-31 22:23:09.000000000 +0100 @@ -0,0 +1,98 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#ifndef DNotify_included +#define DNotify_included + +#include "config.h" +#include "Monitor.h" +#include + +// DNotify is an object encapsulating the dnotify linux fcntl. +// It "emulates" the IMon interface. +// There can only be one instantiation of the DNotify object. +// +// The user of this object uses express() and revoke() to +// express/revoke interest in a file. There is also +// a callback, the EventHandler. When an dnotify event comes in, +// the EventHandler is called. +// +// The user of the DNotify object is the Interest class. + +class DNotify : public Monitor { +public: + DNotify(EventHandler h); + ~DNotify(); + + static bool is_active(); + + virtual Status express(const char *name, struct stat *stat_return); + virtual Status revoke(const char *name, dev_t dev, ino_t ino); + +private: + struct FileWatch; + struct DirWatch; + struct ChangeEventData; + + // Class Variables + enum { QUEUESIZE = 1024 }; + static int pipe_write_fd; + static int pipe_read_fd; + static int change_queue[QUEUESIZE]; + static volatile sig_atomic_t DNotify::queue_overflowed; + static volatile sig_atomic_t DNotify::queue_changed; + static volatile int queue_head; // Only modified by read handler + static volatile int queue_tail; // Only modified by signal handler + static EventHandler ehandler; + static void overflow_signal_handler(int sig, siginfo_t *si, void *data); + static void signal_handler(int sig, siginfo_t *si, void *data); + static void read_handler(int fd, void *closure); + + enum { DIR_HASHSIZE = 257 }; + static DirWatch *dir_hash[DIR_HASHSIZE]; + enum { FILE_HASHSIZE = 257 }; + static FileWatch *file_hash[FILE_HASHSIZE]; + + static DirWatch **dir_hashchain(int fd) + { return &dir_hash[(unsigned) (fd) % DIR_HASHSIZE]; } + static FileWatch **file_hashchain(dev_t d, ino_t i) + { return &file_hash[(unsigned) (d+i) % FILE_HASHSIZE]; } + + static DirWatch *lookup_dirwatch (int fd); + static DirWatch *lookup_dirwatch (dev_t dir_dev, ino_t dir_ino); + static FileWatch *lookup_filewatch (dev_t file_dev, ino_t file_ino); + static void hash_dirwatch(DirWatch *w); + static void hash_filewatch(FileWatch *w); + static void unhash_dirwatch(DirWatch *w); + static void unhash_filewatch(FileWatch *w); + static Status watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino); + + static void all_watches_changed(void); + + DNotify(const DNotify&); // Do not copy + DNotify & operator = (const DNotify&); // or assign. +}; + +#endif /* !IMon_included */ + + --- fam-2.6.9/fam/IMon.h.dnotify 2002-07-16 07:23:24.000000000 +0200 +++ fam-2.6.9/fam/IMon.h 2003-01-31 22:23:09.000000000 +0100 @@ -24,10 +24,7 @@ #define IMon_included #include "config.h" -#include -#include - -#include "Boolean.h" +#include "Monitor.h" struct stat; @@ -41,25 +38,18 @@ // // The user of the IMon object is the Interest class. -class IMon { +class IMon : public Monitor { public: - - enum Status { OK = 0, BAD = -1 }; - enum Event { EXEC, EXIT, CHANGE }; - - typedef void (*EventHandler)(dev_t, ino_t, int event); - IMon(EventHandler h); ~IMon(); static bool is_active(); - Status express(const char *name, struct stat *stat_return); - Status revoke(const char *name, dev_t dev, ino_t ino); + virtual Status express(const char *name, struct stat *stat_return); + virtual Status revoke(const char *name, dev_t dev, ino_t ino); private: - // Class Variables static int imonfd; --- fam-2.6.9/fam/Interest.c++.dnotify 2002-07-16 08:14:41.000000000 +0200 +++ fam-2.6.9/fam/Interest.c++ 2003-01-31 22:23:09.000000000 +0100 @@ -43,12 +43,21 @@ #include "Event.h" #include "FileSystem.h" #include "IMon.h" +#include "DNotify.h" #include "Log.h" #include "Pollster.h" #include "timeval.h" Interest *Interest::hashtable[]; -IMon Interest::imon(imon_handler); + +#ifdef USE_DNOTIFY +static DNotify dnotify(Interest::monitor_handler); +Monitor * Interest::monitor = &dnotify; +#else +static IMon imon(Interest::monitor_handler); +Monitor * Interest::monitor = &imon; +#endif + bool Interest::xtab_verification = true; Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev) @@ -60,11 +69,11 @@ myhost(host), mypath_exported_to_host(ev == NO_VERIFY_EXPORTED) { - memset(&old_stat, 0, sizeof(old_stat)); - IMon::Status s = IMon::BAD; - - s = imon.express(name, &old_stat); - if (s != IMon::OK) + memset(&old_stat, 0, sizeof(old_stat)); + + Monitor::Status s = Monitor::BAD; + s = monitor->express(name, &old_stat); + if (s != Monitor::OK) { int rc = lstat(name, &old_stat); if (rc < 0) { Log::info("can't lstat %s", name); @@ -101,7 +110,7 @@ } #endif - if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK); + if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK); } Interest::~Interest() @@ -129,7 +138,7 @@ pp = &p->hashlink; // move to next element } if (!found_same) - (void) imon.revoke(name(), dev, ino); + (void) monitor->revoke(name(), dev, ino); } } @@ -148,7 +157,7 @@ // Express interest. IMon::Status s = IMon::BAD; - s = imon.express(name(), NULL); + s = monitor->express(name(), NULL); if (s != IMon::OK) { return true; } @@ -249,23 +258,23 @@ } void -Interest::imon_handler(dev_t device, ino_t inumber, int event) +Interest::monitor_handler(dev_t device, ino_t inumber, int event) { assert(device || inumber); for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next) { next = p->hashlink; if (p->ino == inumber && p->dev == device) - { if (event == IMon::EXEC) + { if (event == Monitor::EXEC) { p->cur_exec_state = EXECUTING; (void) p->report_exec_state(); } - else if (event == IMon::EXIT) + else if (event == Monitor::EXIT) { p->cur_exec_state = NOT_EXECUTING; (void) p->report_exec_state(); } else - { assert(event == IMon::CHANGE); + { assert(event == Monitor::CHANGE); p->scan(); } } --- fam-2.6.9/fam/Interest.h.dnotify 2002-07-16 07:23:24.000000000 +0200 +++ fam-2.6.9/fam/Interest.h 2003-01-31 22:23:09.000000000 +0100 @@ -32,7 +32,7 @@ class Event; class FileSystem; -class IMon; +class Monitor; struct stat; // Interest -- abstract base class for filesystem entities of interest. @@ -74,7 +74,7 @@ // Public Class Method - static void imon_handler(dev_t, ino_t, int event); + static void monitor_handler(dev_t, ino_t, int event); static void enable_xtab_verification(bool enable); @@ -121,7 +121,7 @@ // Class Variables - static IMon imon; + static Monitor *monitor; static Interest *hashtable[HASHSIZE]; static bool xtab_verification; --- fam-2.6.9/fam/Makefile.am.dnotify 2002-07-16 07:23:24.000000000 +0200 +++ fam-2.6.9/fam/Makefile.am 2003-01-31 22:24:29.000000000 +0100 @@ -3,6 +3,12 @@ bin_PROGRAMS = fam sysconf_DATA = fam.conf +if USE_DNOTIFY +DNOTIFY_FILES = DNotify.c++ +else +DNOTIFY_FILES = +endif + fam_SOURCES = \ Activity.c++ \ Activity.h \ @@ -20,6 +26,7 @@ Directory.h \ DirectoryScanner.c++ \ DirectoryScanner.h \ + DNotify.h \ Event.c++ \ Event.h \ File.c++ \ @@ -48,6 +55,7 @@ NFSFileSystem.h \ NetConnection.c++ \ NetConnection.h \ + Monitor.h \ Pollster.c++ \ Pollster.h \ Request.h \ @@ -72,11 +80,12 @@ main.c++ \ timeval.c++ \ timeval.h \ - @IMON_FUNCS@.c++ + @IMON_FUNCS@.c++ \ + $(DNOTIFY_FILES) -EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ +EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ -fam_LDADD = -lrpcsvc $(top_srcdir)/support/libsupport.a +fam_LDADD = -lrpcsvc $(top_srcdir)/support/libsupport.a -lrt -lpthread CLEANFILES += @MKDEPFILE@ ii_files/*.ii sinclude @MKDEPFILE@ --- fam-2.6.9/fam/Monitor.h.dnotify 2003-01-31 22:23:09.000000000 +0100 +++ fam-2.6.9/fam/Monitor.h 2003-01-31 22:23:09.000000000 +0100 @@ -0,0 +1,57 @@ +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it would be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any +// license provided herein, whether implied or otherwise, is limited to +// this program in accordance with the express provisions of the GNU +// General Public License. Patent licenses, if any, provided herein do not +// apply to combinations of this program with other product or programs, or +// any other product whatsoever. This program is distributed without any +// warranty that the program is delivered free of the rightful claim of any +// third person by way of infringement or the like. See the GNU General +// Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write the Free Software Foundation, Inc., 59 +// Temple Place - Suite 330, Boston MA 02111-1307, USA. + +#ifndef Monitor_included +#define Monitor_included + +#include "config.h" +#include +#include + +struct stat; + +// Monitor is an abstract baseclass for differend file monitoring +// systems. The original system used was IMon, and the Montor API +// is heavily influenced by that. +// There can only be one instantiation of the Monitor object. +// +// The user of this object uses express() and revoke() to +// express/revoke interest in a file to imon. There is also +// a callback, the EventHandler. When an event comes in, +// the EventHandler is called. +// +// The main implementers of the Monitor class is IMon and DNotify + +class Monitor { +public: + + enum Status { OK = 0, BAD = -1 }; + enum Event { EXEC, EXIT, CHANGE }; + + typedef void (*EventHandler)(dev_t, ino_t, int event); + + virtual Status express(const char *name, struct stat *stat_return) = 0; + virtual Status revoke(const char *name, dev_t dev, ino_t ino) = 0; +}; + +#endif /* !Monitor_included */ --- fam-2.6.9/acconfig.h.dnotify 2002-07-16 08:03:58.000000000 +0200 +++ fam-2.6.9/acconfig.h 2003-01-31 22:23:09.000000000 +0100 @@ -17,6 +17,9 @@ /* Define if the system has imon and IMONIOC_ ioctl flags. */ #undef HAVE_IMON +/* Define if the system has the dnotify fcntl and it's gonna be used. */ +#undef USE_DNOTIFY + /* Define if the system has the struct revokdi and the IMONIOC_REVOKDI ** ioctl flag. (IRIX 5.3 doesn't.) */ --- fam-2.6.9/configure.in.dnotify 2002-07-16 08:23:52.000000000 +0200 +++ fam-2.6.9/configure.in 2003-01-31 22:23:09.000000000 +0100 @@ -100,6 +100,24 @@ dnl AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h syslog.h unistd.h) dnl +dnl Test for the linux dnotify fcntl +dnl +AC_MSG_CHECKING([for dnotify fcntl support]) +fam_save_cppflags="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +AC_TRY_COMPILE([ +#define _GNU_SOURCE +#include +#include +], +[ int fd = 1; + fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)|DN_MULTISHOT); +], have_dnotify=yes, have_dnotify=no) +use_dnotify=false +CPPFLAGS="$pango_save_cppflags" +AC_MSG_RESULT($have_dnotify) + +dnl dnl See if imon is available; if so, is it IRIX or Linux? dnl if test `uname` = 'IRIX' || test `uname` = 'IRIX64'; then @@ -122,11 +140,17 @@ if test "$have_imon" != "yes"; then have_imon=no AC_DEFINE(HAVE_IMON, 0) + if test "$have_dnotify" = "yes"; then + AC_DEFINE(USE_DNOTIFY) + use_dnotify=true + fi IMON_FUNCS=IMonNone fi +AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify) AC_SUBST(IMON_FUNCS) echo "Using imon support module $IMON_FUNCS" + AC_CHECK_HEADER(sys/statvfs.h, [AC_DEFINE(HAVE_STATVFS, 1) have_statvfs="yes"], [AC_DEFINE(HAVE_STATVFS, 0) have_statvfs="no"]) AC_CHECK_HEADER(sys/syssgi.h, AC_DEFINE(HAVE_SYSSGI, 1), AC_DEFINE(HAVE_SYSSGI, 0)) AC_CHECK_HEADER(sys/fs/nfs_clnt.h, AC_DEFINE(HAVE_SYS_FS_NFS_CLNT_H, 1), AC_DEFINE(HAVE_SYS_FS_NFS_CLNT_H, 0)) @@ -580,7 +604,7 @@ dnl dnl fam is a good deal less interesting without imon. dnl -if test "$have_imon" != 'yes'; then +if test "$have_imon" != 'yes' -a "$have_dnotify" != 'yes'; then cat << EOF ******************************************************************