windows powerfail signal: stop indexing only on resume and topdirs change

This commit is contained in:
Jean-Francois Dockes 2019-03-19 14:38:57 +01:00
parent d2b8eb6d80
commit 4d7d1a7965
6 changed files with 80 additions and 39 deletions

View File

@ -168,12 +168,14 @@ LRESULT CALLBACK MainWndProc(HWND hwnd , UINT msg , WPARAM wParam,
case WM_POWERBROADCAST: case WM_POWERBROADCAST:
{ {
LOGDEB("MainWndProc: got powerbroadcast message\n"); LOGDEB("MainWndProc: got powerbroadcast message\n");
// We always try to end an indexing operation, independantly // This gets specific processing because we want to check the
// of the kind of event. Mounted volumes may have changed // state of topdirs on resuming indexing (in case a mounted
// etc. Using SIGTERM just to have something different from // volume went away).
// the other messages
if (l_sigcleanup) { if (l_sigcleanup) {
l_sigcleanup(SIGTERM); if (wParam == PBT_APMRESUMEAUTOMATIC ||
wParam == PBT_APMRESUMESUSPEND) {
l_sigcleanup(RCLSIG_RESUME);
}
} }
} }
break; break;

View File

@ -41,6 +41,14 @@ class RclConfig;
*/ */
enum RclInitFlags {RCLINIT_NONE = 0, RCLINIT_DAEMON = 1, RCLINIT_IDX = 2, enum RclInitFlags {RCLINIT_NONE = 0, RCLINIT_DAEMON = 1, RCLINIT_IDX = 2,
RCLINIT_PYTHON = 4}; RCLINIT_PYTHON = 4};
// Kinds of termination requests, in addition to the normal signal
// values. Passed as type int to sigcleanup() when it is not invoked
// directly as a sig handler. Note that because of the existence of
// sigset_t, we are pretty sure that no signals can have a high value
enum RclSigKind {
// System resume from sleep
RCLSIG_RESUME = 1002};
extern RclConfig *recollinit(int flags, extern RclConfig *recollinit(int flags,
void (*cleanup)(void), void (*sigcleanup)(int), void (*cleanup)(void), void (*sigcleanup)(int),
std::string& reason, const std::string *argcnf = 0); std::string& reason, const std::string *argcnf = 0);

View File

@ -172,21 +172,6 @@ bool FsIndexer::init()
return true; return true;
} }
// Check if path is either non-existing or an empty directory.
static bool path_empty(const string& path)
{
if (path_isdir(path)) {
string reason;
std::set<string> entries;
if (!readdir(path, reason, entries) || entries.empty()) {
return true;
}
return false;
} else {
return !path_exists(path);
}
}
// Recursively index each directory in the topdirs: // Recursively index each directory in the topdirs:
bool FsIndexer::index(int flags) bool FsIndexer::index(int flags)
{ {

View File

@ -174,12 +174,43 @@ private:
}; };
static MyUpdater *updater; static MyUpdater *updater;
// This holds the state of topdirs (exist+nonempty) on indexing
// startup. If it changes after a resume from sleep we interrupt the
// indexing (the assumption being that a volume has been mounted or
// unmounted while we slept). This is not foolproof as the user can
// always pull out a removable volume while we work. It just avoids a
// harmful purge in a common case.
static vector<string> o_topdirs;
static vector<bool> o_topdirs_emptiness;
bool topdirs_state(vector<bool> tdlstate)
{
tdlstate.clear();
for (const auto& dir : o_topdirs) {
tdlstate.push_back(path_empty(dir));
}
}
static void sigcleanup(int sig) static void sigcleanup(int sig)
{ {
cerr << "Recollindex: got signal " << sig << ", registering stop request\n"; if (sig == RCLSIG_RESUME) {
LOGDEB("Got signal " << sig << ", registering stop request\n"); vector<bool> emptiness;
CancelCheck::instance().setCancel(); topdirs_state(emptiness);
stopindexing = 1; if (emptiness != o_topdirs_emptiness) {
string msg = "Recollindex: resume: topdirs state changed while "
"we were sleeping\n";
cerr << msg;
LOGDEB(msg);
CancelCheck::instance().setCancel();
stopindexing = 1;
}
} else {
cerr << "Recollindex: got signal " << sig <<
", registering stop request\n";
LOGDEB("Got signal " << sig << ", registering stop request\n");
CancelCheck::instance().setCancel();
stopindexing = 1;
}
} }
static void makeIndexerOrExit(RclConfig *config, bool inPlaceReset) static void makeIndexerOrExit(RclConfig *config, bool inPlaceReset)
@ -330,8 +361,7 @@ static bool createstemdb(RclConfig *config, const string &lang)
// match existing files or directories. Warn if they don't // match existing files or directories. Warn if they don't
static bool checktopdirs(RclConfig *config, vector<string>& nonexist) static bool checktopdirs(RclConfig *config, vector<string>& nonexist)
{ {
vector<string> tdl; if (!config->getConfParam("topdirs", &o_topdirs)) {
if (!config->getConfParam("topdirs", &tdl)) {
cerr << "No 'topdirs' parameter in configuration\n"; 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; return false;
@ -343,7 +373,7 @@ static bool checktopdirs(RclConfig *config, vector<string>& nonexist)
if (config->getConfParam("monitordirs", &mondirs)) { if (config->getConfParam("monitordirs", &mondirs)) {
for (const auto& sub : mondirs) { for (const auto& sub : mondirs) {
bool found{false}; bool found{false};
for (const auto& top : tdl) { for (const auto& top : o_topdirs) {
if (path_isdesc(top, sub)) { if (path_isdesc(top, sub)) {
found = true; found = true;
break; break;
@ -358,24 +388,24 @@ static bool checktopdirs(RclConfig *config, vector<string>& nonexist)
} }
} }
} }
for (vector<string>::iterator it = tdl.begin(); it != tdl.end(); it++) { for (auto& dir : o_topdirs) {
*it = path_tildexpand(*it); dir = path_tildexpand(dir);
if (!it->size() || !path_isabsolute(*it)) { if (!dir.size() || !path_isabsolute(dir)) {
if ((*it)[0] == '~') { if (dir[0] == '~') {
cerr << "Tilde expansion failed: " << *it << endl; cerr << "Tilde expansion failed: " << dir << endl;
LOGERR("recollindex: tilde expansion failed: " << *it << "\n"); LOGERR("recollindex: tilde expansion failed: " << dir << "\n");
} else { } else {
cerr << "Not an absolute path: " << *it << endl; cerr << "Not an absolute path: " << dir << endl;
LOGERR("recollindex: not an absolute path: " << *it << "\n"); LOGERR("recollindex: not an absolute path: " << dir << "\n");
} }
return false; return false;
} }
if (!path_exists(*it)) { if (!path_exists(dir)) {
nonexist.push_back(*it); nonexist.push_back(dir);
} }
} }
topdirs_state(o_topdirs_emptiness);
// We'd like to check skippedPaths too, but these are wildcard // We'd like to check skippedPaths too, but these are wildcard
// exprs, so reasonably can't // exprs, so reasonably can't
@ -895,4 +925,3 @@ int main(int argc, char **argv)
return !status; return !status;
} }
} }

View File

@ -132,6 +132,21 @@ string path_wingettempfilename(TCHAR *pref)
#endif // _WIN32 #endif // _WIN32
// Check if path is either non-existing or an empty directory.
bool path_empty(const string& path)
{
if (path_isdir(path)) {
string reason;
std::set<string> entries;
if (!readdir(path, reason, entries) || entries.empty()) {
return true;
}
return false;
} else {
return !path_exists(path);
}
}
string path_defaultrecollconfsubdir() string path_defaultrecollconfsubdir()
{ {
#ifdef _WIN32 #ifdef _WIN32

View File

@ -30,6 +30,8 @@ extern void rclutil_init_mt();
/// Sub-directory for default recoll config (e.g: .recoll) /// Sub-directory for default recoll config (e.g: .recoll)
extern std::string path_defaultrecollconfsubdir(); extern std::string path_defaultrecollconfsubdir();
// Check if path is either non-existing or an empty directory.
extern bool path_empty(const std::string& path);
/// e.g. /usr/share/recoll. Depends on OS and config /// e.g. /usr/share/recoll. Depends on OS and config
extern const std::string& path_pkgdatadir(); extern const std::string& path_pkgdatadir();