Ticket #193: dnotify.2.patch
File dnotify.2.patch, 28.3 KB (added by , 22 years ago) |
---|
-
fam-2.6.7/acconfig.h
old new 17 17 /* Define if the system has imon and IMONIOC_ ioctl flags. */ 18 18 #undef HAVE_IMON 19 19 20 /* Define if the system has the dnotify fcntl and it's gonna be used. */ 21 #undef USE_DNOTIFY 22 20 23 /* Define if the system has the struct revokdi and the IMONIOC_REVOKDI 21 24 ** ioctl flag. (IRIX 5.3 doesn't.) 22 25 */ -
fam-2.6.7/configure.in
old new 96 99 dnl AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h syslog.h unistd.h) 97 100 98 101 dnl 102 dnl Test for the linux dnotify fcntl 103 dnl 104 AC_MSG_CHECKING([for dnotify fcntl support]) 105 fam_save_cppflags="$CPPFLAGS" 106 CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" 107 AC_TRY_COMPILE([ 108 #define _GNU_SOURCE 109 #include <fcntl.h> 110 #include <unistd.h> 111 ], 112 [ int fd = 1; 113 fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)|DN_MULTISHOT); 114 ], have_dnotify=yes, have_dnotify=no) 115 use_dnotify=false 116 CPPFLAGS="$pango_save_cppflags" 117 AC_MSG_RESULT($have_dnotify) 118 119 dnl 99 120 dnl See if imon is available; if so, is it IRIX or Linux? 100 121 dnl 101 122 if test `uname` = 'IRIX' || test `uname` = 'IRIX64'; then … … 118 139 if test "$have_imon" != "yes"; then 119 140 have_imon=no 120 141 AC_DEFINE(HAVE_IMON, 0) 142 if test "$have_dnotify" = "yes"; then 143 AC_DEFINE(USE_DNOTIFY) 144 use_dnotify=true 145 fi 121 146 IMON_FUNCS=IMonNone 122 147 fi 148 AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify) 123 149 AC_SUBST(IMON_FUNCS) 124 150 echo "Using imon support module $IMON_FUNCS" 125 151 152 126 153 AC_CHECK_HEADER(sys/statvfs.h, [AC_DEFINE(HAVE_STATVFS, 1) have_statvfs="yes"], [AC_DEFINE(HAVE_STATVFS, 0) have_statvfs="no"]) 127 154 AC_CHECK_HEADER(sys/syssgi.h, AC_DEFINE(HAVE_SYSSGI, 1), AC_DEFINE(HAVE_SYSSGI, 0)) 128 155 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)) … … 572 599 dnl 573 600 dnl fam is a good deal less interesting without imon. 574 601 dnl 575 if test "$have_imon" != 'yes' ; then602 if test "$have_imon" != 'yes' -a "$have_dnotify" != 'yes'; then 576 603 cat << EOF 577 604 578 605 ****************************************************************** -
fam-2.6.7/fam/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 "alloc.h" 41 42 43 int DNotify::pipe_write_fd = -2; 44 int DNotify::pipe_read_fd = -2; 45 volatile sig_atomic_t DNotify::queue_overflowed = 0; 46 volatile sig_atomic_t DNotify::queue_changed = 0; 47 int DNotify::change_queue[QUEUESIZE]; 48 volatile int DNotify::queue_head = 0; // Only modified by read handler 49 volatile int DNotify::queue_tail = 0; // Only modified by signal handler 50 DNotify::EventHandler DNotify::ehandler; 51 52 DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE]; 53 DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE]; 54 55 struct 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 64 struct 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 74 struct DNotify::ChangeEventData 75 { 76 dev_t file_dev; 77 ino_t file_ino; 78 }; 79 80 DNotify::DNotify(EventHandler h) 81 { 82 assert(ehandler == NULL); 83 ehandler = h; 84 } 85 86 DNotify::~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 110 void 111 DNotify::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 128 void 129 DNotify::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 163 bool 164 DNotify::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 196 DNotify::DirWatch * 197 DNotify::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 219 DNotify::DirWatch * 220 DNotify::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 241 DNotify::FileWatch * 242 DNotify::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. 264 void 265 DNotify::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. 275 void 276 DNotify::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 284 void 285 DNotify::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 303 void 304 DNotify::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 322 DNotify::Status 323 DNotify::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 **p; 330 FileWatch *fw; 331 332 if (lstat (notify_dir, &stat) == -1) 333 return BAD; 334 335 dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino); 336 if (!dwatch) 337 { 338 Log::debug ("New DirWatch for %s (%x %x)\n", 339 notify_dir, (int)stat.st_dev, (int)stat.st_ino); 340 dwatch = new DirWatch; 341 dwatch->watches = NULL; 342 dwatch->hash_link = NULL; 343 dwatch->dir_dev = stat.st_dev; 344 dwatch->dir_ino = stat.st_ino; 345 346 dwatch->fd = open(notify_dir, O_RDONLY); 347 fcntl (dwatch->fd, F_SETSIG, SIGRTMIN); 348 fcntl (dwatch->fd, F_NOTIFY, 349 (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB) | DN_MULTISHOT); 350 hash_dirwatch (dwatch); 351 } 352 353 for (p=&dwatch->watches; *p; p=&(*p)->next) 354 { 355 fw = *p; 356 if (fw->file_dev == file_dev && fw->file_ino == file_ino) 357 return OK; 358 } 359 360 // No old FileWatch, need to add one: 361 Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino); 362 *p = new FileWatch; 363 fw = *p; 364 fw->next = NULL; 365 fw->file_dev = file_dev; 366 fw->file_ino = file_ino; 367 fw->dir_watch = dwatch; 368 hash_filewatch(fw); 369 return OK; 370 } 371 372 char * 373 dirname_dup (const char *name) 374 { 375 char *copy = strdup(name); 376 char *res = dirname(copy); 377 res = strdup(res); 378 free (copy); 379 return res; 380 } 381 382 DNotify::Status 383 DNotify::express(const char *name, struct stat *status) 384 { 385 struct stat stat; 386 char *notify_dir; 387 int res; 388 Status s; 389 dev_t dev; 390 ino_t ino; 391 392 Log::debug("express() name: %s\n", name); 393 394 if (!is_active()) 395 return BAD; 396 397 if (::lstat (name, &stat) == -1) 398 return BAD; 399 400 dev = stat.st_dev; 401 ino = stat.st_ino; 402 403 if ((stat.st_mode & S_IFMT) != S_IFDIR) 404 notify_dir = dirname_dup (name); 405 else 406 notify_dir = (char *)name; 407 408 s = watch_dir (notify_dir, dev, ino); 409 if (notify_dir != name) 410 free (notify_dir); 411 if (s) 412 return s; 413 414 // Check for a race condition; if someone removed or changed the 415 // file at the same time that we are expressing interest in it, 416 // revoke the interest so we don't get notifications about changes 417 // to a recycled inode that we don't otherwise care about. 418 // 419 struct stat st; 420 if (status == NULL) { 421 status = &st; 422 } 423 if (::lstat(name, status) == -1) { 424 Log::perror("stat on \"%s\" failed", name); 425 revoke(name, stat.st_dev, stat.st_ino); 426 return BAD; 427 } 428 if (status->st_dev != stat.st_dev 429 || status->st_ino != stat.st_ino) { 430 Log::error("File \"%s\" changed between express and stat", 431 name); 432 revoke(name, stat.st_dev, stat.st_ino); 433 return BAD; 434 } 435 436 Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name, 437 major(status->st_dev), minor(status->st_dev), 438 status->st_ino); 439 return OK; 440 } 441 442 DNotify::Status 443 DNotify::revoke(const char *name, dev_t dev, ino_t ino) 444 { 445 FileWatch *fwatch; 446 DirWatch *dwatch; 447 448 Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino); 449 450 if (!is_active()) 451 return BAD; 452 453 // Lookup FileWatch by dev:ino, and its DirWatch. 454 fwatch = lookup_filewatch (dev, ino); 455 if (fwatch == NULL) 456 return BAD; 457 458 dwatch = fwatch->dir_watch; 459 460 // delete FileWatch, if last FileWatch: close fd, delete DirWatch 461 Log::debug ("Destroying FileWatch for (%x %x)\n", 462 (int)fwatch->file_dev, (int)fwatch->file_ino); 463 FileWatch **p; 464 for (p=&dwatch->watches; *p; p=&(*p)->next) 465 { 466 if (*p == fwatch) 467 { 468 *p = (*p)->next; 469 break; 470 } 471 } 472 unhash_filewatch(fwatch); 473 delete fwatch; 474 if (dwatch->watches == NULL) 475 { 476 Log::debug ("Destroying DirWatch for (%x %x)\n", 477 (int)dwatch->dir_dev, (int)dwatch->dir_ino); 478 close(dwatch->fd); 479 unhash_dirwatch(dwatch); 480 delete dwatch; 481 } 482 483 return OK; 484 } 485 486 487 void 488 DNotify::all_watches_changed(void) 489 { 490 int i; 491 FileWatch *fw; 492 493 for (i=0; i<FILE_HASHSIZE; i++) 494 { 495 fw = file_hash[i]; 496 while (fw) 497 { 498 (*ehandler)(fw->file_dev, fw->file_ino, CHANGE); 499 500 fw = fw->hash_link; 501 } 502 } 503 } 504 505 506 void 507 DNotify::read_handler(int fd, void *) 508 { 509 static char readbuf[5000]; 510 DirWatch *dw; 511 FileWatch *fw; 512 int snap_queue_tail; 513 int last_fd; 514 515 int rc = read(fd, readbuf, sizeof readbuf); 516 queue_changed = 0; 517 if (rc < 0) 518 Log::perror("pipe read"); 519 else if (queue_overflowed) 520 { 521 // There is a *slight* race condition here. Between reading 522 // the queue_overflow flag and resetting it. But it doesn't 523 // matter, since I'm gonna handle the overflow after reseting 524 // anyway. 525 queue_overflowed = false; 526 527 // We're soon gonna check all watches anyway, so 528 // get rid of the current queue 529 queue_head = queue_tail; 530 531 all_watches_changed (); 532 } 533 else 534 { 535 // Don't read events that happen later than 536 // the initial read. (Otherwise skipping fd's 537 // might miss some changes). 538 snap_queue_tail = queue_tail; 539 last_fd = -1; 540 while (queue_head != snap_queue_tail) 541 { 542 fd = change_queue[queue_head]; 543 queue_head = (queue_head + 1) % QUEUESIZE; 544 545 // Skip multiple changes to the same fd 546 if (fd != last_fd) 547 { 548 dw = lookup_dirwatch (fd); 549 if (dw) 550 { 551 int n_watches, i; 552 ChangeEventData *data; 553 554 Log::debug("dnotify said dev %d/%d, ino %ld changed", 555 major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino); 556 557 n_watches = 0; 558 for (fw=dw->watches; fw; fw=fw->next) 559 n_watches++; 560 561 data = new ChangeEventData[n_watches]; 562 563 i = 0; 564 for (fw=dw->watches; fw; fw=fw->next) 565 { 566 data[i].file_dev = fw->file_dev; 567 data[i].file_ino = fw->file_ino; 568 i++; 569 } 570 571 for (i = 0; i < n_watches; i++) 572 { 573 (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE); 574 } 575 576 delete[] data; 577 } 578 } 579 last_fd = fd; 580 } 581 } 582 } 583 -
fam-2.6.7/fam/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 42 class DNotify : public Monitor { 43 public: 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 52 private: 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 = 257 }; 72 static DirWatch *dir_hash[DIR_HASHSIZE]; 73 enum { FILE_HASHSIZE = 257 }; 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 -
fam-2.6.7/fam/IMon.h
old new 24 24 #define IMon_included 25 25 26 26 #include "config.h" 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 30 #include "Boolean.h" 27 #include "Monitor.h" 31 28 32 29 struct stat; 33 30 … … 41 38 // 42 39 // The user of the IMon object is the Interest class. 43 40 44 class IMon {41 class IMon : public Monitor { 45 42 46 43 public: 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 44 IMon(EventHandler h); 54 45 ~IMon(); 55 46 56 47 static bool is_active(); 57 48 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); 60 51 61 52 private: 62 63 53 // Class Variables 64 54 65 55 static int imonfd; -
fam-2.6.7/fam/Interest.c++
old new 41 41 #include "Event.h" 42 42 #include "FileSystem.h" 43 43 #include "IMon.h" 44 #include "DNotify.h" 44 45 #include "Log.h" 45 46 #include "Pollster.h" 46 47 #include "timeval.h" 47 48 48 49 Interest *Interest::hashtable[]; 49 IMon Interest::imon(imon_handler); 50 51 #ifdef USE_DNOTIFY 52 static DNotify dnotify(Interest::monitor_handler); 53 Monitor * Interest::monitor = &dnotify; 54 #else 55 static IMon imon(Interest::monitor_handler); 56 Monitor * Interest::monitor = &imon; 57 #endif 58 50 59 bool Interest::xtab_verification = true; 51 60 52 61 Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev) … … 58 67 myhost(host), 59 68 mypath_exported_to_host(ev == NO_VERIFY_EXPORTED) 60 69 { 61 memset(&old_stat, 0, sizeof(old_stat)); 62 IMon::Status s = IMon::BAD;63 64 s = imon.express(name, &old_stat);65 if (s != IMon::OK)70 memset(&old_stat, 0, sizeof(old_stat)); 71 72 Monitor::Status s = Monitor::BAD; 73 s = monitor->express(name, &old_stat); 74 if (s != Monitor::OK) 66 75 { int rc = lstat(name, &old_stat); 67 76 if (rc < 0) 68 77 { Log::info("can't lstat %s", name); … … 99 108 } 100 109 #endif 101 110 102 if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK);111 if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK); 103 112 } 104 113 105 114 Interest::~Interest() … … 127 136 pp = &p->hashlink; // move to next element 128 137 } 129 138 if (!found_same) 130 (void) imon.revoke(name(), dev, ino);139 (void) monitor->revoke(name(), dev, ino); 131 140 } 132 141 } 133 142 … … 146 155 147 156 // Express interest. 148 157 IMon::Status s = IMon::BAD; 149 s = imon.express(name(), NULL);158 s = monitor->express(name(), NULL); 150 159 if (s != IMon::OK) { 151 160 return true; 152 161 } … … 247 256 } 248 257 249 258 void 250 Interest:: imon_handler(dev_t device, ino_t inumber, int event)259 Interest::monitor_handler(dev_t device, ino_t inumber, int event) 251 260 { 252 261 assert(device || inumber); 253 262 254 263 for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next) 255 264 { next = p->hashlink; 256 265 if (p->ino == inumber && p->dev == device) 257 { if (event == IMon::EXEC)266 { if (event == Monitor::EXEC) 258 267 { p->cur_exec_state = EXECUTING; 259 268 (void) p->report_exec_state(); 260 269 } 261 else if (event == IMon::EXIT)270 else if (event == Monitor::EXIT) 262 271 { p->cur_exec_state = NOT_EXECUTING; 263 272 (void) p->report_exec_state(); 264 273 } 265 274 else 266 { assert(event == IMon::CHANGE);275 { assert(event == Monitor::CHANGE); 267 276 p->scan(); 268 277 } 269 278 } -
fam-2.6.7/fam/Interest.h
old new 32 32 33 33 class Event; 34 34 class FileSystem; 35 class IMon;35 class Monitor; 36 36 struct stat; 37 37 38 38 // Interest -- abstract base class for filesystem entities of interest. … … 74 74 75 75 // Public Class Method 76 76 77 static void imon_handler(dev_t, ino_t, int event);77 static void monitor_handler(dev_t, ino_t, int event); 78 78 79 79 static void enable_xtab_verification(bool enable); 80 80 … … 121 121 122 122 // Class Variables 123 123 124 static IMon imon;124 static Monitor *monitor; 125 125 static Interest *hashtable[HASHSIZE]; 126 126 static bool xtab_verification; 127 127 -
fam-2.6.7/fam/Makefile.am
old new 3 3 bin_PROGRAMS = fam 4 4 sysconf_DATA = fam.conf 5 5 6 if USE_DNOTIFY 7 DNOTIFY_FILES = DNotify.c++ 8 else 9 DNOTIFY_FILES = 10 endif 11 6 12 fam_SOURCES = \ 7 13 Activity.c++ \ 8 14 Activity.h \ … … 20 26 Directory.h \ 21 27 DirectoryScanner.c++ \ 22 28 DirectoryScanner.h \ 29 DNotify.h \ 23 30 Event.c++ \ 24 31 Event.h \ 25 32 File.c++ \ … … 48 55 NFSFileSystem.h \ 49 56 NetConnection.c++ \ 50 57 NetConnection.h \ 58 Monitor.h \ 51 59 Pollster.c++ \ 52 60 Pollster.h \ 53 61 Request.h \ … … 72 80 main.c++ \ 73 81 timeval.c++ \ 74 82 timeval.h \ 75 @IMON_FUNCS@.c++ 83 @IMON_FUNCS@.c++ \ 84 $(DNOTIFY_FILES) 76 85 77 EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ 86 EXTRA_fam_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ 78 87 79 88 fam_LDADD = -lrpcsvc $(top_srcdir)/support/libsupport.a 80 89 -
fam-2.6.7/fam/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 31 struct 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 45 class Monitor { 46 public: 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 */ -
fam-2.6.7/include/BTree.h
old new 271 271 n += that->n + 1; 272 272 link[n] = that->link[that->n]; 273 273 that->n = 0; 274 that->link[0] = NULL;274 that->link[0] = 0; 275 275 } 276 276 277 277 /////////////////////////////////////////////////////////////////////////////// … … 280 280 281 281 template <class K, class V> 282 282 BTree<K, V>::BTree() 283 : root( NULL), npairs(0)283 : root(0), npairs(0) 284 284 { 285 285 assert(!(fanout % 2)); 286 286 } … … 407 407 BTree<Key, Value>::Closure 408 408 BTree<Key, Value>::insert(Node *p, const Key& key, const Value& value) 409 409 { 410 if (!p) return Closure(key, value, NULL);410 if (!p) return Closure(key, value, 0); 411 411 // If you're running Purify on a client linking with libfam, and it says 412 412 // that line is causing a 3-byte UMR for BTree<int, bool>::insert() in 413 413 // FAMNextEvent() ("Reading 8 bytes from 0x... on the stack (3 bytes at … … 475 475 case UNDER: 476 476 if (root->n == 0) 477 477 { Node *nr = root->link[0]; 478 root->link[0] = NULL; // don't delete subtree478 root->link[0] = 0; // don't delete subtree 479 479 delete root; 480 480 root = nr; 481 481 } … … 507 507 Node *cp = p->link[i]; 508 508 assert(cp); 509 509 510 Node *rp = i < p->n ? p->link[i + 1] : NULL;511 Node *lp = i > 0 ? p->link[i - 1] : NULL;510 Node *rp = i < p->n ? p->link[i + 1] : 0; 511 Node *lp = i > 0 ? p->link[i - 1] : 0; 512 512 assert(!rp || rp->n >= fanout / 2); 513 513 assert(!lp || lp->n >= fanout / 2); 514 514