Linux real time indexer: fix monitoring inactive under topdirs members which were symbolic links
This commit is contained in:
parent
cbcefc1517
commit
9e0018034c
@ -1,6 +1,6 @@
|
|||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
#ifdef RCL_MONITOR
|
#ifdef RCL_MONITOR
|
||||||
/* Copyright (C) 2006-2021 J.F.Dockes
|
/* Copyright (C) 2006-2022 J.F.Dockes
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
@ -44,7 +44,6 @@
|
|||||||
* http://code.google.com/p/simplefilewatcher/ also MIT licensed.
|
* http://code.google.com/p/simplefilewatcher/ also MIT licensed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -69,7 +68,7 @@ public:
|
|||||||
RclMonitor() {}
|
RclMonitor() {}
|
||||||
virtual ~RclMonitor() {}
|
virtual ~RclMonitor() {}
|
||||||
|
|
||||||
virtual bool addWatch(const string& path, bool isDir) = 0;
|
virtual bool addWatch(const string& path, bool isDir, bool follow = false) = 0;
|
||||||
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) = 0;
|
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) = 0;
|
||||||
virtual bool ok() const = 0;
|
virtual bool ok() const = 0;
|
||||||
// Does this monitor generate 'exist' events at startup?
|
// Does this monitor generate 'exist' events at startup?
|
||||||
@ -106,6 +105,10 @@ public:
|
|||||||
MONDEB("walkerCB: processone " << fn << " m_mon " << m_mon <<
|
MONDEB("walkerCB: processone " << fn << " m_mon " << m_mon <<
|
||||||
" m_mon->ok " << (m_mon ? m_mon->ok() : false) << "\n");
|
" m_mon->ok " << (m_mon ? m_mon->ok() : false) << "\n");
|
||||||
|
|
||||||
|
// We set the watch follow links flag for the topdir only.
|
||||||
|
bool initfollow = m_initfollow;
|
||||||
|
m_initfollow = false;
|
||||||
|
|
||||||
if (flg == FsTreeWalker::FtwDirEnter || flg == FsTreeWalker::FtwDirReturn) {
|
if (flg == FsTreeWalker::FtwDirEnter || flg == FsTreeWalker::FtwDirReturn) {
|
||||||
m_config->setKeyDir(fn);
|
m_config->setKeyDir(fn);
|
||||||
// Set up skipped patterns for this subtree.
|
// Set up skipped patterns for this subtree.
|
||||||
@ -128,7 +131,7 @@ public:
|
|||||||
if (!m_mon || !m_mon->ok())
|
if (!m_mon || !m_mon->ok())
|
||||||
return FsTreeWalker::FtwError;
|
return FsTreeWalker::FtwError;
|
||||||
// We do nothing special if addWatch fails for a reasonable reason
|
// We do nothing special if addWatch fails for a reasonable reason
|
||||||
if (!m_mon->isRecursive() && !m_mon->addWatch(fn, true)) {
|
if (!m_mon->isRecursive() && !m_mon->addWatch(fn, true, initfollow)) {
|
||||||
if (m_mon->saved_errno != EACCES && m_mon->saved_errno != ENOENT) {
|
if (m_mon->saved_errno != EACCES && m_mon->saved_errno != ENOENT) {
|
||||||
LOGINF("walkerCB: addWatch failed\n");
|
LOGINF("walkerCB: addWatch failed\n");
|
||||||
return FsTreeWalker::FtwError;
|
return FsTreeWalker::FtwError;
|
||||||
@ -160,6 +163,7 @@ private:
|
|||||||
RclMonitor *m_mon;
|
RclMonitor *m_mon;
|
||||||
RclMonEventQueue *m_queue;
|
RclMonEventQueue *m_queue;
|
||||||
FsTreeWalker& m_walker;
|
FsTreeWalker& m_walker;
|
||||||
|
bool m_initfollow{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool rclMonAddTopWatches(
|
static bool rclMonAddTopWatches(
|
||||||
@ -185,11 +189,12 @@ static bool rclMonAddTopWatches(
|
|||||||
} else {
|
} else {
|
||||||
walker.setOpts(FsTreeWalker::FtwOptNone);
|
walker.setOpts(FsTreeWalker::FtwOptNone);
|
||||||
}
|
}
|
||||||
if (path_isdir(dir, follow)) {
|
// We always follow links for the topdirs members, and only use the config for subdirs
|
||||||
LOGDEB("rclMonRcvRun: walking " << dir << "\n");
|
if (path_isdir(dir, true)) {
|
||||||
|
LOGDEB("rclMonRcvRun: walking " << dir << " monrecurs " << mon->isRecursive() << "\n");
|
||||||
// If the fs watcher is recursive, we add the watches for the topdirs here, and walk the
|
// If the fs watcher is recursive, we add the watches for the topdirs here, and walk the
|
||||||
// tree just for generating initial events.
|
// tree just for generating initial events.
|
||||||
if (mon->isRecursive() && !mon->addWatch(dir, true)) {
|
if (mon->isRecursive() && !mon->addWatch(dir, true, true)) {
|
||||||
if (mon->saved_errno != EACCES && mon->saved_errno != ENOENT) {
|
if (mon->saved_errno != EACCES && mon->saved_errno != ENOENT) {
|
||||||
LOGERR("rclMonAddTopWatches: addWatch failed for [" << dir << "]\n");
|
LOGERR("rclMonAddTopWatches: addWatch failed for [" << dir << "]\n");
|
||||||
return false;
|
return false;
|
||||||
@ -205,7 +210,8 @@ static bool rclMonAddTopWatches(
|
|||||||
} else {
|
} else {
|
||||||
// We have to special-case regular files which are part of the topdirs list because the
|
// We have to special-case regular files which are part of the topdirs list because the
|
||||||
// tree walker only adds watches for directories
|
// tree walker only adds watches for directories
|
||||||
if (!mon->addWatch(dir, false)) {
|
MONDEB("rclMonRcvRun: adding watch for non dir topdir " << dir << "\n");
|
||||||
|
if (!mon->addWatch(dir, false, true)) {
|
||||||
LOGSYSERR("rclMonRcvRun", "addWatch", dir);
|
LOGSYSERR("rclMonRcvRun", "addWatch", dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,10 +355,10 @@ class RclFAM : public RclMonitor {
|
|||||||
public:
|
public:
|
||||||
RclFAM();
|
RclFAM();
|
||||||
virtual ~RclFAM();
|
virtual ~RclFAM();
|
||||||
virtual bool addWatch(const string& path, bool isdir);
|
virtual bool addWatch(const string& path, bool isdir, bool follow) override;
|
||||||
virtual bool getEvent(RclMonEvent& ev, int msecs = -1);
|
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) override;
|
||||||
bool ok() const {return m_ok;}
|
bool ok() override const {return m_ok;}
|
||||||
virtual bool generatesExist() const {return true;}
|
virtual bool generatesExist() override const {return true;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
@ -410,7 +416,7 @@ static void onalrm(int sig)
|
|||||||
{
|
{
|
||||||
longjmp(jbuf, 1);
|
longjmp(jbuf, 1);
|
||||||
}
|
}
|
||||||
bool RclFAM::addWatch(const string& path, bool isdir)
|
bool RclFAM::addWatch(const string& path, bool isdir, bool)
|
||||||
{
|
{
|
||||||
if (!ok())
|
if (!ok())
|
||||||
return false;
|
return false;
|
||||||
@ -579,9 +585,9 @@ public:
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool addWatch(const string& path, bool isdir);
|
virtual bool addWatch(const string& path, bool isdir, bool follow) override;
|
||||||
virtual bool getEvent(RclMonEvent& ev, int msecs = -1);
|
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) override;
|
||||||
bool ok() const {return m_ok;}
|
bool ok() const override {return m_ok;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
@ -630,11 +636,12 @@ const char *RclIntf::event_name(int code)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RclIntf::addWatch(const string& path, bool)
|
bool RclIntf::addWatch(const string& path, bool, bool follow)
|
||||||
{
|
{
|
||||||
if (!ok())
|
if (!ok()) {
|
||||||
return false;
|
return false;
|
||||||
MONDEB("RclIntf::addWatch: adding " << path << "\n");
|
}
|
||||||
|
MONDEB("RclIntf::addWatch: adding " << path << " follow " << follow << "\n");
|
||||||
// CLOSE_WRITE is covered through MODIFY. CREATE is needed for mkdirs
|
// CLOSE_WRITE is covered through MODIFY. CREATE is needed for mkdirs
|
||||||
uint32_t mask = IN_MODIFY | IN_CREATE
|
uint32_t mask = IN_MODIFY | IN_CREATE
|
||||||
| IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE
|
| IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE
|
||||||
@ -643,7 +650,7 @@ bool RclIntf::addWatch(const string& path, bool)
|
|||||||
// set, and now it is...
|
// set, and now it is...
|
||||||
| IN_ATTRIB
|
| IN_ATTRIB
|
||||||
#ifdef IN_DONT_FOLLOW
|
#ifdef IN_DONT_FOLLOW
|
||||||
| IN_DONT_FOLLOW
|
| (follow ? 0 : IN_DONT_FOLLOW)
|
||||||
#endif
|
#endif
|
||||||
#ifdef IN_EXCL_UNLINK
|
#ifdef IN_EXCL_UNLINK
|
||||||
| IN_EXCL_UNLINK
|
| IN_EXCL_UNLINK
|
||||||
@ -652,8 +659,7 @@ bool RclIntf::addWatch(const string& path, bool)
|
|||||||
int wd;
|
int wd;
|
||||||
if ((wd = inotify_add_watch(m_fd, path.c_str(), mask)) < 0) {
|
if ((wd = inotify_add_watch(m_fd, path.c_str(), mask)) < 0) {
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
LOGERR("RclIntf::addWatch: inotify_add_watch failed. errno " <<
|
LOGSYSERR("RclIntf::addWatch", "inotify_add_watch", path);
|
||||||
saved_errno << "\n");
|
|
||||||
if (errno == ENOSPC) {
|
if (errno == ENOSPC) {
|
||||||
LOGERR("RclIntf::addWatch: ENOSPC error may mean that you should "
|
LOGERR("RclIntf::addWatch: ENOSPC error may mean that you should "
|
||||||
"increase the inotify kernel constants. See inotify(7)\n");
|
"increase the inotify kernel constants. See inotify(7)\n");
|
||||||
@ -820,7 +826,7 @@ public:
|
|||||||
FileWatchListener *Listener{nullptr};
|
FileWatchListener *Listener{nullptr};
|
||||||
bool Recursive;
|
bool Recursive;
|
||||||
std::string DirName;
|
std::string DirName;
|
||||||
std::string OldFileName;
|
std::string OldFileName;
|
||||||
|
|
||||||
HANDLE DirHandle{nullptr};
|
HANDLE DirHandle{nullptr};
|
||||||
// do NOT make this bigger than 64K because it will fail if the folder being watched is on the
|
// do NOT make this bigger than 64K because it will fail if the folder being watched is on the
|
||||||
@ -871,12 +877,12 @@ class RclMonitorWin32 : public RclMonitor, public FileWatchListener {
|
|||||||
public:
|
public:
|
||||||
virtual ~RclMonitorWin32() {}
|
virtual ~RclMonitorWin32() {}
|
||||||
|
|
||||||
virtual bool addWatch(const string& path, bool /*isDir*/) override {
|
virtual bool addWatch(const string& path, bool /*isDir*/, bool /*follow*/) override {
|
||||||
MONDEB("RclMonitorWin32::addWatch: " << path << "\n");
|
MONDEB("RclMonitorWin32::addWatch: " << path << "\n");
|
||||||
return m_fswatcher.addWatch(path, this, true) != -1;
|
return m_fswatcher.addWatch(path, this, true) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) {
|
virtual bool getEvent(RclMonEvent& ev, int msecs = -1) override {
|
||||||
PRETEND_USE(msecs);
|
PRETEND_USE(msecs);
|
||||||
if (!m_events.empty()) {
|
if (!m_events.empty()) {
|
||||||
ev = m_events.front();
|
ev = m_events.front();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user