real time indexer: monitor the configuration for changes and reexecute when needed

This commit is contained in:
Jean-Francois Dockes 2012-03-06 09:35:21 +01:00
parent 7ce1a5f2e4
commit 2c6b023a88
8 changed files with 87 additions and 8 deletions

View File

@ -893,6 +893,21 @@ string RclConfig::getDbDir()
return path_canon(dbdir);
}
bool RclConfig::sourceChanged()
{
if (m_conf && m_conf->sourceChanged())
return true;
if (mimemap && mimemap->sourceChanged())
return true;
if (mimeconf && mimeconf->sourceChanged())
return true;
if (mimeview && mimeview->sourceChanged())
return true;
if (m_fields && m_fields->sourceChanged())
return true;
return false;
}
string RclConfig::getStopfile()
{
return path_cat(getConfDir(), "stoplist.txt");

View File

@ -88,6 +88,10 @@ class RclConfig {
* constructor it it is the default one (~/.recoll) and it did
* not exist yet. */
string getConfDir() {return m_confdir;}
/** Check if the config files were modified since we read them */
bool sourceChanged();
/** Returns true if this is ~/.recoll */
bool isDefaultConfig();
/** Get the local value for /usr/local/share/recoll/ */

View File

@ -65,7 +65,8 @@ class RclMonEvent {
int evflags() {return m_etyp & 0xf0;}
};
enum RclMonitorOption {RCLMON_NONE=0, RCLMON_NOFORK=1, RCLMON_NOX11=2};
enum RclMonitorOption {RCLMON_NONE=0, RCLMON_NOFORK=1, RCLMON_NOX11=2,
RCLMON_NOCONFCHECK=4};
/**
* Monitoring event queue. This is the shared object between the main thread

View File

@ -39,6 +39,7 @@
#include "debuglog.h"
#include "rclmon.h"
#include "debuglog.h"
#include "execmd.h"
#include "recollindex.h"
#include "pathut.h"
#include "x11mon.h"
@ -485,11 +486,11 @@ bool startMonitor(RclConfig *conf, int opts)
switch (ev.evtype()) {
case RclMonEvent::RCLEVT_MODIFY:
case RclMonEvent::RCLEVT_DIRCREATE:
LOGDEB(("Monitor: Modify/Check on %s\n", ev.m_path.c_str()));
LOGDEB0(("Monitor: Modify/Check on %s\n", ev.m_path.c_str()));
modified.push_back(ev.m_path);
break;
case RclMonEvent::RCLEVT_DELETE:
LOGDEB(("Monitor: Delete on %s\n", ev.m_path.c_str()));
LOGDEB0(("Monitor: Delete on %s\n", ev.m_path.c_str()));
// If this is for a directory (which the caller should
// tell us because he knows), we should purge the db
// of all the subtree, because on a directory rename,
@ -552,6 +553,11 @@ bool startMonitor(RclConfig *conf, int opts)
}
}
// Check for a config change
if (!(opts & RCLMON_NOCONFCHECK) && o_reexec && conf->sourceChanged()) {
LOGDEB(("Rclmonprc: config changed, reexecuting myself\n"));
o_reexec->reexec();
}
// Lock queue before waiting again
rclEQ.lock();
}

View File

@ -45,6 +45,7 @@ using namespace std;
#include "recollindex.h"
#include "fsindexer.h"
#include "rclionice.h"
#include "execmd.h"
// Command line options
static int op_flags;
@ -63,6 +64,9 @@ static int op_flags;
#define OPT_l 0x1000
#define OPT_b 0x2000
#define OPT_f 0x4000
#define OPT_C 0x8000
ReExec *o_reexec;
// Globals for atexit cleanup
static ConfIndexer *confindexer;
@ -224,9 +228,10 @@ static const char usage [] =
" Index everything according to configuration file\n"
" -z : reset database before starting indexing\n"
#ifdef RCL_MONITOR
"recollindex -m [-w <secs>] -x [-D]\n"
"recollindex -m [-w <secs>] -x [-D] [-C]\n"
" Perform real time indexing. Don't become a daemon if -D is set.\n"
" -w sets number of seconds to wait before starting.\n"
" -C disables monitoring config for changes/reexecuting.\n"
#ifndef DISABLE_X11MON
" -x disables exit on end of x11 session\n"
#endif /* DISABLE_X11MON */
@ -271,10 +276,12 @@ void lockorexit(Pidfile *pidfile)
}
}
int main(int argc, const char **argv)
int main(int argc, char **argv)
{
string a_config;
int sleepsecs = 60;
o_reexec = new ReExec;
o_reexec->init(argc, argv);
thisprog = argv[0];
argc--; argv++;
@ -290,6 +297,7 @@ int main(int argc, const char **argv)
a_config = *(++argv);
argc--; goto b1;
#ifdef RCL_MONITOR
case 'C': op_flags |= OPT_C; break;
case 'D': op_flags |= OPT_D; break;
#endif
case 'e': op_flags |= OPT_e; break;
@ -333,6 +341,8 @@ int main(int argc, const char **argv)
cerr << "Configuration problem: " << reason << endl;
exit(1);
}
o_reexec->atexit(cleanup);
bool rezero(op_flags & OPT_z);
Pidfile pidfile(config->getPidfile());
updater = new MyUpdater(config);
@ -433,6 +443,8 @@ int main(int argc, const char **argv)
int opts = RCLMON_NONE;
if (op_flags & OPT_D)
opts |= RCLMON_NOFORK;
if (op_flags & OPT_C)
opts |= RCLMON_NOCONFCHECK;
if (op_flags & OPT_x)
opts |= RCLMON_NOX11;
bool monret = startMonitor(config, opts);

View File

@ -25,4 +25,7 @@ extern bool createAuxDbs(RclConfig *config);
extern int stopindexing;
class ReExec;
extern ReExec *o_reexec;
#endif /* _recollindex_h_included_ */

View File

@ -23,6 +23,7 @@
#include <unistd.h> // for access(2)
#include <ctype.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <fstream>
#include <sstream>
@ -145,13 +146,13 @@ void ConfSimple::parseinput(istream &input)
ConfSimple::ConfSimple(int readonly, bool tildexp)
: dotildexpand(tildexp), m_holdWrites(false)
: dotildexpand(tildexp), m_fmtime(0), m_holdWrites(false)
{
status = readonly ? STATUS_RO : STATUS_RW;
}
ConfSimple::ConfSimple(const string& d, int readonly, bool tildexp)
: dotildexpand(tildexp), m_holdWrites(false)
: dotildexpand(tildexp), m_fmtime(0), m_holdWrites(false)
{
status = readonly ? STATUS_RO : STATUS_RW;
@ -160,7 +161,7 @@ ConfSimple::ConfSimple(const string& d, int readonly, bool tildexp)
}
ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp)
: dotildexpand(tildexp), m_filename(fname), m_holdWrites(false)
: dotildexpand(tildexp), m_filename(fname), m_fmtime(0), m_holdWrites(false)
{
status = readonly ? STATUS_RO : STATUS_RW;
@ -193,6 +194,7 @@ ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp)
}
parseinput(input);
i_changed(true);
}
ConfSimple::StatusCode ConfSimple::getStatus() const
@ -204,6 +206,26 @@ ConfSimple::StatusCode ConfSimple::getStatus() const
}
}
bool ConfSimple::sourceChanged()
{
return i_changed(false);
}
bool ConfSimple::i_changed(bool upd)
{
if (!m_filename.empty()) {
struct stat st;
if (stat(m_filename.c_str(), &st) == 0) {
if (m_fmtime != st.st_mtime) {
if (upd)
m_fmtime = st.st_mtime;
return true;
}
}
}
return false;
}
int ConfSimple::get(const string &nm, string &value, const string &sk) const
{
if (!ok())

View File

@ -107,6 +107,7 @@ public:
virtual list<string> getSubKeys() = 0;
virtual list<string> getSubKeys(bool) = 0;
virtual bool holdWrites(bool) = 0;
virtual bool sourceChanged() = 0;
};
/**
@ -140,6 +141,9 @@ public:
virtual ~ConfSimple() {};
/** Origin file changed. Only makes sense if we read the data from a file */
virtual bool sourceChanged();
/**
* Decide if we actually rewrite the backing-store after modifying the
* tree.
@ -252,6 +256,7 @@ protected:
private:
// Set if we're working with a file
string m_filename;
time_t m_fmtime;
// Configuration data submaps (one per subkey, the main data has a
// null subkey)
map<string, map<string, string> > m_submaps;
@ -267,6 +272,7 @@ private:
// Internal version of set: no RW checking
virtual int i_set(const string &nm, const string &val,
const string &sk, bool init = false);
bool i_changed(bool upd);
};
/**
@ -366,6 +372,16 @@ public:
return *this;
}
virtual bool sourceChanged()
{
typename list<T*>::const_iterator it;
for (it = m_confs.begin();it != m_confs.end();it++) {
if ((*it)->sourceChanged())
return true;
}
return false;
}
virtual int get(const string &name, string &value, const string &sk) const
{
typename list<T*>::const_iterator it;