From 297a8b7d6cb9df764b346147a6eb79d47774080c Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@Germany> Date: Mon, 7 Jun 2010 13:51:14 +0200 Subject: [PATCH] ENH: move fileMonitor stat vs. inotify to internal class - avoids potential mismatches between header and courtesy binaries --- src/Allwmake | 2 +- src/OSspecific/POSIX/Allwmake | 21 ++++ src/OSspecific/POSIX/Make/options | 4 +- src/OSspecific/POSIX/fileMonitor.C | 170 ++++++++++++++++++----------- src/OSspecific/POSIX/fileMonitor.H | 39 +++---- 5 files changed, 147 insertions(+), 89 deletions(-) create mode 100755 src/OSspecific/POSIX/Allwmake diff --git a/src/Allwmake b/src/Allwmake index 4da8d4f7192..e1589a40467 100755 --- a/src/Allwmake +++ b/src/Allwmake @@ -17,7 +17,7 @@ wmakeLnInclude OpenFOAM wmakeLnInclude OSspecific/$WM_OSTYPE Pstream/Allwmake -wmake libo OSspecific/$WM_OSTYPE +OSspecific/$WM_OSTYPE/Allwmake wmake libso OpenFOAM wmake libso lagrangian/basic diff --git a/src/OSspecific/POSIX/Allwmake b/src/OSspecific/POSIX/Allwmake new file mode 100755 index 00000000000..7819ce885bf --- /dev/null +++ b/src/OSspecific/POSIX/Allwmake @@ -0,0 +1,21 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # run from this directory + +# +# use <sys/inotify.h> if available (Linux) +# unless otherwise specified (with FOAM_USE_STAT) +# +# eg, ./Allwmake FOAM_USE_STAT +# +if [ -f /usr/include/sys/inotify.h -a "${1%USE_STAT}" = "$1" ] +then + unset FOAM_FILE_MONITOR +else + export FOAM_FILE_MONITOR="-DFOAM_USE_STAT" +fi + + +# make (non-shared) object +wmake libo + +# ----------------------------------------------------------------- end-of-file diff --git a/src/OSspecific/POSIX/Make/options b/src/OSspecific/POSIX/Make/options index b7e9d7211b0..be643469df3 100644 --- a/src/OSspecific/POSIX/Make/options +++ b/src/OSspecific/POSIX/Make/options @@ -1,3 +1 @@ -#ifdef SunOS64 -EXE_INC = -DFOAM_USE_STAT -#endif +EXE_INC = $(FOAM_FILE_MONITOR) diff --git a/src/OSspecific/POSIX/fileMonitor.C b/src/OSspecific/POSIX/fileMonitor.C index f7f0246c986..a812dec9429 100644 --- a/src/OSspecific/POSIX/fileMonitor.C +++ b/src/OSspecific/POSIX/fileMonitor.C @@ -37,7 +37,6 @@ Class # include "regIOobject.H" // for fileModificationSkew symbol #else # include <sys/inotify.h> -# include <stropts.h> # include <sys/ioctl.h> #endif @@ -49,8 +48,8 @@ template<> const char* Foam::NamedEnum<Foam::fileMonitor::fileState, 3>::names[] = { "unmodified", - "deleted", - "modified" + "modified", + "deleted" }; const Foam::NamedEnum<Foam::fileMonitor::fileState, 3> Foam::fileMonitor::fileStateNames_; @@ -58,7 +57,7 @@ const Foam::NamedEnum<Foam::fileMonitor::fileState, 3> namespace Foam { - // Reduction operator for PackedList of fileState + //- Reduction operator for PackedList of fileState class reduceFileStates { public: @@ -89,7 +88,7 @@ namespace Foam } }; - // Combine operator for PackedList of fileState + //- Combine operator for PackedList of fileState class combineReduceFileStates { public: @@ -98,22 +97,101 @@ namespace Foam x = reduceFileStates()(x, y); } }; + + + + //! @cond internalClass + //- Internal tracking via stat(3p) or inotify(7) + class fileMonitorWatcher + { + public: + +#ifdef FOAM_USE_STAT + //- From watch descriptor to modified time + HashTable<label, time_t> lastMod; + + //- initialize HashTable size + inline fileMonitorWatcher(const label sz = 20) + : + lastMod(sz) + {} + + inline label addWatch(const fileName& fName) + { + const label watchFd = lastMod.size(); + lastMod.insert(watchFd, lastModified(fName)); + return watchFd; + } + + inline bool removeWatch(const label watchFd) + { + return lastMod.erase(watchFd); + } + +#else + //- File descriptor for the inotify instance + int fd; + + //- Pre-allocated structure containing file descriptors + fd_set fdSet; + + //- initialize inotify + inline fileMonitorWatcher(const label dummy = 0) + : + fd(inotify_init()) + { + // Add notify descriptor to select fd_set + FD_ZERO(&fdSet); + FD_SET(fd, &fdSet); + } + + //- test if file descriptor is set + inline bool isSet() const + { + return FD_ISSET(fd, &fdSet); + } + + //- reset file descriptor + inline void reset() + { + FD_SET(fd, &fdSet); + } + + inline label addWatch(const fileName& fName) + { + return inotify_add_watch + ( + fd, + fName.c_str(), + // IN_ALL_EVENTS + IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MODIFY + ); + } + + inline bool removeWatch(const label watchFd) + { + return inotify_rm_watch(fd, int(watchFd)) == 0; + } +#endif + + }; + //! @endcond } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -#ifdef FOAM_USE_STAT void Foam::fileMonitor::checkFiles() const { +#ifdef FOAM_USE_STAT for ( - HashTable<label, time_t>::iterator iter = lastModified_.begin(); - iter != lastModified_.end(); + HashTable<label, time_t>::iterator iter = watcher_->lastMod.begin(); + iter != watcher_->lastMod.end(); ++iter ) { - label watchFd = iter.key(); + const label watchFd = iter.key(); const fileName& fName = watchFile_[watchFd]; time_t newTime = lastModified(fName); @@ -135,21 +213,18 @@ void Foam::fileMonitor::checkFiles() const } } } -} #else -void Foam::fileMonitor::checkFiles() const -{ while (true) { struct timeval zeroTimeout = {0, 0}; int ready = select ( - inotifyFd_+1, // num filedescriptors in watchSet_ - &watchSet_, // watchSet_ with only inotifyFd - NULL, - NULL, - &zeroTimeout + watcher_->fd+1, // num filedescriptors in fdSet + &(watcher_->fdSet), // fdSet with only inotifyFd + NULL, // No writefds + NULL, // No errorfds + &zeroTimeout // eNo timeout ); if (ready < 0) @@ -158,14 +233,14 @@ void Foam::fileMonitor::checkFiles() const << "Problem in issuing select." << abort(FatalError); } - else if (FD_ISSET(inotifyFd_, &watchSet_)) + else if (watcher_->isSet()) { struct inotify_event inotifyEvent; // Read first event ssize_t nBytes = read ( - inotifyFd_, + watcher_->fd, &inotifyEvent, sizeof(inotifyEvent) ); @@ -178,9 +253,9 @@ void Foam::fileMonitor::checkFiles() const << abort(FatalError); } - //Pout<< "mask:" << inotifyEvent.mask << endl; - //Pout<< "watchFd:" << inotifyEvent.wd << endl; - //Pout<< "watchName:" << watchFile_[inotifyEvent.wd] << endl; + // Pout<< "mask:" << inotifyEvent.mask << nl + // << "watchFd:" << inotifyEvent.wd << nl + // << "watchName:" << watchFile_[inotifyEvent.wd] << endl; switch (inotifyEvent.mask) { @@ -204,51 +279,37 @@ void Foam::fileMonitor::checkFiles() const } else { - // No data. Reset watchSet_ - FD_SET(inotifyFd_, &watchSet_); + // No data - reset + watcher_->reset(); return; } } -} #endif +} // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -// Null constructor -#ifdef FOAM_USE_STAT Foam::fileMonitor::fileMonitor() : state_(20), watchFile_(20), - lastModified_(20) + watcher_(new fileMonitorWatcher(20)) {} -#else - -Foam::fileMonitor::fileMonitor() -: - state_(20), - watchFile_(20), - inotifyFd_(inotify_init()) -{ - //- Add notify descriptor to select set - FD_ZERO(&watchSet_); - FD_SET(inotifyFd_, &watchSet_); -} - -#endif // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::fileMonitor::~fileMonitor() { - // Remove any remaining files + // Remove watch on any remaining files List<label> watchFds(state_.toc()); forAll(watchFds, i) { removeWatch(watchFds[i]); } + + delete watcher_; } @@ -257,18 +318,7 @@ Foam::fileMonitor::~fileMonitor() Foam::label Foam::fileMonitor::addWatch(const fileName& fName) { -#ifdef FOAM_USE_STAT - label watchFd = lastModified_.size(); - lastModified_.insert(watchFd, lastModified(fName)); -#else - label watchFd = inotify_add_watch - ( - inotifyFd_, - fName.c_str(), - //IN_ALL_EVENTS - IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MODIFY - ); -#endif + const label watchFd = watcher_->addWatch(fName); if (debug) { @@ -300,11 +350,7 @@ bool Foam::fileMonitor::removeWatch(const label watchFd) state_.erase(watchFd); watchFile_.erase(watchFd); -#ifdef FOAM_USE_STAT - return lastModified_.erase(watchFd); -#else - return inotify_rm_watch(inotifyFd_, int(watchFd)) == 0; -#endif + return watcher_->removeWatch(watchFd); } @@ -331,7 +377,7 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const label i = 0; forAllConstIter(Map<fileState>, state_, iter) { - stats[i++] = (unsigned int)(iter()); + stats[i++] = static_cast<unsigned int>(iter()); } // Save local state for warning message below PackedList<2> thisProcStats(stats); @@ -378,7 +424,7 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const void Foam::fileMonitor::setUnmodified(const label watchFd) { #ifdef FOAM_USE_STAT - lastModified_[watchFd] = lastModified(watchFile_[watchFd]); + watcher_->lastMod[watchFd] = lastModified(watchFile_[watchFd]); #endif Map<fileState>::iterator iter = state_.find(watchFd); diff --git a/src/OSspecific/POSIX/fileMonitor.H b/src/OSspecific/POSIX/fileMonitor.H index b9922eb3e2a..fbb0c4e2d64 100644 --- a/src/OSspecific/POSIX/fileMonitor.H +++ b/src/OSspecific/POSIX/fileMonitor.H @@ -27,13 +27,13 @@ Class Description Checking for changes to files. -!!!!!!!NOTE: - Default is to use inotify (Linux specific, since 2.6.13) +Note + The default is to use inotify (Linux specific, since 2.6.13) - Compile with FOAM_USE_STAT to use the stat function call. + Compiling with FOAM_USE_STAT (or if /usr/include/sys/inotify.h + does not exist) uses the stat function call. - - - works fine except for if file gets deleted and recreated + - works fine except when a file is deleted and recreated: it stops monitoring the file! (does work though if the file gets moved) @@ -48,7 +48,6 @@ SourceFiles #include <sys/types.h> #include "Map.H" #include "NamedEnum.H" -#include "labelList.H" #include "className.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -57,9 +56,10 @@ namespace Foam { class fileMonitor; +class fileMonitorWatcher; /*---------------------------------------------------------------------------*\ - Class fileMonitor Declaration + Class fileMonitor Declaration \*---------------------------------------------------------------------------*/ class fileMonitor @@ -73,8 +73,8 @@ public: enum fileState { UNMODIFIED = 0, - DELETED = 1, - MODIFIED = 2 + MODIFIED = 1, + DELETED = 2, }; static const NamedEnum<fileState, 3> fileStateNames_; @@ -84,22 +84,16 @@ private: //- State for all watchFds mutable Map<fileState> state_; - + //- From watch descriptor to filename HashTable<fileName, label> watchFile_; -#ifdef FOAM_USE_STAT + //- Watch mechanism (stat or inotify) + mutable fileMonitorWatcher *watcher_; - //- From watch descriptor to modified time - mutable HashTable<label, time_t> lastModified_; -#else - //- File descriptor for the inotify instance - int inotifyFd_; - //- Pre-allocated structure containing file descriptors - mutable fd_set watchSet_; + // Private Member Functions -#endif //- Update state_ from any events. void checkFiles() const; @@ -121,14 +115,13 @@ public: fileMonitor(); - // Destructor - - ~fileMonitor(); + //- Destructor + ~fileMonitor(); // Member Functions - //- Add file to watch. Returns watch descriptor + //- Add file to watch. Return watch descriptor label addWatch(const fileName&); //- Remove file to watch. Return true if successful -- GitLab