diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index b6badb6b..0da0595b 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -585,18 +585,24 @@ pair RclConfig::getThrConf(ThrStage who) const return m_thrConf[who]; } -vector RclConfig::getTopdirs() const +vector RclConfig::getTopdirs(bool formonitor) const { vector tdl; - if (!getConfParam("topdirs", &tdl)) { - LOGERR("RclConfig::getTopdirs: no top directories in config or " - "bad list format\n"); + if (formonitor) { + if (!getConfParam("monitordirs", &tdl)) { + getConfParam("topdirs", &tdl); + } + } else { + getConfParam("topdirs", &tdl); + } + if (tdl.empty()) { + LOGERR("RclConfig::getTopdirs: nothing to index: topdirs/monitordirs " + " are not set or have a bad list format\n"); return tdl; } - for (vector::iterator it = tdl.begin(); it != tdl.end(); it++) { - *it = path_tildexpand(*it); - *it = path_canon(*it); + for (auto& dir : tdl) { + dir = path_canon(path_tildexpand(dir)); } return tdl; } diff --git a/src/common/rclconfig.h b/src/common/rclconfig.h index 249ce97f..d289f5cf 100644 --- a/src/common/rclconfig.h +++ b/src/common/rclconfig.h @@ -182,8 +182,11 @@ class RclConfig { /** Get list of top directories. This is needed from a number of places * and needs some cleaning-up code. An empty list is always an error, no - * need for other status */ - vector getTopdirs() const; + * need for other status + * @param formonitor if set retrieve the list for real time monitoring + * (if the monitor list does not exist we return the normal one). + */ + vector getTopdirs(bool formonitor = false) const; string getConfdirPath(const char *varname, const char *dflt) const; string getCachedirPath(const char *varname, const char *dflt) const; diff --git a/src/index/rclmonrcv.cpp b/src/index/rclmonrcv.cpp index ba8a302c..caebf5b6 100644 --- a/src/index/rclmonrcv.cpp +++ b/src/index/rclmonrcv.cpp @@ -161,8 +161,9 @@ void *rclMonRcvRun(void *q) return 0; } - // Get top directories from config - vector tdl = lconfig.getTopdirs(); + // Get top directories from config. Special monitor sublist if + // set, else full list. + vector tdl = lconfig.getTopdirs(true); if (tdl.empty()) { LOGERR("rclMonRcvRun:: top directory list (topdirs param.) not found " "in configuration or topdirs list parse error"); diff --git a/src/index/recollindex.cpp b/src/index/recollindex.cpp index 25f0dd1a..8265f70b 100644 --- a/src/index/recollindex.cpp +++ b/src/index/recollindex.cpp @@ -201,6 +201,18 @@ void rclIxIonice(const RclConfig *config) #endif } +static void setMyPriority(const RclConfig *config) +{ +#ifndef _WIN32 + if (setpriority(PRIO_PROCESS, 0, 20) != 0) { + LOGINFO("recollindex: can't setpriority(), errno " << errno << "\n"); + } + // Try to ionice. This does not work on all platforms + rclIxIonice(config); +#endif +} + + class MakeListWalkerCB : public FsTreeWalkerCB { public: MakeListWalkerCB(list& files, const vector& selpats) @@ -316,10 +328,33 @@ static bool checktopdirs(RclConfig *config, vector& nonexist) vector tdl; if (!config->getConfParam("topdirs", &tdl)) { cerr << "No 'topdirs' parameter in configuration\n"; - LOGERR("recollindex:No 'topdirs' parameter in configuration\n");; + LOGERR("recollindex:No 'topdirs' parameter in configuration\n"); return false; } + // If a restricted list for real-time monitoring exists check that + // all entries are descendants from a topdir + vector mondirs; + if (config->getConfParam("monitordirs", &mondirs)) { + for (const auto& sub : mondirs) { + bool found{false}; + for (const auto& top : tdl) { + if (path_isdesc(top, sub)) { + found = true; + break; + } + } + if (!found) { + string s("Real time monitoring directory entry " + sub + + " is not part of the topdirs tree\n"); + cerr << s; + LOGERR(s); + return false; + } + } + } + + for (vector::iterator it = tdl.begin(); it != tdl.end(); it++) { *it = path_tildexpand(*it); if (!it->size() || !path_isabsolute(*it)) { @@ -639,14 +674,8 @@ int main(int argc, char **argv) // Log something at LOGINFO to reset the trace file. Else at level // 3 it's not even truncated if all docs are up to date. LOGINFO("recollindex: starting up\n"); -#ifndef _WIN32 - if (setpriority(PRIO_PROCESS, 0, 20) != 0) { - LOGINFO("recollindex: can't setpriority(), errno " << errno << "\n"); - } - // Try to ionice. This does not work on all platforms - rclIxIonice(config); -#endif - + setMyPriority(config); + if (op_flags & OPT_r) { if (argc != 1) Usage(); @@ -732,15 +761,9 @@ int main(int argc, char **argv) } // Need to rewrite pid, it changed pidfile.write_pid(); -#ifndef _WIN32 // Not too sure if I have to redo the nice thing after daemon(), // can't hurt anyway (easier than testing on all platforms...) - if (setpriority(PRIO_PROCESS, 0, 20) != 0) { - LOGINFO("recollindex: can't setpriority(), errno " << errno<< "\n"); - } - // Try to ionice. This does not work on all platforms - rclIxIonice(config); -#endif + setMyPriority(config); if (sleepsecs > 0) { LOGDEB("recollindex: sleeping " << sleepsecs << "\n"); @@ -753,6 +776,7 @@ int main(int argc, char **argv) } } } + if (!(op_flags & OPT_n)) { makeIndexerOrExit(config, inPlaceReset); LOGDEB("Recollindex: initial indexing pass before monitoring\n"); @@ -776,10 +800,11 @@ int main(int argc, char **argv) // Note that -n will be inside the reexec when we come // back, but the monitor will explicitely strip it before // starting a config change exec to ensure that we do a - // purging pass in this case. + // purging pass in this latter case (full restart). o_reexec->reexec(); #endif } + if (updater) { updater->status.phase = DbIxStatus::DBIXS_MONITOR; updater->status.fn.clear(); diff --git a/src/utils/pathut.cpp b/src/utils/pathut.cpp index d6c01eba..6c12920c 100644 --- a/src/utils/pathut.cpp +++ b/src/utils/pathut.cpp @@ -353,6 +353,29 @@ bool path_isroot(const string& path) return false; } +bool path_isdesc(const string& _top, const string& _sub) +{ + string top = path_canon(_top); + string sub = path_canon(_sub); + path_catslash(top); + path_catslash(sub); + for (;;) { + if (sub == top) { + return true; + } + string::size_type l = sub.size(); + sub = path_getfather(sub); + if (sub.size() == l || sub.size() < top.size()) { + // At root or sub shorter than top: done + if (sub == top) { + return true; + } else { + return false; + } + } + } +} + bool path_isabsolute(const string& path) { if (!path.empty() && (path[0] == '/' diff --git a/src/utils/pathut.h b/src/utils/pathut.h index 14991f4a..d3586589 100644 --- a/src/utils/pathut.h +++ b/src/utils/pathut.h @@ -113,6 +113,10 @@ extern bool path_isabsolute(const std::string& s); /// Test if path is root (x:/). root is defined by root/.. == root extern bool path_isroot(const std::string& p); +/// Test if sub is a subdirectory of top. This is a textual test, +/// links not allowed +extern bool path_isdesc(const std::string& top, const std::string& sub); + /// Turn absolute path into file:// url extern std::string path_pathtofileurl(const std::string& path);