From ff9a4a2a9225ffdab280eb22cb7548ff22d48e71 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Fri, 25 May 2012 18:51:52 +0200 Subject: [PATCH] indexing daemon: reexecute after the initial indexing pass to get rid of memory if it was heavy --- src/index/rclmonprc.cpp | 4 +++ src/index/recollindex.cpp | 30 ++++++++++++++++++---- src/utils/execmd.cpp | 53 +++++++++++++++++++++++++++++++++++++++ src/utils/execmd.h | 6 +++++ 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/index/rclmonprc.cpp b/src/index/rclmonprc.cpp index 243b98e3..88545f85 100644 --- a/src/index/rclmonprc.cpp +++ b/src/index/rclmonprc.cpp @@ -559,6 +559,10 @@ 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")); + // We never want to have a -n option after a config + // change. -n was added by the reexec after the initial + // pass even if it was not given on the command line + o_reexec->removeArg("-n"); o_reexec->reexec(); } // Lock queue before waiting again diff --git a/src/index/recollindex.cpp b/src/index/recollindex.cpp index b8480979..4a5eab9d 100644 --- a/src/index/recollindex.cpp +++ b/src/index/recollindex.cpp @@ -66,6 +66,7 @@ static int op_flags; #define OPT_f 0x4000 #define OPT_C 0x8000 #define OPT_Z 0x10000 +#define OPT_n 0x20000 ReExec *o_reexec; @@ -233,6 +234,7 @@ static const char usage [] = " 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" +" -n disables initial incremental indexing (!and purge!).\n" #ifndef DISABLE_X11MON " -x disables exit on end of x11 session\n" #endif /* DISABLE_X11MON */ @@ -288,6 +290,10 @@ int main(int argc, char **argv) { string a_config; int sleepsecs = 60; + + // The reexec struct is used by the daemon to shed memory after + // the initial indexing pass and to restart when the configuration + // changes o_reexec = new ReExec; o_reexec->init(argc, argv); @@ -314,6 +320,7 @@ int main(int argc, char **argv) case 'i': op_flags |= OPT_i; break; case 'l': op_flags |= OPT_l; break; case 'm': op_flags |= OPT_m; break; + case 'n': op_flags |= OPT_n; break; case 's': op_flags |= OPT_s; break; #ifdef RCL_USE_ASPELL case 'S': op_flags |= OPT_S; break; @@ -446,17 +453,30 @@ int main(int argc, char **argv) } } } - makeIndexerOrExit(config, inPlaceReset); - if (!confindexer->index(rezero, ConfIndexer::IxTAll) || stopindexing) { - LOGERR(("recollindex, initial indexing pass failed, not going into monitor mode\n")); - exit(1); + if (!(op_flags & OPT_n)) { + makeIndexerOrExit(config, inPlaceReset); + LOGDEB(("Recollindex: initial indexing pass before monitoring\n")); + if (!confindexer->index(rezero, ConfIndexer::IxTAll) || + stopindexing) { + LOGERR(("recollindex, initial indexing pass failed, " + "not going into monitor mode\n")); + exit(1); + } + deleteZ(confindexer); + o_reexec->insertArgs(vector(1, "-n")); + LOGDEB(("recollindex: calling reexec after init path with " + "option -n\n")); + // Note that -n will be inside the reexec when we come + // back, but the monitor will explicitely strip it before + // starting a config change exec to ensure that we do a + // purging pass in this case. + o_reexec.reexec(); } if (updater) { updater->status.phase = DbIxStatus::DBIXS_MONITOR; updater->status.fn.clear(); updater->update(); } - deleteZ(confindexer); int opts = RCLMON_NONE; if (op_flags & OPT_D) opts |= RCLMON_NOFORK; diff --git a/src/utils/execmd.cpp b/src/utils/execmd.cpp index 9885fcda..da2f2511 100644 --- a/src/utils/execmd.cpp +++ b/src/utils/execmd.cpp @@ -623,6 +623,48 @@ void ReExec::init(int argc, char *args[]) free(cd); } +void ReExec::insertArgs(const vector& args, int idx) +{ + vector::iterator it, cit; + unsigned int cmpoffset = (unsigned int)-1; + + if (idx == -1 || string::size_type(idx) >= m_argv.size()) { + it = m_argv.end(); + if (m_argv.size() >= args.size()) { + cmpoffset = m_argv.size() - args.size(); + } + } else { + it = m_argv.begin() + idx; + if (idx + args.size() <= m_argv.size()) { + cmpoffset = idx; + } + } + + // Check that the option is not already there + if (cmpoffset != (unsigned int)-1) { + bool allsame = true; + for (unsigned int i = 0; i < args.size(); i++) { + if (m_argv[cmpoffset + i] != args[i]) { + allsame = false; + break; + } + } + if (allsame) + return; + } + + m_argv.insert(it, args.begin(), args.end()); +} + +void ReExec::removeArg(const string& arg) +{ + for (vector::iterator it = m_argv.begin(); + it != m_argv.end(); it++) { + if (*it == arg) + it = m_argv.erase(it); + } +} + // Reexecute myself, as close as possible to the initial exec void ReExec::reexec() { @@ -758,6 +800,17 @@ ReExec reexec; int main(int argc, char *argv[]) { reexec.init(argc, argv); + + if (0) { + vector newargs; + newargs.push_back("newarg"); + newargs.push_back("newarg1"); + newargs.push_back("newarg2"); + newargs.push_back("newarg3"); + newargs.push_back("newarg4"); + reexec.insertArgs(newargs, 2); + } + thisprog = argv[0]; argc--; argv++; diff --git a/src/utils/execmd.h b/src/utils/execmd.h index 6694d320..cc61b49b 100644 --- a/src/utils/execmd.h +++ b/src/utils/execmd.h @@ -245,6 +245,12 @@ public: } void reexec(); const string& getreason() {return m_reason;} + // Insert new args into the initial argv. idx designates the place + // before which the new args are inserted (the default of 1 + // inserts after argv[0] which would probably be an appropriate + // place for additional options) + void insertArgs(const vector& args, int idx = 1); + void removeArg(const string& arg); private: vector m_argv; string m_curdir;