mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: fileMonitor : monitor directory, not file
Some editors (emacs) rename file at startup to the backup version. Hence watching the original file tells one nothing.
This commit is contained in:
@ -31,6 +31,7 @@ Class
|
|||||||
#include "Pstream.H"
|
#include "Pstream.H"
|
||||||
#include "PackedList.H"
|
#include "PackedList.H"
|
||||||
#include "PstreamReduceOps.H"
|
#include "PstreamReduceOps.H"
|
||||||
|
#include "OSspecific.H"
|
||||||
|
|
||||||
#ifdef FOAM_USE_STAT
|
#ifdef FOAM_USE_STAT
|
||||||
# include "OSspecific.H"
|
# include "OSspecific.H"
|
||||||
@ -112,50 +113,104 @@ namespace Foam
|
|||||||
|
|
||||||
#ifdef FOAM_USE_STAT
|
#ifdef FOAM_USE_STAT
|
||||||
//- From watch descriptor to modified time
|
//- From watch descriptor to modified time
|
||||||
HashTable<label, time_t> lastMod;
|
DynamicList<time_t> lastMod_;
|
||||||
|
|
||||||
//- initialize HashTable size
|
//- initialize HashTable size
|
||||||
inline fileMonitorWatcher(const label sz = 20)
|
inline fileMonitorWatcher(const label sz = 20)
|
||||||
:
|
:
|
||||||
lastMod(sz)
|
lastMod_(sz)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline label addWatch(const fileName& fName)
|
inline bool addWatch(const label watchFd, const fileName& fName)
|
||||||
{
|
{
|
||||||
const label watchFd = lastMod.size();
|
if (watchFd < lastMod_.size() && lastMod_[watchFd] != 0)
|
||||||
lastMod.insert(watchFd, lastModified(fName));
|
{
|
||||||
return watchFd;
|
// Reuse of watchFd : should have lastMod set to 0.
|
||||||
|
FatalErrorIn("addWatch(const label, const fileName&)")
|
||||||
|
<< "Problem adding watch " << watchFd
|
||||||
|
<< " to file " << fName
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastMod_(watchFd) = lastModified(fName);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool removeWatch(const label watchFd)
|
inline bool removeWatch(const label watchFd)
|
||||||
{
|
{
|
||||||
return lastMod.erase(watchFd);
|
lastMod_[watchFd] = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
//- File descriptor for the inotify instance
|
//- File descriptor for the inotify instance
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
//- initialize inotify
|
//- Current watchIDs and corresponding directory id
|
||||||
inline fileMonitorWatcher(const label dummy = 0)
|
DynamicList<label> dirWatches_;
|
||||||
|
DynamicList<fileName> dirFiles_;
|
||||||
|
|
||||||
|
//- initialise inotify
|
||||||
|
inline fileMonitorWatcher(const label sz = 20)
|
||||||
:
|
:
|
||||||
fd(inotify_init())
|
fd(inotify_init()),
|
||||||
|
dirWatches_(sz),
|
||||||
|
dirFiles_(sz)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline label addWatch(const fileName& fName)
|
//- remove all watches
|
||||||
|
inline ~fileMonitorWatcher()
|
||||||
{
|
{
|
||||||
return inotify_add_watch
|
forAll(dirWatches_, i)
|
||||||
|
{
|
||||||
|
if (dirWatches_[i] >= 0)
|
||||||
|
{
|
||||||
|
if (inotify_rm_watch(fd, int(dirWatches_[i])))
|
||||||
|
{
|
||||||
|
WarningIn("fileMonitor::~fileMonitor()")
|
||||||
|
<< "Failed deleting directory watch "
|
||||||
|
<< dirWatches_[i] << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool addWatch(const label watchFd, const fileName& fName)
|
||||||
|
{
|
||||||
|
// Add/retrieve watch on directory containing file
|
||||||
|
label dirWatchID = inotify_add_watch
|
||||||
(
|
(
|
||||||
fd,
|
fd,
|
||||||
fName.c_str(),
|
fName.path().c_str(),
|
||||||
// IN_ALL_EVENTS
|
IN_CLOSE_WRITE
|
||||||
IN_CLOSE_WRITE | IN_DELETE_SELF //| IN_MODIFY
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (dirWatchID < 0)
|
||||||
|
{
|
||||||
|
FatalErrorIn("addWatch(const label, const fileName&)")
|
||||||
|
<< "Failed adding watch " << watchFd
|
||||||
|
<< " to directory " << fName
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watchFd < dirWatches_.size() && dirWatches_[watchFd] != -1)
|
||||||
|
{
|
||||||
|
// Reuse of watchFd : should have dir watchID set to -1.
|
||||||
|
FatalErrorIn("addWatch(const label, const fileName&)")
|
||||||
|
<< "Problem adding watch " << watchFd
|
||||||
|
<< " to file " << fName
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
dirWatches_(watchFd) = dirWatchID;
|
||||||
|
dirFiles_(watchFd) = fName.name();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool removeWatch(const label watchFd)
|
inline bool removeWatch(const label watchFd)
|
||||||
{
|
{
|
||||||
return inotify_rm_watch(fd, int(watchFd)) == 0;
|
dirWatches_[watchFd] = -1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -169,32 +224,30 @@ namespace Foam
|
|||||||
void Foam::fileMonitor::checkFiles() const
|
void Foam::fileMonitor::checkFiles() const
|
||||||
{
|
{
|
||||||
#ifdef FOAM_USE_STAT
|
#ifdef FOAM_USE_STAT
|
||||||
for
|
forAll(watcher_->lastMod_, watchFd)
|
||||||
(
|
|
||||||
HashTable<label, time_t>::iterator iter = watcher_->lastMod.begin();
|
|
||||||
iter != watcher_->lastMod.end();
|
|
||||||
++iter
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const label watchFd = iter.key();
|
time_t oldTime = watcher_->lastMod_[watchFd];
|
||||||
const fileName& fName = watchFile_[watchFd];
|
|
||||||
time_t newTime = lastModified(fName);
|
|
||||||
|
|
||||||
if (newTime == 0)
|
if (oldTime != 0)
|
||||||
{
|
{
|
||||||
state_.set(watchFd, DELETED);
|
const fileName& fName = watchFile_[watchFd];
|
||||||
}
|
time_t newTime = lastModified(fName);
|
||||||
else
|
|
||||||
{
|
if (newTime == 0)
|
||||||
time_t oldTime = iter();
|
|
||||||
if (newTime > (oldTime + regIOobject::fileModificationSkew))
|
|
||||||
{
|
{
|
||||||
iter() = newTime;
|
state_[watchFd] = DELETED;
|
||||||
state_.set(watchFd, MODIFIED);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state_.set(watchFd, UNMODIFIED);
|
if (newTime > (oldTime + regIOobject::fileModificationSkew))
|
||||||
|
{
|
||||||
|
watcher_->lastMod_[watchFd] = newTime;
|
||||||
|
state_[watchFd] = MODIFIED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state_[watchFd] = UNMODIFIED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,26 +303,30 @@ void Foam::fileMonitor::checkFiles() const
|
|||||||
&buffer[i]
|
&buffer[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pout<< "mask:" << inotifyEvent->mask << nl
|
//Pout<< "watchFd:" << inotifyEvent->wd << nl
|
||||||
// << "watchFd:" << inotifyEvent->wd << nl
|
// << "mask:" << inotifyEvent->mask << nl
|
||||||
// << "watchName:" << watchFile_[inotifyEvent->wd] << endl;
|
// << endl;
|
||||||
|
//Pout<< "file:" << fileName(inotifyEvent->name) << endl;
|
||||||
|
//Pout<< "len:" << inotifyEvent->len << endl;
|
||||||
|
|
||||||
if (inotifyEvent->mask % IN_DELETE_SELF)
|
if ((inotifyEvent->mask & IN_CLOSE_WRITE) && inotifyEvent->len)
|
||||||
{
|
{
|
||||||
Map<fileState>::iterator iter =
|
// Search for file
|
||||||
state_.find(label(inotifyEvent->wd));
|
forAll(watcher_->dirWatches_, i)
|
||||||
iter() = DELETED;
|
{
|
||||||
}
|
label id = watcher_->dirWatches_[i];
|
||||||
else if
|
if
|
||||||
(
|
(
|
||||||
//(inotifyEvent->mask % IN_MODIFY)
|
id == inotifyEvent->wd
|
||||||
(inotifyEvent->mask % IN_CLOSE_WRITE)
|
&& inotifyEvent->name == watcher_->dirFiles_[i]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Map<fileState>::iterator iter =
|
// Correct directory and name
|
||||||
state_.find(label(inotifyEvent->wd));
|
state_[i] = MODIFIED;
|
||||||
iter() = MODIFIED;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += EVENT_SIZE + inotifyEvent->len;
|
i += EVENT_SIZE + inotifyEvent->len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,6 +346,7 @@ Foam::fileMonitor::fileMonitor()
|
|||||||
:
|
:
|
||||||
state_(20),
|
state_(20),
|
||||||
watchFile_(20),
|
watchFile_(20),
|
||||||
|
freeWatchFds_(2),
|
||||||
watcher_(new fileMonitorWatcher(20))
|
watcher_(new fileMonitorWatcher(20))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -296,24 +354,27 @@ Foam::fileMonitor::fileMonitor()
|
|||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileMonitor::~fileMonitor()
|
Foam::fileMonitor::~fileMonitor()
|
||||||
{
|
{}
|
||||||
// Remove watch on any remaining files
|
|
||||||
List<label> watchFds(state_.toc());
|
|
||||||
forAll(watchFds, i)
|
|
||||||
{
|
|
||||||
removeWatch(watchFds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete watcher_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::label Foam::fileMonitor::addWatch(const fileName& fName)
|
Foam::label Foam::fileMonitor::addWatch(const fileName& fName)
|
||||||
{
|
{
|
||||||
const label watchFd = watcher_->addWatch(fName);
|
label watchFd;
|
||||||
|
|
||||||
|
label sz = freeWatchFds_.size();
|
||||||
|
if (sz)
|
||||||
|
{
|
||||||
|
watchFd = freeWatchFds_[sz-1];
|
||||||
|
freeWatchFds_.setSize(sz-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
watchFd = state_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
watcher_->addWatch(watchFd, fName);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
@ -328,8 +389,8 @@ Foam::label Foam::fileMonitor::addWatch(const fileName& fName)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state_.insert(watchFd, UNMODIFIED);
|
state_(watchFd) = UNMODIFIED;
|
||||||
watchFile_.insert(watchFd, fName);
|
watchFile_(watchFd) = fName;
|
||||||
}
|
}
|
||||||
return watchFd;
|
return watchFd;
|
||||||
}
|
}
|
||||||
@ -343,8 +404,7 @@ bool Foam::fileMonitor::removeWatch(const label watchFd)
|
|||||||
<< watchFile_[watchFd] << endl;
|
<< watchFile_[watchFd] << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_.erase(watchFd);
|
freeWatchFds_.append(watchFd);
|
||||||
watchFile_.erase(watchFd);
|
|
||||||
return watcher_->removeWatch(watchFd);
|
return watcher_->removeWatch(watchFd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,10 +429,9 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const
|
|||||||
if (syncPar)
|
if (syncPar)
|
||||||
{
|
{
|
||||||
PackedList<2> stats(state_.size());
|
PackedList<2> stats(state_.size());
|
||||||
label i = 0;
|
forAll(state_, watchFd)
|
||||||
forAllConstIter(Map<fileState>, state_, iter)
|
|
||||||
{
|
{
|
||||||
stats[i++] = static_cast<unsigned int>(iter());
|
stats[watchFd] = static_cast<unsigned int>(state_[watchFd]);
|
||||||
}
|
}
|
||||||
// Save local state for warning message below
|
// Save local state for warning message below
|
||||||
PackedList<2> thisProcStats(stats);
|
PackedList<2> thisProcStats(stats);
|
||||||
@ -391,26 +450,24 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
forAll(state_, watchFd)
|
||||||
forAllIter(Map<fileState>, state_, iter)
|
|
||||||
{
|
{
|
||||||
if (thisProcStats[i] != UNMODIFIED)
|
if (thisProcStats[watchFd] != UNMODIFIED)
|
||||||
{
|
{
|
||||||
if (stats[i] == UNMODIFIED)
|
if (stats[watchFd] == UNMODIFIED)
|
||||||
{
|
{
|
||||||
WarningIn("fileMonitor::updateStates(const bool) const")
|
WarningIn("fileMonitor::updateStates(const bool) const")
|
||||||
<< "Delaying reading " << watchFile_[iter.key()]
|
<< "Delaying reading " << watchFile_[watchFd]
|
||||||
<< " due to inconsistent "
|
<< " due to inconsistent "
|
||||||
"file time-stamps between processors"
|
"file time-stamps between processors"
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int stat = stats[i];
|
unsigned int stat = stats[watchFd];
|
||||||
iter() = fileState(stat);
|
state_[watchFd] = fileState(stat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,19 +476,9 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const
|
|||||||
void Foam::fileMonitor::setUnmodified(const label watchFd)
|
void Foam::fileMonitor::setUnmodified(const label watchFd)
|
||||||
{
|
{
|
||||||
#ifdef FOAM_USE_STAT
|
#ifdef FOAM_USE_STAT
|
||||||
watcher_->lastMod[watchFd] = lastModified(watchFile_[watchFd]);
|
watcher_->lastMod_[watchFd] = lastModified(watchFile_[watchFd]);
|
||||||
#endif
|
#endif
|
||||||
|
state_[watchFd] = UNMODIFIED;
|
||||||
Map<fileState>::iterator iter = state_.find(watchFd);
|
|
||||||
|
|
||||||
if (iter == state_.end())
|
|
||||||
{
|
|
||||||
FatalErrorIn("fileMonitor::setUnmodified(const label)")
|
|
||||||
<< "Illegal watchFd " << watchFd
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
iter() = UNMODIFIED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -33,10 +33,6 @@ Note
|
|||||||
Compiling with FOAM_USE_STAT (or if /usr/include/sys/inotify.h
|
Compiling with FOAM_USE_STAT (or if /usr/include/sys/inotify.h
|
||||||
does not exist) uses the stat function call.
|
does not exist) uses the stat function call.
|
||||||
|
|
||||||
- works fine except when a file is deleted and recreated:
|
|
||||||
it stops monitoring the file!
|
|
||||||
(does work though if the file gets moved)
|
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
fileMonitor.C
|
fileMonitor.C
|
||||||
|
|
||||||
@ -46,9 +42,9 @@ SourceFiles
|
|||||||
#define fileMonitor_H
|
#define fileMonitor_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "Map.H"
|
|
||||||
#include "NamedEnum.H"
|
#include "NamedEnum.H"
|
||||||
#include "className.H"
|
#include "className.H"
|
||||||
|
#include "DynamicList.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -83,13 +79,16 @@ private:
|
|||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
//- State for all watchFds
|
//- State for all watchFds
|
||||||
mutable Map<fileState> state_;
|
mutable DynamicList<fileState> state_;
|
||||||
|
|
||||||
//- From watch descriptor to filename
|
//- Filename for all watchFds
|
||||||
HashTable<fileName, label> watchFile_;
|
DynamicList<fileName> watchFile_;
|
||||||
|
|
||||||
|
//- Free watchFds
|
||||||
|
DynamicList<label> freeWatchFds_;
|
||||||
|
|
||||||
//- Watch mechanism (stat or inotify)
|
//- Watch mechanism (stat or inotify)
|
||||||
mutable fileMonitorWatcher *watcher_;
|
mutable autoPtr<fileMonitorWatcher> watcher_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|||||||
@ -371,6 +371,11 @@ Foam::Time::Time
|
|||||||
|
|
||||||
Foam::Time::~Time()
|
Foam::Time::~Time()
|
||||||
{
|
{
|
||||||
|
if (controlDict_.watchIndex() != -1)
|
||||||
|
{
|
||||||
|
removeWatch(controlDict_.watchIndex());
|
||||||
|
}
|
||||||
|
|
||||||
// destroy function objects first
|
// destroy function objects first
|
||||||
functionObjects_.clear();
|
functionObjects_.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,6 +184,7 @@ void Foam::Time::readDict()
|
|||||||
if (!runTimeModifiable_ && controlDict_.watchIndex() != -1)
|
if (!runTimeModifiable_ && controlDict_.watchIndex() != -1)
|
||||||
{
|
{
|
||||||
removeWatch(controlDict_.watchIndex());
|
removeWatch(controlDict_.watchIndex());
|
||||||
|
controlDict_.watchIndex() = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user