diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index fc0dda6a..6b947bed 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -883,6 +883,10 @@ string RclConfig::getPidfile() { return path_cat(getConfDir(), "index.pid"); } +string RclConfig::getIdxStatusFile() +{ + return path_cat(getConfDir(), "idxstatus.txt"); +} list& RclConfig::getSkippedNames() { diff --git a/src/common/rclconfig.h b/src/common/rclconfig.h index aa8d3196..86b2637f 100644 --- a/src/common/rclconfig.h +++ b/src/common/rclconfig.h @@ -141,8 +141,10 @@ class RclConfig { string getDbDir(); /** Get stoplist file name */ string getStopfile(); - /** Get indexing pid file */ + /** Get indexing pid file name */ string getPidfile(); + /** Get indexing status file name */ + string getIdxStatusFile(); /** Get list of skipped file names for current keydir */ list& getSkippedNames(); diff --git a/src/index/indexer.cpp b/src/index/indexer.cpp index 0debdbb2..0b072c9c 100644 --- a/src/index/indexer.cpp +++ b/src/index/indexer.cpp @@ -102,6 +102,8 @@ bool ConfIndexer::index(bool resetbefore, ixType typestorun) return false; createAspellDict(); clearMimeHandlerCache(); + if (m_updater) + m_updater->update(DbIxStatus::DBIXS_DONE, string()); return true; } diff --git a/src/index/indexer.h b/src/index/indexer.h index 454087e8..deee8877 100644 --- a/src/index/indexer.h +++ b/src/index/indexer.h @@ -36,7 +36,9 @@ class BeagleQueueIndexer; class DbIxStatus { public: - enum Phase {DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING}; + enum Phase {DBIXS_NONE, + DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING, + DBIXS_DONE}; Phase phase; string fn; // Last file processed int docsdone; // Documents processed @@ -51,13 +53,17 @@ class DbIxStatusUpdater { public: DbIxStatus status; virtual ~DbIxStatusUpdater(){} - virtual bool update() = 0; + + // Convenience: change phase/fn and update virtual bool update(DbIxStatus::Phase phase, const string& fn) { status.phase = phase; status.fn = fn; return update(); } + + // To be implemented by user for sending info somewhere + virtual bool update() = 0; }; /** diff --git a/src/index/recollindex.cpp b/src/index/recollindex.cpp index fa51e4e0..c5dd5757 100644 --- a/src/index/recollindex.cpp +++ b/src/index/recollindex.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -76,29 +77,62 @@ static void cleanup() // indexing routines. int stopindexing; -// Mainly used to request indexing stop, we currently do not use the -// current file name +// Receive status updates from the ongoing indexing operation +// Also check for an interrupt request and return the info to caller which +// should subsequently orderly terminate what it is doing. class MyUpdater : public DbIxStatusUpdater { public: - virtual bool update() { + MyUpdater(RclConfig *config) + : m_prevphase(DbIxStatus::DBIXS_NONE) + { + m_fd = open(config->getIdxStatusFile().c_str(), + O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (m_fd < 0) + LOGERR(("Can't open/create status file: [%s]\n", + config->getIdxStatusFile().c_str())); + } + + virtual bool update() + { + // Update the status file. Avoid doing it too often + if (status.phase != m_prevphase || m_chron.millis() > 300) { + m_prevphase = status.phase; + m_chron.restart(); + lseek(m_fd, 0, 0); + int fd1 = dup(m_fd); + FILE *fp = fdopen(fd1, "w"); + fprintf(fp, "phase = %d\n", int(status.phase)); + fprintf(fp, "docsdone = %d\n", status.docsdone); + fprintf(fp, "dbtotdocs = %d\n", status.dbtotdocs); + fprintf(fp, "fn = %s\n", status.fn.c_str()); + ftruncate(m_fd, off_t(ftell(fp))); + // Flush data and closes fd1. m_fd still valid + fclose(fp); + } + if (stopindexing) { return false; } - // If we are in the monitor, we also need to check x status + // If we are in the monitor, we also need to check X11 status // during the initial indexing pass (else the user could log // out and the indexing would go on, not good (ie: if the user // logs in again, the new recollindex will fail). if ((op_flags & OPT_m) && !(op_flags & OPT_x) && !x11IsAlive()) { - LOGDEB(("X11 session went away during initial indexing pass\n")); - stopindexing = true; - return false; + LOGDEB(("X11 session went away during initial indexing pass\n")); + stopindexing = true; + return false; } return true; } + +private: + int m_fd; + Chrono m_chron; + DbIxStatus::Phase m_prevphase; }; -static MyUpdater updater; +static MyUpdater *updater; static void sigcleanup(int sig) { @@ -111,7 +145,7 @@ static void sigcleanup(int sig) static bool makeIndexer(RclConfig *config) { if (!confindexer) - confindexer = new ConfIndexer(config, &updater); + confindexer = new ConfIndexer(config, updater); if (!confindexer) { cerr << "Cannot create indexer" << endl; exit(1); @@ -300,6 +334,7 @@ int main(int argc, const char **argv) } bool rezero(op_flags & OPT_z); Pidfile pidfile(config->getPidfile()); + updater = new MyUpdater(config); if (setpriority(PRIO_PROCESS, 0, 20) != 0) { LOGINFO(("recollindex: can't setpriority(), errno %d\n", errno)); @@ -383,8 +418,7 @@ int main(int argc, const char **argv) } } } - - confindexer = new ConfIndexer(config, &updater); + confindexer = new ConfIndexer(config, updater); if (!confindexer->index(rezero, ConfIndexer::IxTAll) || stopindexing) { LOGERR(("recollindex, initial indexing pass failed, not going into monitor mode\n")); exit(1); @@ -412,13 +446,18 @@ int main(int argc, const char **argv) } else { lockorexit(&pidfile); pidfile.write_pid(); - confindexer = new ConfIndexer(config, &updater); + confindexer = new ConfIndexer(config, updater); bool status = confindexer->index(rezero, ConfIndexer::IxTAll); if (!status) cerr << "Indexing failed" << endl; if (!confindexer->getReason().empty()) cerr << confindexer->getReason() << endl; + + if (updater) { + updater->status.phase = DbIxStatus::DBIXS_DONE; + updater->status.fn.clear(); + updater->update(); + } return !status; } } -