real time indexer: monitor the configuration for changes and reexecute when needed
This commit is contained in:
parent
7ce1a5f2e4
commit
2c6b023a88
@ -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");
|
||||
|
||||
@ -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/ */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -25,4 +25,7 @@ extern bool createAuxDbs(RclConfig *config);
|
||||
|
||||
extern int stopindexing;
|
||||
|
||||
class ReExec;
|
||||
extern ReExec *o_reexec;
|
||||
|
||||
#endif /* _recollindex_h_included_ */
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user