From 272a63104eb732ea358165eb23147abe4c3828c2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Thu, 12 Apr 2018 09:46:25 +0200 Subject: [PATCH] Add user interfaces for triggering an incremental in a running monitor --- src/Makefile.am | 2 ++ src/common/rclconfig.cpp | 1 - src/index/idxstatus.cpp | 39 +++++++++++++++++++++++++++ src/index/idxstatus.h | 56 +++++++++++++++++++++++++++++++++++++++ src/index/indexer.cpp | 1 + src/index/indexer.h | 34 +++--------------------- src/index/recollindex.cpp | 37 +++++++++++++++++++++----- src/qtgui/rclm_idx.cpp | 40 +++++++++++++++++++--------- src/qtgui/rclmain.ui | 11 ++++++++ src/qtgui/rclmain_w.cpp | 6 +++++ src/qtgui/rclmain_w.h | 3 +++ 11 files changed, 180 insertions(+), 50 deletions(-) create mode 100644 src/index/idxstatus.cpp create mode 100644 src/index/idxstatus.h diff --git a/src/Makefile.am b/src/Makefile.am index 53814620..78806241 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,6 +90,8 @@ index/fsfetcher.cpp \ index/fsfetcher.h \ index/fsindexer.cpp \ index/fsindexer.h \ +index/idxstatus.h \ +index/idxstatus.cpp \ index/mimetype.cpp \ index/mimetype.h \ index/rclmon.h \ diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index 0da0595b..b27115ef 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -1304,7 +1304,6 @@ string RclConfig::getConfdirPath(const char *varname, const char *dflt) const } } return path_canon(result); - } string RclConfig::getCacheDir() const diff --git a/src/index/idxstatus.cpp b/src/index/idxstatus.cpp new file mode 100644 index 00000000..cb5a3d75 --- /dev/null +++ b/src/index/idxstatus.cpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2017-2018 J.F.Dockes + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "idxstatus.h" + +#include "rclconfig.h" +#include "conftree.h" + +void readIdxStatus(RclConfig *config, DbIxStatus &status) +{ + ConfSimple cs(config->getIdxStatusFile().c_str(), 1); + string val; + cs.get("phase", val); + status.phase = DbIxStatus::Phase(atoi(val.c_str())); + cs.get("fn", status.fn); + cs.get("docsdone", &status.docsdone); + cs.get("filesdone", &status.filesdone); + cs.get("fileerrors", &status.fileerrors); + cs.get("dbtotdocs", &status.dbtotdocs); + cs.get("totfiles", &status.totfiles); + string shm("0"); + cs.get("hasmonitor", shm); + status.hasmonitor = stringToBool(shm); +} diff --git a/src/index/idxstatus.h b/src/index/idxstatus.h new file mode 100644 index 00000000..126b22ec --- /dev/null +++ b/src/index/idxstatus.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2017-2018 J.F.Dockes + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _IDXSTATUS_H_INCLUDED_ +#define _IDXSTATUS_H_INCLUDED_ + +#include + +// Current status of an indexing operation. This is updated in +// $RECOLL_CONFDIR/idxstatus.txt +class DbIxStatus { + public: + enum Phase {DBIXS_NONE, + DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING, + DBIXS_MONITOR, + DBIXS_DONE}; + Phase phase; + std::string fn; // Last file processed + int docsdone; // Documents actually updated + int filesdone; // Files tested (updated or not) + int fileerrors; // Failed files (e.g.: missing input handler). + int dbtotdocs; // Doc count in index at start + // Total files in index.This is actually difficult to compute from + // the index so it's preserved from last indexing + int totfiles; + // Is this indexer a monitoring one? This is a permanent value + // telling if option -m was set, not about what we are currently + // doing + bool hasmonitor{false}; + + void reset() { + phase = DBIXS_FILES; + fn.erase(); + docsdone = filesdone = fileerrors = dbtotdocs = totfiles = 0; + } + DbIxStatus() {reset();} +}; + +class RclConfig; +extern void readIdxStatus(RclConfig *config, DbIxStatus &status); + +#endif /* _IDXSTATUS_H_INCLUDED_ */ diff --git a/src/index/indexer.cpp b/src/index/indexer.cpp index 099bbc27..46191d70 100644 --- a/src/index/indexer.cpp +++ b/src/index/indexer.cpp @@ -31,6 +31,7 @@ #endif #include "mimehandler.h" #include "pathut.h" +#include "idxstatus.h" #ifdef RCL_USE_ASPELL #include "rclaspell.h" diff --git a/src/index/indexer.h b/src/index/indexer.h index 290474e4..dbddd1f2 100644 --- a/src/index/indexer.h +++ b/src/index/indexer.h @@ -24,41 +24,13 @@ #include #include -using std::string; -using std::list; -using std::map; -using std::vector; - #include "rcldb.h" #include "rcldoc.h" +#include "idxstatus.h" class FsIndexer; class BeagleQueueIndexer; -class DbIxStatus { - public: - enum Phase {DBIXS_NONE, - DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING, - DBIXS_MONITOR, - DBIXS_DONE}; - Phase phase; - string fn; // Last file processed - int docsdone; // Documents actually updated - int filesdone; // Files tested (updated or not) - int fileerrors; // Failed files (e.g.: missing input handler). - int dbtotdocs; // Doc count in index at start - // Total files in index.This is actually difficult to compute from - // the index so it's preserved from last indexing - int totfiles; - - void reset() { - phase = DBIXS_FILES; - fn.erase(); - docsdone = filesdone = fileerrors = dbtotdocs = totfiles = 0; - } - DbIxStatus() {reset();} -}; - /** Callback to say what we're doing. If the update func returns false, we * stop as soon as possible without corrupting state */ class DbIxStatusUpdater { @@ -130,14 +102,14 @@ class ConfIndexer { static vector getStemmerNames(); /** Index a list of files. No db cleaning or stemdb updating */ - bool indexFiles(list &files, int f = IxFNone); + bool indexFiles(std::list &files, int f = IxFNone); /** Update index for list of documents given as list of docs (out of query) */ bool updateDocs(vector &docs, IxFlag f = IxFNone); /** Purge a list of files. */ - bool purgeFiles(list &files, int f = IxFNone); + bool purgeFiles(std::list &files, int f = IxFNone); /** Set in place reset mode */ void setInPlaceReset() {m_db.setInPlaceReset();} diff --git a/src/index/recollindex.cpp b/src/index/recollindex.cpp index 8265f70b..7258274c 100644 --- a/src/index/recollindex.cpp +++ b/src/index/recollindex.cpp @@ -58,6 +58,7 @@ using namespace std; #endif #include "execmd.h" #include "checkretryfailed.h" +#include "idxstatus.h" // Command line options static int op_flags; @@ -141,6 +142,7 @@ class MyUpdater : public DbIxStatusUpdater { m_file.set("dbtotdocs", status.dbtotdocs); m_file.set("totfiles", status.totfiles); m_file.set("fn", status.fn); + m_file.set("hasmonitor", status.hasmonitor); m_file.holdWrites(false); } @@ -483,12 +485,32 @@ Usage(FILE *where = stderr) static RclConfig *config; -void lockorexit(Pidfile *pidfile) +static void lockorexit(Pidfile *pidfile, RclConfig *config) { pid_t pid; if ((pid = pidfile->open()) != 0) { - cerr << "Can't become exclusive indexer: " << pidfile->getreason() << - ". Return (other pid?): " << pid << endl; + if (pid > 0) { + cerr << "Can't become exclusive indexer: " << pidfile->getreason() + << ". Return (other pid?): " << pid << endl; +#ifndef _WIN32 + // Have a look at the status file. If the other process is + // a monitor we can tell it to start an incremental pass + // by touching the configuration file + DbIxStatus status; + readIdxStatus(config, status); + if (status.hasmonitor) { + string cmd("touch "); + string path = path_cat(config->getConfDir(), "recoll.conf"); + cmd += path; + system(cmd.c_str()); + cerr << "Monitoring indexer process was notified of " + "indexing request\n"; + } +#endif + } else { + cerr << "Can't become exclusive indexer: " << pidfile->getreason() + << endl; + } exit(1); } if (pidfile->write_pid() != 0) { @@ -688,7 +710,7 @@ int main(int argc, char **argv) flushIdxReasons(); exit(status ? 0 : 1); } else if (op_flags & (OPT_i|OPT_e)) { - lockorexit(&pidfile); + lockorexit(&pidfile, config); list filenames; @@ -746,7 +768,10 @@ int main(int argc, char **argv) } else if (op_flags & OPT_m) { if (argc != 0) Usage(); - lockorexit(&pidfile); + lockorexit(&pidfile, config); + if (updater) { + updater->status.hasmonitor = true; + } if (!(op_flags&OPT_D)) { LOGDEB("recollindex: daemonizing\n"); #ifndef _WIN32 @@ -826,7 +851,7 @@ int main(int argc, char **argv) cerr << "Not yet" << endl; return 1; } else { - lockorexit(&pidfile); + lockorexit(&pidfile, config); makeIndexerOrExit(config, inPlaceReset); bool status = confindexer->index(rezero, ConfIndexer::IxTAll, indexerFlags); diff --git a/src/qtgui/rclm_idx.cpp b/src/qtgui/rclm_idx.cpp index be186dda..77323990 100644 --- a/src/qtgui/rclm_idx.cpp +++ b/src/qtgui/rclm_idx.cpp @@ -30,24 +30,18 @@ #include "specialindex.h" #include "readfile.h" #include "snippets_w.h" +#include "idxstatus.h" using namespace std; + +// This is called from periodic100 if we started an indexer, or from +// the rclmain idxstatus file watcher, every time the file changes. void RclMain::updateIdxStatus() { - ConfSimple cs(theconfig->getIdxStatusFile().c_str(), 1); - QString msg = tr("Indexing in progress: "); DbIxStatus status; - string val; - cs.get("phase", val); - status.phase = DbIxStatus::Phase(atoi(val.c_str())); - cs.get("fn", status.fn); - cs.get("docsdone", &status.docsdone); - cs.get("filesdone", &status.filesdone); - cs.get("fileerrors", &status.fileerrors); - cs.get("dbtotdocs", &status.dbtotdocs); - cs.get("totfiles", &status.totfiles); - + readIdxStatus(theconfig, status); + QString msg = tr("Indexing in progress: "); QString phs; switch (status.phase) { case DbIxStatus::DBIXS_NONE:phs=tr("None");break; @@ -153,6 +147,7 @@ void RclMain::periodic100() } else { Pidfile pidfile(theconfig->getPidfile()); pid_t pid = pidfile.open(); + fileBumpIndexingAction->setEnabled(false); if (pid == getpid()) { // Locked by me m_indexerState = IXST_NOTRUNNING; @@ -172,6 +167,13 @@ void RclMain::periodic100() // Real time or externally started batch indexer running m_indexerState = IXST_RUNNINGNOTMINE; fileToggleIndexingAction->setText(tr("Stop &Indexing")); + DbIxStatus status; + readIdxStatus(theconfig, status); + if (status.hasmonitor) { + // Real-time indexer running. We can trigger an + // incremental pass + fileBumpIndexingAction->setEnabled(true); + } fileToggleIndexingAction->setEnabled(true); fileRebuildIndexAction->setEnabled(false); actionSpecial_Indexing->setEnabled(false); @@ -292,6 +294,20 @@ void RclMain::toggleIndexing() } } +#ifndef _WIN32 +void RclMain::bumpIndexing() +{ + DbIxStatus status; + readIdxStatus(theconfig, status); + if (status.hasmonitor) { + string cmd("touch "); + string path = path_cat(theconfig->getConfDir(), "recoll.conf"); + cmd += path; + system(cmd.c_str()); + } +} +#endif + static void delay(int millisecondsWait) { QEventLoop loop; diff --git a/src/qtgui/rclmain.ui b/src/qtgui/rclmain.ui index 71558876..90b4b0d3 100644 --- a/src/qtgui/rclmain.ui +++ b/src/qtgui/rclmain.ui @@ -170,6 +170,17 @@ fileToggleIndexingAction + + + Trigger incremental pass + + + fileBumpIndexingAction + + + false + + &Rebuild index diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 6b9d1ffc..ad542fb9 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -282,6 +282,7 @@ void RclMain::init() // sc = new QShortcut(quitKeySeq, restable); // connect(sc, SIGNAL (activated()), this, SLOT (fileExit())); + // A shortcut to get the focus back to the search entry. QKeySequence seq("Ctrl+Shift+s"); QShortcut *sc = new QShortcut(seq, this); @@ -306,6 +307,11 @@ void RclMain::init() this, SLOT(fileExit() ) ); connect(fileToggleIndexingAction, SIGNAL(triggered()), this, SLOT(toggleIndexing())); +#ifndef _WIN32 + fileMenu->insertAction(fileRebuildIndexAction, fileBumpIndexingAction); + connect(fileBumpIndexingAction, SIGNAL(triggered()), + this, SLOT(bumpIndexing())); +#endif connect(fileRebuildIndexAction, SIGNAL(triggered()), this, SLOT(rebuildIndex())); connect(fileEraseDocHistoryAction, SIGNAL(triggered()), diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 1eedfc0f..3b62d60b 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -123,6 +123,9 @@ public slots: virtual void fileExit(); virtual void periodic100(); virtual void toggleIndexing(); +#ifndef _WIN32 + virtual void bumpIndexing(); +#endif virtual void rebuildIndex(); virtual void specialIndex(); virtual void startSearch(std::shared_ptr sdata,