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

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 873009c 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
  • src/DNotify.c++

    old new  
     1//  Copyright (C) 2001 Red Hat, Inc.  All Rights Reserved.
     2//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.
     3// 
     4//  This program is free software; you can redistribute it and/or modify it
     5//  under the terms of version 2 of the GNU General Public License as
     6//  published by the Free Software Foundation.
     7//
     8//  This program is distributed in the hope that it would be useful, but
     9//  WITHOUT ANY WARRANTY; without even the implied warranty of
     10//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any
     11//  license provided herein, whether implied or otherwise, is limited to
     12//  this program in accordance with the express provisions of the GNU
     13//  General Public License.  Patent licenses, if any, provided herein do not
     14//  apply to combinations of this program with other product or programs, or
     15//  any other product whatsoever.  This program is distributed without any
     16//  warranty that the program is delivered free of the rightful claim of any
     17//  third person by way of infringement or the like.  See the GNU General
     18//  Public License for more details.
     19//
     20//  You should have received a copy of the GNU General Public License along
     21//  with this program; if not, write the Free Software Foundation, Inc., 59
     22//  Temple Place - Suite 330, Boston MA 02111-1307, USA.
     23
     24#define _GNU_SOURCE 
     25#include <fcntl.h>
     26
     27#include <string.h>
     28#include <signal.h>
     29#include <stdio.h>
     30#include <unistd.h>
     31#include <sys/types.h>
     32#include <sys/stat.h>
     33#include <libgen.h>
     34
     35#include "DNotify.h"
     36
     37#include "Interest.h"
     38#include "Log.h"
     39#include "Scheduler.h"
     40#include <memory>
     41
     42
     43int DNotify::pipe_write_fd = -2;
     44int DNotify::pipe_read_fd = -2;
     45volatile sig_atomic_t DNotify::queue_overflowed = 0;
     46volatile sig_atomic_t DNotify::queue_changed = 0;
     47int DNotify::change_queue[QUEUESIZE];
     48volatile int DNotify::queue_head = 0; // Only modified by read handler
     49volatile int DNotify::queue_tail = 0; // Only modified by signal handler
     50DNotify::EventHandler DNotify::ehandler;
     51
     52DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE];
     53DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE];
     54
     55struct DNotify::FileWatch
     56{
     57    DirWatch *dir_watch;
     58    dev_t file_dev;
     59    ino_t file_ino;
     60    FileWatch *next; // The DirWatch.watches list
     61    FileWatch *hash_link;
     62};
     63
     64struct DNotify::DirWatch
     65{
     66    int fd;
     67    dev_t dir_dev;
     68    ino_t dir_ino;
     69   
     70    DirWatch *hash_link;
     71    FileWatch *watches;
     72};
     73
     74struct DNotify::ChangeEventData
     75{
     76    dev_t file_dev;
     77    ino_t file_ino;
     78};   
     79
     80DNotify::DNotify(EventHandler h)
     81{
     82    assert(ehandler == NULL);
     83    ehandler = h;
     84}
     85
     86DNotify::~DNotify()
     87{
     88    if (pipe_read_fd >= 0)
     89    {
     90        //  Tell the scheduler.
     91
     92        (void) Scheduler::remove_read_handler(pipe_read_fd);
     93
     94        //  Close the pipe.
     95
     96        if (close(pipe_read_fd) < 0)
     97            Log::perror("can't pipe read end");
     98        else
     99            Log::debug("closed pipe read end");
     100       
     101        if (close(pipe_write_fd) < 0)
     102            Log::perror("can't pipe write end");
     103        else
     104            Log::debug("closed pipe write end");
     105        pipe_read_fd = -1;
     106    }
     107    ehandler = NULL;
     108}
     109
     110void
     111DNotify::overflow_signal_handler(int sig, siginfo_t *si, void *data)
     112{
     113  char c = 'x';
     114
     115  {
     116    char *str = "*************** overflow sigqueue ***********************\n";
     117    write (STDERR_FILENO, str, strlen(str));
     118  }
     119
     120  if (!queue_overflowed)
     121  {
     122      queue_overflowed = 1;
     123      // Trigger the read handler
     124      write(pipe_write_fd, &c, 1);
     125  }
     126}
     127
     128void
     129DNotify::signal_handler(int sig, siginfo_t *si, void *data)
     130{
     131  int left;
     132  char c = 'x';
     133
     134  if (queue_head <= queue_tail)
     135    left = (QUEUESIZE + queue_head) - queue_tail;
     136  else
     137    left = queue_head - queue_tail;
     138 
     139  // Must leave at least one item unused to see difference
     140  // Betweeen empty and full
     141  if (left <= 1)
     142  {
     143      queue_overflowed = 1;
     144      {
     145        char *str = "*************** overflow famqueue ****************\n";
     146        write (STDERR_FILENO, str, strlen(str));
     147      }
     148  }
     149  else
     150  {
     151      change_queue[queue_tail] = si->si_fd;
     152      queue_tail = (queue_tail + 1) % QUEUESIZE;
     153  }
     154 
     155  if (!queue_changed)
     156  {
     157      queue_changed = 1;
     158      // Trigger the read handler
     159      write(pipe_write_fd, &c, 1);
     160  }
     161}
     162
     163bool
     164DNotify::is_active()
     165{
     166    if (pipe_read_fd == -2)
     167    {
     168        int filedes[2];
     169        int res;
     170       
     171        res = pipe (filedes);
     172        if (res >= 0)
     173        {   Log::debug("opened pipe");
     174            pipe_read_fd = filedes[0];
     175            pipe_write_fd = filedes[1];
     176
     177            // Setup signal handler:
     178            struct sigaction act;
     179           
     180            act.sa_sigaction = signal_handler;
     181            sigemptyset(&act.sa_mask);
     182            act.sa_flags = SA_SIGINFO;
     183            sigaction(SIGRTMIN, &act, NULL);
     184
     185            // When the RT queue overflows we get a SIGIO
     186            act.sa_sigaction = overflow_signal_handler;
     187            sigemptyset(&act.sa_mask);
     188            sigaction(SIGIO, &act, NULL);
     189
     190            (void) Scheduler::install_read_handler(pipe_read_fd, read_handler, NULL);
     191        }
     192    }
     193    return pipe_read_fd >= 0;
     194}
     195
     196DNotify::DirWatch *
     197DNotify::lookup_dirwatch (int fd)
     198{
     199  DirWatch **p;
     200  DirWatch *w;
     201
     202  p = dir_hashchain (fd);
     203
     204  while (*p)
     205    {
     206      w = *p;
     207
     208      if (w->fd == fd)
     209        return w;
     210
     211      p = &w->hash_link;
     212    }
     213 
     214  return *p;
     215}
     216
     217// This colud be made faster by using another hash table.
     218// But it's not that bad, since it is only used by express/revoke
     219DNotify::DirWatch *
     220DNotify::lookup_dirwatch (dev_t dir_dev, ino_t dir_ino)
     221{
     222  DirWatch *p;
     223  int i;
     224
     225  for (i=0;i<DIR_HASHSIZE;i++)
     226    {
     227      p = dir_hash[i];
     228     
     229      while (p)
     230        {
     231          if (p->dir_dev == dir_dev && p->dir_ino == dir_ino)
     232            return p;
     233         
     234          p = p->hash_link;
     235        }
     236    }
     237 
     238  return NULL;
     239}
     240
     241DNotify::FileWatch *
     242DNotify::lookup_filewatch (dev_t dev, ino_t ino)
     243{
     244  FileWatch **p;
     245  FileWatch *w;
     246
     247  p = file_hashchain (dev, ino);
     248
     249  while (*p)
     250    {
     251      w = *p;
     252
     253      if (w->file_dev == dev && w->file_ino == ino)
     254        return w;
     255
     256      p = &w->hash_link;
     257    }
     258 
     259  return *p;
     260}
     261
     262// Make sure w is not already in the hash table before calling
     263// this function.
     264void
     265DNotify::hash_dirwatch(DirWatch *w)
     266{
     267  DirWatch **p;
     268  p = dir_hashchain (w->fd);
     269  w->hash_link = *p;
     270  *p = w;
     271}
     272
     273// Make sure w is not already in the hash table before calling
     274// this function.
     275void
     276DNotify::hash_filewatch(FileWatch *w)
     277{
     278  FileWatch **p;
     279  p = file_hashchain (w->file_dev, w->file_ino);
     280  w->hash_link = *p;
     281  *p = w;
     282}
     283
     284void
     285DNotify::unhash_dirwatch(DirWatch *w)
     286{
     287  DirWatch **p;
     288 
     289  p = dir_hashchain (w->fd);
     290 
     291  while (*p)
     292    {
     293      if (*p == w)
     294        {
     295          *p = w->hash_link;
     296          break;
     297        }
     298      p = &(*p)->hash_link;
     299    }
     300  w->hash_link = NULL;
     301}
     302
     303void
     304DNotify::unhash_filewatch(FileWatch *w)
     305{
     306  FileWatch **p;
     307 
     308  p = file_hashchain (w->file_dev, w->file_ino);
     309 
     310  while (*p)
     311    {
     312      if (*p == w)
     313        {
     314          *p = w->hash_link;
     315          break;
     316        }
     317      p = &(*p)->hash_link;
     318    }
     319  w->hash_link = NULL;
     320}
     321
     322DNotify::Status
     323DNotify::watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino)
     324{
     325  struct stat stat;
     326  dev_t dir_dev;
     327  ino_t dir_ino;
     328  DirWatch *dwatch;
     329  FileWatch *fw;
     330   
     331  if (lstat (notify_dir, &stat) == -1)
     332      return BAD;
     333 
     334  dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino);
     335  if (!dwatch)
     336    {
     337      Log::debug ("New DirWatch for %s (%x %x)\n",
     338                  notify_dir, (int)stat.st_dev, (int)stat.st_ino);
     339      dwatch = new DirWatch;
     340      dwatch->watches = NULL;
     341      dwatch->hash_link = NULL;
     342      dwatch->dir_dev = stat.st_dev;
     343      dwatch->dir_ino = stat.st_ino;
     344     
     345      dwatch->fd = open(notify_dir, O_RDONLY);
     346      fcntl (dwatch->fd, F_SETSIG, SIGRTMIN);
     347      if (fcntl (dwatch->fd, F_NOTIFY,
     348                 (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)
     349                  | DN_MULTISHOT) == -1) {
     350              return BAD;
     351      }
     352      hash_dirwatch (dwatch);
     353    }
     354
     355  fw = lookup_filewatch (file_dev, file_ino);
     356  if (fw && fw->dir_watch == dwatch)
     357        return OK;
     358 
     359  // No old FileWatch, need to add one:
     360  Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino);
     361  fw = new FileWatch;
     362  fw->next = dwatch->watches;
     363  dwatch->watches = fw;
     364  fw->file_dev = file_dev;
     365  fw->file_ino = file_ino;
     366  fw->dir_watch = dwatch;
     367  hash_filewatch(fw);
     368  return OK;
     369}
     370
     371char *
     372dirname_dup (const char *name)
     373{
     374  char *copy = strdup(name);
     375  char *res = dirname(copy);
     376  res = strdup(res);
     377  free (copy);
     378  return res;
     379}
     380
     381DNotify::Status
     382DNotify::express(const char *name, struct stat *status)
     383{
     384    struct stat stat;
     385    char *notify_dir;
     386    int res;
     387    Status s;
     388    dev_t dev;
     389    ino_t ino;
     390
     391    Log::debug("express() name: %s\n", name);
     392
     393    if (!is_active())
     394        return BAD;
     395
     396    if (::lstat (name, &stat) == -1)
     397      return BAD;
     398
     399    dev = stat.st_dev;
     400    ino = stat.st_ino;
     401   
     402    if ((stat.st_mode & S_IFMT) != S_IFDIR)
     403        notify_dir = dirname_dup (name);
     404    else
     405        notify_dir = (char *)name;
     406
     407    s = watch_dir (notify_dir, dev, ino);
     408    if (notify_dir != name)
     409        free (notify_dir);
     410    if (s)
     411      return s;
     412
     413    // Check for a race condition; if someone removed or changed the
     414    // file at the same time that we are expressing interest in it,
     415    // revoke the interest so we don't get notifications about changes
     416    // to a recycled inode that we don't otherwise care about.
     417    //
     418    struct stat st;
     419    if (status == NULL) {
     420        status = &st;
     421    }
     422    if (::lstat(name, status) == -1) {
     423        Log::perror("stat on \"%s\" failed", name);
     424        revoke(name, stat.st_dev, stat.st_ino);
     425        return BAD;
     426    }
     427    if (status->st_dev != stat.st_dev
     428        || status->st_ino != stat.st_ino) {
     429        Log::error("File \"%s\" changed between express and stat",
     430                   name);
     431        revoke(name, stat.st_dev, stat.st_ino);
     432        return BAD;
     433    }   
     434
     435    Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name,
     436               major(status->st_dev), minor(status->st_dev),
     437               status->st_ino);
     438    return OK;
     439}
     440
     441DNotify::Status
     442DNotify::revoke(const char *name, dev_t dev, ino_t ino)
     443{
     444    FileWatch *fwatch;
     445    DirWatch *dwatch;
     446   
     447    Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino);
     448
     449    if (!is_active())
     450        return BAD;
     451
     452    // Lookup FileWatch by dev:ino, and its DirWatch.
     453    fwatch = lookup_filewatch (dev, ino);
     454    if (fwatch == NULL)
     455        return BAD;
     456   
     457    dwatch = fwatch->dir_watch;
     458   
     459    // delete FileWatch, if last FileWatch: close fd, delete DirWatch
     460    Log::debug ("Destroying FileWatch for (%x %x)\n",
     461                (int)fwatch->file_dev, (int)fwatch->file_ino);
     462    FileWatch **p;
     463    for (p=&dwatch->watches; *p; p=&(*p)->next)
     464    {
     465      if (*p == fwatch)
     466        {
     467          *p = (*p)->next;
     468          break;
     469        }
     470    }
     471    unhash_filewatch(fwatch);
     472    delete fwatch;
     473    if (dwatch->watches == NULL)
     474      {
     475        Log::debug ("Destroying DirWatch for (%x %x)\n",
     476                    (int)dwatch->dir_dev, (int)dwatch->dir_ino);
     477        close(dwatch->fd);
     478        unhash_dirwatch(dwatch);
     479        delete dwatch;
     480      }
     481 
     482    return OK;
     483}
     484
     485
     486void
     487DNotify::all_watches_changed(void)
     488{
     489  int i;
     490  FileWatch *fw;
     491
     492  for (i=0; i<FILE_HASHSIZE; i++)
     493  {
     494      fw = file_hash[i];
     495      while (fw)
     496      {
     497          (*ehandler)(fw->file_dev, fw->file_ino, CHANGE);
     498
     499          fw = fw->hash_link;
     500      }
     501  }
     502}
     503
     504
     505void
     506DNotify::read_handler(int fd, void *)
     507{
     508    static char readbuf[5000];
     509    DirWatch *dw;
     510    FileWatch *fw;
     511    int snap_queue_tail;
     512    int last_fd;
     513
     514    int rc = read(fd, readbuf, sizeof readbuf);
     515    queue_changed = 0;
     516    if (rc < 0)
     517        Log::perror("pipe read");
     518    else if (queue_overflowed)
     519    {
     520          // There is a *slight* race condition here. Between reading
     521          // the queue_overflow flag and resetting it. But it doesn't
     522          // matter, since I'm gonna handle the overflow after reseting
     523          // anyway.
     524          queue_overflowed = false;
     525
     526          // We're soon gonna check all watches anyway, so
     527          // get rid of the current queue
     528          queue_head = queue_tail;
     529         
     530          all_watches_changed ();
     531    }
     532    else
     533    {
     534        // Don't read events that happen later than
     535        // the initial read. (Otherwise skipping fd's
     536        // might miss some changes).
     537        snap_queue_tail = queue_tail;
     538        last_fd = -1;
     539        while (queue_head != snap_queue_tail)
     540        {
     541            fd = change_queue[queue_head];
     542            queue_head = (queue_head + 1) % QUEUESIZE;
     543
     544            // Skip multiple changes to the same fd
     545            if (fd != last_fd)
     546            {
     547                dw = lookup_dirwatch (fd);
     548                if (dw)
     549                {
     550                    int n_watches, i;
     551                    ChangeEventData *data;
     552                   
     553                    Log::debug("dnotify said dev %d/%d, ino %ld changed",
     554                               major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino);
     555                   
     556                    n_watches = 0;
     557                    for (fw=dw->watches; fw; fw=fw->next)
     558                        n_watches++;
     559                   
     560                    data = new ChangeEventData[n_watches];
     561
     562                    i = 0;
     563                    for (fw=dw->watches; fw; fw=fw->next)
     564                    {
     565                        data[i].file_dev = fw->file_dev;
     566                        data[i].file_ino = fw->file_ino;
     567                        i++;
     568                    }
     569
     570                    for (i = 0; i < n_watches; i++)
     571                    {
     572                        (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE);
     573                    }
     574                   
     575                    delete[] data;
     576                }
     577            }
     578            last_fd = fd;
     579        }
     580    }
     581}
     582
  • src/DNotify.h

    old new  
     1//  Copyright (C) 2001 Red Hat, Inc.  All Rights Reserved.
     2//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.
     3//
     4//  This program is free software; you can redistribute it and/or modify it
     5//  under the terms of version 2 of the GNU General Public License as
     6//  published by the Free Software Foundation.
     7//
     8//  This program is distributed in the hope that it would be useful, but
     9//  WITHOUT ANY WARRANTY; without even the implied warranty of
     10//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any
     11//  license provided herein, whether implied or otherwise, is limited to
     12//  this program in accordance with the express provisions of the GNU
     13//  General Public License.  Patent licenses, if any, provided herein do not
     14//  apply to combinations of this program with other product or programs, or
     15//  any other product whatsoever.  This program is distributed without any
     16//  warranty that the program is delivered free of the rightful claim of any
     17//  third person by way of infringement or the like.  See the GNU General
     18//  Public License for more details.
     19//
     20//  You should have received a copy of the GNU General Public License along
     21//  with this program; if not, write the Free Software Foundation, Inc., 59
     22//  Temple Place - Suite 330, Boston MA 02111-1307, USA.
     23
     24#ifndef DNotify_included
     25#define DNotify_included
     26
     27#include "config.h"
     28#include "Monitor.h"
     29#include <signal.h>
     30
     31//  DNotify is an object encapsulating the dnotify linux fcntl.
     32//  It "emulates" the IMon interface.
     33//  There can only be one instantiation of the DNotify object.
     34//
     35//  The user of this object uses express() and revoke() to
     36//  express/revoke interest in a file.  There is also
     37//  a callback, the EventHandler.  When an dnotify event comes in,
     38//  the EventHandler is called.
     39//
     40//  The user of the DNotify object is the Interest class.
     41
     42class DNotify : public Monitor {
     43public:
     44    DNotify(EventHandler h);
     45    ~DNotify();
     46
     47    static bool is_active();
     48
     49    virtual Status express(const char *name, struct stat *stat_return);
     50    virtual Status revoke(const char *name, dev_t dev, ino_t ino);
     51
     52private:
     53    struct FileWatch;
     54    struct DirWatch;
     55    struct ChangeEventData;
     56 
     57    //  Class Variables
     58    enum { QUEUESIZE = 1024 };
     59    static int pipe_write_fd;
     60    static int pipe_read_fd;
     61    static int change_queue[QUEUESIZE];
     62    static volatile sig_atomic_t DNotify::queue_overflowed;
     63    static volatile sig_atomic_t DNotify::queue_changed;
     64    static volatile int queue_head; // Only modified by read handler
     65    static volatile int queue_tail; // Only modified by signal handler
     66    static EventHandler ehandler;
     67    static void overflow_signal_handler(int sig, siginfo_t *si, void *data);
     68    static void signal_handler(int sig, siginfo_t *si, void *data);
     69    static void read_handler(int fd, void *closure);
     70 
     71    enum { DIR_HASHSIZE = 367 };
     72    static DirWatch *dir_hash[DIR_HASHSIZE];
     73    enum { FILE_HASHSIZE = 823 };
     74    static FileWatch *file_hash[FILE_HASHSIZE];
     75
     76    static DirWatch **dir_hashchain(int fd)
     77                          { return &dir_hash[(unsigned) (fd) % DIR_HASHSIZE]; }
     78    static FileWatch **file_hashchain(dev_t d, ino_t i)
     79                          { return &file_hash[(unsigned) (d+i) % FILE_HASHSIZE]; }
     80
     81    static DirWatch *lookup_dirwatch (int fd);
     82    static DirWatch *lookup_dirwatch (dev_t dir_dev, ino_t dir_ino);
     83    static FileWatch *lookup_filewatch (dev_t file_dev, ino_t file_ino);
     84    static void hash_dirwatch(DirWatch *w);
     85    static void hash_filewatch(FileWatch *w);
     86    static void unhash_dirwatch(DirWatch *w);
     87    static void unhash_filewatch(FileWatch *w);
     88    static Status watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino);
     89
     90    static void all_watches_changed(void);
     91   
     92    DNotify(const DNotify&);                    // Do not copy
     93    DNotify & operator = (const DNotify&);      //  or assign.
     94};
     95
     96#endif /* !IMon_included */
     97
     98
  • src/Interest.c++

    old new  
    4242#include "Event.h"
    4343#include "FileSystem.h"
    4444#include "IMon.h"
     45#include "DNotify.h"
    4546#include "Log.h"
    4647#include "Pollster.h"
    4748#include "timeval.h"
    4849
    4950Interest *Interest::hashtable[];
    50 IMon      Interest::imon(imon_handler);
     51
     52#ifdef USE_DNOTIFY
     53static DNotify dnotify(Interest::monitor_handler);
     54Monitor * Interest::monitor = &dnotify;
     55#else
     56static IMon imon(Interest::monitor_handler);
     57Monitor * Interest::monitor = &imon;
     58#endif
     59
    5160bool      Interest::xtab_verification = true;
    5261
    5362Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev)
     
    6069      mypath_exported_to_host(ev == NO_VERIFY_EXPORTED)
    6170{
    6271    memset(&old_stat, 0, sizeof(old_stat));
    63     IMon::Status s = IMon::BAD;
    6472
    65     s = imon.express(name, &old_stat);
    66     if (s != IMon::OK)
     73    Monitor::Status s = Monitor::BAD;
     74    s = monitor->express(name, &old_stat);
     75    if (s != Monitor::OK)
    6776    {   int rc = lstat(name, &old_stat);
    6877        if (rc < 0)
    6978        {   Log::info("can't lstat %s", name);
     
    100109    }
    101110#endif
    102111
    103     if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK);
     112    if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK);
    104113}
    105114
    106115Interest::~Interest()
     
    128137                pp = &p->hashlink;      // move to next element
    129138            }
    130139        if (!found_same)
    131             (void) imon.revoke(name(), dev, ino);
     140          (void) monitor->revoke(name(), dev, ino);
    132141    }
    133142}
    134143
     
    147156
    148157        // Express interest.
    149158        IMon::Status s = IMon::BAD;
    150         s = imon.express(name(), NULL);
     159        s = monitor->express(name(), NULL);
    151160        if (s != IMon::OK) {
    152161            return true;
    153162        }
     
    248257}
    249258
    250259void
    251 Interest::imon_handler(dev_t device, ino_t inumber, int event)
     260Interest::monitor_handler(dev_t device, ino_t inumber, int event)
    252261{
    253262    assert(device || inumber);
    254263
    255264    for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next)
    256265    {   next = p->hashlink;
    257266        if (p->ino == inumber && p->dev == device)
    258         {   if (event == IMon::EXEC)
     267          {   if (event == Monitor::EXEC)
    259268            {   p->cur_exec_state = EXECUTING;
    260269                (void) p->report_exec_state();
    261270            }
    262             else if (event == IMon::EXIT)
     271            else if (event == Monitor::EXIT)
    263272            {   p->cur_exec_state = NOT_EXECUTING;
    264273                (void) p->report_exec_state();
    265274            }
    266275            else
    267             {   assert(event == IMon::CHANGE);
     276            {   assert(event == Monitor::CHANGE);
    268277                p->scan();
    269278            }
    270279        }
  • config.h.in

    old new  
    180180
    181181/* Define to `int' if <sys/types.h> doesn't define. */
    182182#undef uid_t
     183
     184/* Define to 1 if you have F_NOTIFY fcntl */
     185#undef USE_DNOTIFY
  • configure.ac

    old new  
    3434AC_HEADER_DIRENT
    3535AC_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])
    3636
    37 if test "$have_sys_imon_h"; then
     37# Test for the linux dnotify fcntl
     38AC_MSG_CHECKING([for dnotify fcntl support])
     39AC_TRY_COMPILE([
     40#define _GNU_SOURCE 
     41#include <fcntl.h>
     42#include <unistd.h>
     43],
     44[ int fd = 1;
     45  fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)
     46                       |DN_MULTISHOT);
     47], have_dnotify=yes, have_dnotify=no)
     48
     49use_dnotify=false
     50AC_MSG_RESULT($have_dnotify)
     51
     52if test "$have_dnotify"; then
     53        MONITOR_FUNCS=IMonNone
     54        AC_DEFINE([USE_DNOTIFY], [], [Use dnotify])
     55        use_dnotify=true
     56elif test "$have_sys_imon_h"; then
    3857        MONITOR_FUNCS=IMonIRIX
    3958elif test "$have_linux_imon_h"; then
    4059        MONITOR_FUNCS=IMonLinux
     
    4262        MONITOR_FUNCS=IMonNone
    4363fi
    4464AC_SUBST(MONITOR_FUNCS)
     65AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify)
    4566
    4667# Checks for typedefs, structures, and compiler characteristics.
    4768AC_HEADER_STDBOOL
  • src/IMon.h

    old new  
    2424#define IMon_included
    2525
    2626#include "config.h"
    27 #include <sys/stat.h>
    28 #include <sys/types.h>
    29 
    30 #include "Boolean.h"
     27#include "Monitor.h"
    3128
    3229struct stat;
    3330
     
    4138//
    4239//  The user of the IMon object is the Interest class.
    4340
    44 class IMon {
     41class IMon : public Monitor {
    4542
    4643public:
    47 
    48     enum Status { OK = 0, BAD = -1 };
    49     enum Event { EXEC, EXIT, CHANGE };
    50 
    51     typedef void (*EventHandler)(dev_t, ino_t, int event);
    52 
    5344    IMon(EventHandler h);
    5445    ~IMon();
    5546
    5647    static bool is_active();
    5748
    58     Status express(const char *name, struct stat *stat_return);
    59     Status revoke(const char *name, dev_t dev, ino_t ino);
     49    virtual Status express(const char *name, struct stat *stat_return);
     50    virtual Status revoke(const char *name, dev_t dev, ino_t ino);
    6051
    6152private:
    62 
    6353    //  Class Variables
    6454
    6555    static int imonfd;
  • src/Interest.h

    old new  
    3232
    3333class Event;
    3434class FileSystem;
    35 class IMon;
     35class Monitor;
    3636struct stat;
    3737
    3838//  Interest -- abstract base class for filesystem entities of interest.
     
    7474
    7575    //  Public Class Method
    7676
    77     static void imon_handler(dev_t, ino_t, int event);
     77    static void monitor_handler(dev_t, ino_t, int event);
    7878
    7979    static void enable_xtab_verification(bool enable);
    8080
     
    121121
    122122    //  Class Variables
    123123
    124     static IMon imon;
     124    static Monitor *monitor;
    125125    static Interest *hashtable[HASHSIZE];
    126126    static bool xtab_verification;
    127127
  • src/Makefile.am

    old new  
    7171  main.c++ \
    7272  timeval.c++ \
    7373  timeval.h \
    74   @MONITOR_FUNCS@.c++
     74  Monitor.h \
     75  DNotify.h \
     76  DNotify.c++ \
     77  @MONITOR_FUNCS@.c++
    7578
    76 EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++
     79EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ \
     80  DNotify.h Monitor.h
    7781
  • src/Monitor.h

    old new  
     1//  Copyright (C) 2001 Red Hat, Inc.  All Rights Reserved.
     2//  Copyright (C) 1999 Silicon Graphics, Inc.  All Rights Reserved.
     3// 
     4//  This program is free software; you can redistribute it and/or modify it
     5//  under the terms of version 2 of the GNU General Public License as
     6//  published by the Free Software Foundation.
     7//
     8//  This program is distributed in the hope that it would be useful, but
     9//  WITHOUT ANY WARRANTY; without even the implied warranty of
     10//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  Further, any
     11//  license provided herein, whether implied or otherwise, is limited to
     12//  this program in accordance with the express provisions of the GNU
     13//  General Public License.  Patent licenses, if any, provided herein do not
     14//  apply to combinations of this program with other product or programs, or
     15//  any other product whatsoever.  This program is distributed without any
     16//  warranty that the program is delivered free of the rightful claim of any
     17//  third person by way of infringement or the like.  See the GNU General
     18//  Public License for more details.
     19//
     20//  You should have received a copy of the GNU General Public License along
     21//  with this program; if not, write the Free Software Foundation, Inc., 59
     22//  Temple Place - Suite 330, Boston MA 02111-1307, USA.
     23
     24#ifndef Monitor_included
     25#define Monitor_included
     26
     27#include "config.h"
     28#include <sys/stat.h>
     29#include <sys/types.h>
     30
     31struct stat;
     32
     33//  Monitor is an abstract baseclass for differend file monitoring
     34//  systems. The original system used was IMon, and the Montor API
     35//  is heavily influenced by that.
     36//  There can only be one instantiation of the Monitor object.
     37//
     38//  The user of this object uses express() and revoke() to
     39//  express/revoke interest in a file to imon.  There is also
     40//  a callback, the EventHandler.  When an event comes in,
     41//  the EventHandler is called.
     42//
     43//  The main implementers of the Monitor class is IMon and DNotify
     44
     45class Monitor {
     46public:
     47
     48    enum Status { OK = 0, BAD = -1 };
     49    enum Event { EXEC, EXIT, CHANGE };
     50
     51    typedef void (*EventHandler)(dev_t, ino_t, int event);
     52
     53    virtual Status express(const char *name, struct stat *stat_return) = 0;
     54    virtual Status revoke(const char *name, dev_t dev, ino_t ino) = 0;
     55};
     56
     57#endif /* !Monitor_included */
Note: See TracBrowser for help on using the repository browser.