Get rid of the GUI indexing thread. All indexing now done by recollindex, with start/stop from the GUI
This commit is contained in:
parent
f59e2e033a
commit
fccc0ac09c
@ -349,6 +349,7 @@ FsIndexer::processone(const std::string &fn, const struct stat *stp,
|
|||||||
if (m_updater) {
|
if (m_updater) {
|
||||||
// Status bar update, abort request etc.
|
// Status bar update, abort request etc.
|
||||||
m_updater->status.fn = fn;
|
m_updater->status.fn = fn;
|
||||||
|
++(m_updater->status.filesdone);
|
||||||
if (!m_updater->update()) {
|
if (!m_updater->update()) {
|
||||||
return FsTreeWalker::FtwStop;
|
return FsTreeWalker::FtwStop;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,7 +107,7 @@ bool ConfIndexer::index(bool resetbefore, ixType typestorun)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfIndexer::indexFiles(std::list<string>& ifiles, IxFlag flag)
|
bool ConfIndexer::indexFiles(list<string>& ifiles, IxFlag flag)
|
||||||
{
|
{
|
||||||
list<string> myfiles;
|
list<string> myfiles;
|
||||||
for (list<string>::const_iterator it = ifiles.begin();
|
for (list<string>::const_iterator it = ifiles.begin();
|
||||||
@ -151,11 +151,8 @@ bool ConfIndexer::indexFiles(std::list<string>& ifiles, IxFlag flag)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update index for specific documents. The docs come from an index
|
bool ConfIndexer::docsToPaths(vector<Rcl::Doc> &docs, vector<string> &paths)
|
||||||
// query, so the udi, backend etc. fields are filled.
|
|
||||||
bool ConfIndexer::updateDocs(std::vector<Rcl::Doc> &docs, IxFlag flag)
|
|
||||||
{
|
{
|
||||||
list<string> files;
|
|
||||||
for (vector<Rcl::Doc>::iterator it = docs.begin(); it != docs.end(); it++) {
|
for (vector<Rcl::Doc>::iterator it = docs.begin(); it != docs.end(); it++) {
|
||||||
Rcl::Doc &idoc = *it;
|
Rcl::Doc &idoc = *it;
|
||||||
string backend;
|
string backend;
|
||||||
@ -168,15 +165,24 @@ bool ConfIndexer::updateDocs(std::vector<Rcl::Doc> &docs, IxFlag flag)
|
|||||||
if (!backend.empty() && backend.compare("FS"))
|
if (!backend.empty() && backend.compare("FS"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Filesystem document. Intern from file.
|
// Filesystem document. The url has to be like file://
|
||||||
// The url has to be like file://
|
|
||||||
if (idoc.url.find(cstr_fileu) != 0) {
|
if (idoc.url.find(cstr_fileu) != 0) {
|
||||||
LOGERR(("idx::updateDocs: FS backend and non fs url: [%s]\n",
|
LOGERR(("idx::docsToPaths: FS backend and non fs url: [%s]\n",
|
||||||
idoc.url.c_str()));
|
idoc.url.c_str()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
files.push_back(idoc.url.substr(7, string::npos));
|
paths.push_back(idoc.url.substr(7, string::npos));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update index for specific documents. The docs come from an index
|
||||||
|
// query, so the udi, backend etc. fields are filled.
|
||||||
|
bool ConfIndexer::updateDocs(std::vector<Rcl::Doc> &docs, IxFlag flag)
|
||||||
|
{
|
||||||
|
vector<string> paths;
|
||||||
|
docsToPaths(docs, paths);
|
||||||
|
list<string> files(paths.begin(), paths.end());
|
||||||
if (!files.empty()) {
|
if (!files.empty()) {
|
||||||
return indexFiles(files, flag);
|
return indexFiles(files, flag);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,11 +20,13 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifndef NO_NAMESPACES
|
#ifndef NO_NAMESPACES
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::list;
|
using std::list;
|
||||||
using std::map;
|
using std::map;
|
||||||
|
using std::vector;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
@ -38,12 +40,19 @@ class DbIxStatus {
|
|||||||
public:
|
public:
|
||||||
enum Phase {DBIXS_NONE,
|
enum Phase {DBIXS_NONE,
|
||||||
DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING,
|
DBIXS_FILES, DBIXS_PURGE, DBIXS_STEMDB, DBIXS_CLOSING,
|
||||||
|
DBIXS_MONITOR,
|
||||||
DBIXS_DONE};
|
DBIXS_DONE};
|
||||||
Phase phase;
|
Phase phase;
|
||||||
string fn; // Last file processed
|
string fn; // Last file processed
|
||||||
int docsdone; // Documents processed
|
int docsdone; // Documents actually updated
|
||||||
|
int filesdone; // Files tested (updated or not)
|
||||||
int dbtotdocs; // Doc count in index at start
|
int dbtotdocs; // Doc count in index at start
|
||||||
void reset() {phase = DBIXS_FILES;fn.erase();docsdone=dbtotdocs=0;}
|
void reset()
|
||||||
|
{
|
||||||
|
phase = DBIXS_FILES;
|
||||||
|
fn.erase();
|
||||||
|
docsdone = filesdone = dbtotdocs = 0;
|
||||||
|
}
|
||||||
DbIxStatus() {reset();}
|
DbIxStatus() {reset();}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,14 +110,14 @@ class ConfIndexer {
|
|||||||
static list<string> getStemmerNames();
|
static list<string> getStemmerNames();
|
||||||
|
|
||||||
/** Index a list of files. No db cleaning or stemdb updating */
|
/** Index a list of files. No db cleaning or stemdb updating */
|
||||||
bool indexFiles(std::list<string> &files, IxFlag f = IxFNone);
|
bool indexFiles(list<string> &files, IxFlag f = IxFNone);
|
||||||
|
|
||||||
/** Update index for list of documents given as list of docs (out of query)
|
/** Update index for list of documents given as list of docs (out of query)
|
||||||
*/
|
*/
|
||||||
bool updateDocs(std::vector<Rcl::Doc> &docs, IxFlag f = IxFNone);
|
bool updateDocs(vector<Rcl::Doc> &docs, IxFlag f = IxFNone);
|
||||||
|
static bool docsToPaths(vector<Rcl::Doc> &docs, vector<string> &paths);
|
||||||
/** Purge a list of files. */
|
/** Purge a list of files. */
|
||||||
bool purgeFiles(std::list<string> &files);
|
bool purgeFiles(list<string> &files);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RclConfig *m_config;
|
RclConfig *m_config;
|
||||||
|
|||||||
@ -103,6 +103,7 @@ class MyUpdater : public DbIxStatusUpdater {
|
|||||||
FILE *fp = fdopen(fd1, "w");
|
FILE *fp = fdopen(fd1, "w");
|
||||||
fprintf(fp, "phase = %d\n", int(status.phase));
|
fprintf(fp, "phase = %d\n", int(status.phase));
|
||||||
fprintf(fp, "docsdone = %d\n", status.docsdone);
|
fprintf(fp, "docsdone = %d\n", status.docsdone);
|
||||||
|
fprintf(fp, "filesdone = %d\n", status.filesdone);
|
||||||
fprintf(fp, "dbtotdocs = %d\n", status.dbtotdocs);
|
fprintf(fp, "dbtotdocs = %d\n", status.dbtotdocs);
|
||||||
fprintf(fp, "fn = %s\n", status.fn.c_str());
|
fprintf(fp, "fn = %s\n", status.fn.c_str());
|
||||||
ftruncate(m_fd, off_t(ftell(fp)));
|
ftruncate(m_fd, off_t(ftell(fp)));
|
||||||
@ -423,6 +424,11 @@ int main(int argc, const char **argv)
|
|||||||
LOGERR(("recollindex, initial indexing pass failed, not going into monitor mode\n"));
|
LOGERR(("recollindex, initial indexing pass failed, not going into monitor mode\n"));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (updater) {
|
||||||
|
updater->status.phase = DbIxStatus::DBIXS_MONITOR;
|
||||||
|
updater->status.fn.clear();
|
||||||
|
updater->update();
|
||||||
|
}
|
||||||
deleteZ(confindexer);
|
deleteZ(confindexer);
|
||||||
int opts = RCLMON_NONE;
|
int opts = RCLMON_NONE;
|
||||||
if (op_flags & OPT_D)
|
if (op_flags & OPT_D)
|
||||||
|
|||||||
@ -33,7 +33,6 @@ using std::list;
|
|||||||
|
|
||||||
#include "confgui.h"
|
#include "confgui.h"
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
#include "idxthread.h"
|
|
||||||
#include "confguiindex.h"
|
#include "confguiindex.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
@ -85,10 +84,6 @@ void ConfIndexW::acceptChanges()
|
|||||||
m_rclconf->updateMainConfig();
|
m_rclconf->updateMainConfig();
|
||||||
snapshotConfig();
|
snapshotConfig();
|
||||||
|
|
||||||
if (startIndexingAfterConfig) {
|
|
||||||
startIndexingAfterConfig = 0;
|
|
||||||
start_indexing(true);
|
|
||||||
}
|
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <qthread.h>
|
|
||||||
#include <qmutex.h>
|
|
||||||
#include <qwaitcondition.h>
|
|
||||||
|
|
||||||
#include "indexer.h"
|
|
||||||
#include "debuglog.h"
|
|
||||||
#include "idxthread.h"
|
|
||||||
#include "smallut.h"
|
|
||||||
#include "rclinit.h"
|
|
||||||
#include "pathut.h"
|
|
||||||
#include "recoll.h"
|
|
||||||
|
|
||||||
static int stopindexing;
|
|
||||||
static int startindexing;
|
|
||||||
static bool rezero;
|
|
||||||
static vector<Rcl::Doc> idxdocs; // Docs to update. Update all if empty
|
|
||||||
|
|
||||||
static IdxThreadStatus indexingstatus = IDXTS_OK;
|
|
||||||
static string indexingReason;
|
|
||||||
static int stopidxthread;
|
|
||||||
|
|
||||||
static QMutex curfile_mutex;
|
|
||||||
static QMutex action_mutex;
|
|
||||||
static QWaitCondition action_wait;
|
|
||||||
|
|
||||||
class IdxThread : public QThread , public DbIxStatusUpdater {
|
|
||||||
virtual void run();
|
|
||||||
public:
|
|
||||||
// This gets called at intervals by the file system walker to check for
|
|
||||||
// a requested interrupt and update the current status.
|
|
||||||
virtual bool update() {
|
|
||||||
QMutexLocker locker(&curfile_mutex);
|
|
||||||
m_statusSnap = status;
|
|
||||||
LOGDEB1(("IdxThread::update: indexing %s\n", m_statusSnap.fn.c_str()));
|
|
||||||
if (stopindexing) {
|
|
||||||
stopindexing = 0;
|
|
||||||
m_interrupted = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Maintain a copy/snapshot of idx status
|
|
||||||
DbIxStatus m_statusSnap;
|
|
||||||
bool m_interrupted;
|
|
||||||
};
|
|
||||||
|
|
||||||
void IdxThread::run()
|
|
||||||
{
|
|
||||||
recoll_threadinit();
|
|
||||||
action_mutex.lock();
|
|
||||||
for (;;) {
|
|
||||||
if (startindexing) {
|
|
||||||
startindexing = 0;
|
|
||||||
action_mutex.unlock();
|
|
||||||
|
|
||||||
m_interrupted = false;
|
|
||||||
indexingstatus = IDXTS_NULL;
|
|
||||||
// We make a private snapshot of the config: setKeydir changes
|
|
||||||
// it during indexing and it may be updated by the main thread.
|
|
||||||
RclConfig *myconf;
|
|
||||||
{
|
|
||||||
PTMutexLocker locker(thestableconfiglock);
|
|
||||||
myconf = new RclConfig(*thestableconfig);
|
|
||||||
}
|
|
||||||
int loglevel;
|
|
||||||
myconf->setKeyDir("");
|
|
||||||
myconf->getConfParam("loglevel", &loglevel);
|
|
||||||
DebugLog::getdbl()->setloglevel(loglevel);
|
|
||||||
|
|
||||||
Pidfile pidfile(myconf->getPidfile());
|
|
||||||
if (pidfile.open() != 0) {
|
|
||||||
// Have to sleep a little here else the main thread
|
|
||||||
// won't see the status change because it only tests
|
|
||||||
// after seeing IDXTS_NULL at least once. Better
|
|
||||||
// interlock needed...
|
|
||||||
sleep(2);
|
|
||||||
indexingstatus = IDXTS_ERROR;
|
|
||||||
indexingReason = "Indexing failed: other process active? " +
|
|
||||||
pidfile.getreason();
|
|
||||||
} else {
|
|
||||||
pidfile.write_pid();
|
|
||||||
ConfIndexer *indexer = new ConfIndexer(myconf, this);
|
|
||||||
bool status = idxdocs.empty() ?
|
|
||||||
indexer->index(rezero, ConfIndexer::IxTAll) :
|
|
||||||
indexer->updateDocs(idxdocs);
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
indexingstatus = IDXTS_OK;
|
|
||||||
indexingReason = "";
|
|
||||||
} else {
|
|
||||||
indexingstatus = IDXTS_ERROR;
|
|
||||||
indexingReason = "Indexing failed: " + indexer->getReason();
|
|
||||||
}
|
|
||||||
pidfile.close();
|
|
||||||
delete indexer;
|
|
||||||
}
|
|
||||||
delete myconf;
|
|
||||||
myconf = 0;
|
|
||||||
rezero = false;
|
|
||||||
action_mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stopidxthread) {
|
|
||||||
action_mutex.unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
action_wait.wait(&action_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static IdxThread idxthread;
|
|
||||||
|
|
||||||
// Functions called by the main thread
|
|
||||||
|
|
||||||
void start_idxthread()
|
|
||||||
{
|
|
||||||
idxthread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop_idxthread()
|
|
||||||
{
|
|
||||||
action_mutex.lock();
|
|
||||||
startindexing = 0;
|
|
||||||
stopindexing = 1;
|
|
||||||
stopidxthread = 1;
|
|
||||||
action_mutex.unlock();
|
|
||||||
action_wait.wakeAll();
|
|
||||||
idxthread.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop_indexing()
|
|
||||||
{
|
|
||||||
action_mutex.lock();
|
|
||||||
startindexing = 0;
|
|
||||||
stopindexing = 1;
|
|
||||||
action_mutex.unlock();
|
|
||||||
action_wait.wakeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_indexing(bool raz, vector<Rcl::Doc> docs)
|
|
||||||
{
|
|
||||||
action_mutex.lock();
|
|
||||||
startindexing = 1;
|
|
||||||
rezero = raz;
|
|
||||||
idxdocs = docs;
|
|
||||||
action_mutex.unlock();
|
|
||||||
action_wait.wakeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
DbIxStatus idxthread_idxStatus()
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&curfile_mutex);
|
|
||||||
return idxthread.m_statusSnap;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool idxthread_idxInterrupted()
|
|
||||||
{
|
|
||||||
return idxthread.m_interrupted;
|
|
||||||
}
|
|
||||||
|
|
||||||
string idxthread_getReason()
|
|
||||||
{
|
|
||||||
return indexingReason;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdxThreadStatus idxthread_getStatus()
|
|
||||||
{
|
|
||||||
return indexingstatus;
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
/* Copyright (C) 2004 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 _IDXTHREAD_H_INCLUDED_
|
|
||||||
#define _IDXTHREAD_H_INCLUDED_
|
|
||||||
#include <string>
|
|
||||||
#include "indexer.h"
|
|
||||||
#include "rcldoc.h"
|
|
||||||
|
|
||||||
// These two deal with starting / stopping the thread itself, not
|
|
||||||
// indexing sessions.
|
|
||||||
// cnf will be cloned each time we start an indexing pass. The pointer must
|
|
||||||
// stay valid for the whole program duration.
|
|
||||||
extern void start_idxthread();
|
|
||||||
extern void stop_idxthread();
|
|
||||||
|
|
||||||
// Use these to to request action from thread
|
|
||||||
extern void start_indexing(bool rezero = false,
|
|
||||||
const vector<Rcl::Doc> docs = vector<Rcl::Doc>());
|
|
||||||
extern void stop_indexing();
|
|
||||||
|
|
||||||
// Final status of indexing. indexingstatus is NULL iff indexing is
|
|
||||||
// currently in progress.
|
|
||||||
enum IdxThreadStatus {IDXTS_NULL = 0, IDXTS_OK = 1, IDXTS_ERROR = 2};
|
|
||||||
extern IdxThreadStatus idxthread_getStatus();
|
|
||||||
extern string idxthread_getReason();
|
|
||||||
|
|
||||||
// Current status of running indexing (phase, file name etc.)
|
|
||||||
extern DbIxStatus idxthread_idxStatus();
|
|
||||||
// Did last op fail because of stop request ?
|
|
||||||
extern bool idxthread_idxInterrupted();
|
|
||||||
#endif /* _IDXTHREAD_H_INCLUDED_ */
|
|
||||||
@ -97,7 +97,6 @@ Aspell *aspell;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int recollNeedsExit;
|
int recollNeedsExit;
|
||||||
int startIndexingAfterConfig;
|
|
||||||
RclMain *mainWindow;
|
RclMain *mainWindow;
|
||||||
|
|
||||||
void startManual(const string& helpindex)
|
void startManual(const string& helpindex)
|
||||||
@ -352,10 +351,6 @@ int main(int argc, char **argv)
|
|||||||
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
|
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
|
||||||
app.connect(&app, SIGNAL(aboutToQuit()), mainWindow, SLOT(close()));
|
app.connect(&app, SIGNAL(aboutToQuit()), mainWindow, SLOT(close()));
|
||||||
|
|
||||||
// Start the indexing thread. It will immediately go to sleep waiting for
|
|
||||||
// something to do.
|
|
||||||
start_idxthread();
|
|
||||||
|
|
||||||
mainWindow->sSearch->searchTypCMB->setCurrentIndex(prefs.ssearchTyp);
|
mainWindow->sSearch->searchTypCMB->setCurrentIndex(prefs.ssearchTyp);
|
||||||
mainWindow->sSearch->searchTypeChanged(prefs.ssearchTyp);
|
mainWindow->sSearch->searchTypeChanged(prefs.ssearchTyp);
|
||||||
if (op_flags & OPT_q) {
|
if (op_flags & OPT_q) {
|
||||||
|
|||||||
@ -48,6 +48,7 @@ using std::pair;
|
|||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
#include <qcursor.h>
|
#include <qcursor.h>
|
||||||
#include <qevent.h>
|
#include <qevent.h>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
@ -73,6 +74,7 @@ using std::pair;
|
|||||||
#include "idxsched.h"
|
#include "idxsched.h"
|
||||||
#include "crontool.h"
|
#include "crontool.h"
|
||||||
#include "rtitool.h"
|
#include "rtitool.h"
|
||||||
|
#include "indexer.h"
|
||||||
|
|
||||||
using namespace confgui;
|
using namespace confgui;
|
||||||
|
|
||||||
@ -97,7 +99,8 @@ void RclMain::init()
|
|||||||
(const char *)tr("filtered").toUtf8());
|
(const char *)tr("filtered").toUtf8());
|
||||||
|
|
||||||
periodictimer = new QTimer(this);
|
periodictimer = new QTimer(this);
|
||||||
|
m_watcher.addPath(QString::fromLocal8Bit(
|
||||||
|
theconfig->getIdxStatusFile().c_str()));
|
||||||
// At least some versions of qt4 don't display the status bar if
|
// At least some versions of qt4 don't display the status bar if
|
||||||
// it's not created here.
|
// it's not created here.
|
||||||
(void)statusBar();
|
(void)statusBar();
|
||||||
@ -203,6 +206,8 @@ void RclMain::init()
|
|||||||
connect(sc, SIGNAL (activated()),
|
connect(sc, SIGNAL (activated()),
|
||||||
this, SLOT (focusToSearch()));
|
this, SLOT (focusToSearch()));
|
||||||
|
|
||||||
|
connect(&m_watcher, SIGNAL(fileChanged(QString)),
|
||||||
|
this, SLOT(idxStatus()));
|
||||||
connect(sSearch, SIGNAL(startSearch(RefCntr<Rcl::SearchData>)),
|
connect(sSearch, SIGNAL(startSearch(RefCntr<Rcl::SearchData>)),
|
||||||
this, SLOT(startSearch(RefCntr<Rcl::SearchData>)));
|
this, SLOT(startSearch(RefCntr<Rcl::SearchData>)));
|
||||||
connect(sSearch, SIGNAL(clearSearch()),
|
connect(sSearch, SIGNAL(clearSearch()),
|
||||||
@ -473,82 +478,117 @@ void RclMain::fileExit()
|
|||||||
// We'd prefer to do this in the exit handler, but it's apparently to late
|
// We'd prefer to do this in the exit handler, but it's apparently to late
|
||||||
// and some of the qt stuff is already dead at this point?
|
// and some of the qt stuff is already dead at this point?
|
||||||
LOGDEB2(("RclMain::fileExit() : stopping idx thread\n"));
|
LOGDEB2(("RclMain::fileExit() : stopping idx thread\n"));
|
||||||
stop_idxthread();
|
|
||||||
|
// Do we want to stop an ongoing index operation here ?
|
||||||
|
// I guess not. We did use to cancel the indexing thread.
|
||||||
|
|
||||||
// Let the exit handler clean up the rest (internal recoll stuff).
|
// Let the exit handler clean up the rest (internal recoll stuff).
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called by a periodic timer to check the status of the
|
void RclMain::idxStatus()
|
||||||
// indexing thread and a possible need to exit
|
{
|
||||||
|
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", val);
|
||||||
|
status.docsdone = atoi(val.c_str());
|
||||||
|
cs.get("filesdone", val);
|
||||||
|
status.filesdone = atoi(val.c_str());
|
||||||
|
cs.get("dbtotdocs", val);
|
||||||
|
status.dbtotdocs = atoi(val.c_str());
|
||||||
|
|
||||||
|
QString phs;
|
||||||
|
switch (status.phase) {
|
||||||
|
case DbIxStatus::DBIXS_NONE:phs=tr("None");break;
|
||||||
|
case DbIxStatus::DBIXS_FILES: phs=tr("Updating");break;
|
||||||
|
case DbIxStatus::DBIXS_PURGE: phs=tr("Purge");break;
|
||||||
|
case DbIxStatus::DBIXS_STEMDB: phs=tr("Stemdb");break;
|
||||||
|
case DbIxStatus::DBIXS_CLOSING:phs=tr("Closing");break;
|
||||||
|
case DbIxStatus::DBIXS_DONE:phs=tr("Done");break;
|
||||||
|
case DbIxStatus::DBIXS_MONITOR:phs=tr("Monitor");break;
|
||||||
|
default: phs=tr("Unknown");break;
|
||||||
|
}
|
||||||
|
msg += phs + " ";
|
||||||
|
if (status.phase == DbIxStatus::DBIXS_FILES) {
|
||||||
|
char cnts[100];
|
||||||
|
if (status.dbtotdocs > 0)
|
||||||
|
sprintf(cnts,"(%d/%d/%d) ", status.docsdone, status.filesdone,
|
||||||
|
status.dbtotdocs);
|
||||||
|
else
|
||||||
|
sprintf(cnts, "(%d/%d) ", status.docsdone, status.filesdone);
|
||||||
|
msg += QString::fromAscii(cnts) + " ";
|
||||||
|
}
|
||||||
|
string mf;int ecnt = 0;
|
||||||
|
string fcharset = theconfig->getDefCharset(true);
|
||||||
|
if (!transcode(status.fn, mf, fcharset, "UTF-8", &ecnt) || ecnt) {
|
||||||
|
mf = url_encode(status.fn, 0);
|
||||||
|
}
|
||||||
|
msg += QString::fromUtf8(mf.c_str());
|
||||||
|
statusBar()->showMessage(msg, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called by a periodic timer to check the status of
|
||||||
|
// indexing, a possible need to exit, and cleanup exited viewers
|
||||||
void RclMain::periodic100()
|
void RclMain::periodic100()
|
||||||
{
|
{
|
||||||
// Check if indexing thread done
|
LOGDEB2(("Periodic100\n"));
|
||||||
if (idxthread_getStatus() != IDXTS_NULL) {
|
if (m_idxproc) {
|
||||||
// Indexing is stopped
|
// An indexing process was launched. If its' done, see status.
|
||||||
fileToggleIndexingAction->setText(tr("Update &Index"));
|
int status;
|
||||||
fileToggleIndexingAction->setEnabled(TRUE);
|
bool exited = m_idxproc->maybereap(&status);
|
||||||
if (m_idxStatusAck == false) {
|
if (exited) {
|
||||||
m_idxStatusAck = true;
|
deleteZ(m_idxproc);
|
||||||
if (idxthread_getStatus() != IDXTS_OK) {
|
if (status) {
|
||||||
if (idxthread_idxInterrupted()) {
|
QMessageBox::warning(0, "Recoll",
|
||||||
QMessageBox::warning(0, "Recoll",
|
tr("Indexing failed"));
|
||||||
tr("Indexing interrupted"));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(0, "Recoll",
|
|
||||||
QString::fromAscii(idxthread_getReason().c_str()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Make sure we reopen the db to get the results. If there
|
|
||||||
// is current search data, we should reset it else things
|
|
||||||
// are inconsistent (ie: applying sort will fail. But we
|
|
||||||
// don't like erasing results while the user may be
|
|
||||||
// looking at them either). Fixing this would be
|
|
||||||
// relatively complicated (keep an open/close gen number
|
|
||||||
// and check this / restart query in DocSeqDb() ?)
|
|
||||||
string reason;
|
string reason;
|
||||||
maybeOpenDb(reason, 1);
|
maybeOpenDb(reason, 1);
|
||||||
periodictimer->setInterval(1000);
|
} else {
|
||||||
|
// update/show status even if the status file did not
|
||||||
|
// change (else the status line goes blank during
|
||||||
|
// lengthy operations).
|
||||||
|
idxStatus();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// Indexing is running
|
// Update the "start/stop indexing" menu entry, can't be done from
|
||||||
m_idxStatusAck = false;
|
// the "start/stop indexing" slot itself
|
||||||
|
if (m_idxproc) {
|
||||||
fileToggleIndexingAction->setText(tr("Stop &Indexing"));
|
fileToggleIndexingAction->setText(tr("Stop &Indexing"));
|
||||||
fileToggleIndexingAction->setEnabled(TRUE);
|
fileToggleIndexingAction->setEnabled(TRUE);
|
||||||
periodictimer->setInterval(100);
|
} else {
|
||||||
// The toggle thing is for the status to flash
|
fileToggleIndexingAction->setText(tr("Update &Index"));
|
||||||
if (m_periodicToggle < 9) {
|
// No indexer of our own runnin, but the real time one may be up, check
|
||||||
QString msg = tr("Indexing in progress: ");
|
// for some other indexer.
|
||||||
DbIxStatus status = idxthread_idxStatus();
|
Pidfile pidfile(theconfig->getPidfile());
|
||||||
QString phs;
|
if (pidfile.open() == 0) {
|
||||||
switch (status.phase) {
|
fileToggleIndexingAction->setEnabled(TRUE);
|
||||||
case DbIxStatus::DBIXS_FILES: phs=tr("Files");break;
|
} else {
|
||||||
case DbIxStatus::DBIXS_PURGE: phs=tr("Purge");break;
|
fileToggleIndexingAction->setEnabled(FALSE);
|
||||||
case DbIxStatus::DBIXS_STEMDB: phs=tr("Stemdb");break;
|
}
|
||||||
case DbIxStatus::DBIXS_CLOSING:phs=tr("Closing");break;
|
|
||||||
default: phs=tr("Unknown");break;
|
|
||||||
}
|
|
||||||
msg += phs + " ";
|
|
||||||
if (status.phase == DbIxStatus::DBIXS_FILES) {
|
|
||||||
char cnts[100];
|
|
||||||
if (status.dbtotdocs>0)
|
|
||||||
sprintf(cnts,"(%d/%d) ",status.docsdone, status.dbtotdocs);
|
|
||||||
else
|
|
||||||
sprintf(cnts, "(%d) ", status.docsdone);
|
|
||||||
msg += QString::fromAscii(cnts) + " ";
|
|
||||||
}
|
|
||||||
string mf;int ecnt = 0;
|
|
||||||
string fcharset = theconfig->getDefCharset(true);
|
|
||||||
if (!transcode(status.fn, mf, fcharset, "UTF-8", &ecnt) || ecnt) {
|
|
||||||
mf = url_encode(status.fn, 0);
|
|
||||||
}
|
|
||||||
msg += QString::fromUtf8(mf.c_str());
|
|
||||||
statusBar()->showMessage(msg, 4000);
|
|
||||||
} else if (m_periodicToggle == 9) {
|
|
||||||
statusBar()->showMessage("");
|
|
||||||
}
|
|
||||||
if (++m_periodicToggle >= 10)
|
|
||||||
m_periodicToggle = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Possibly cleanup the dead viewers
|
||||||
|
for (vector<ExecCmd*>::iterator it = m_viewers.begin();
|
||||||
|
it != m_viewers.end(); it++) {
|
||||||
|
int status;
|
||||||
|
if ((*it)->maybereap(&status)) {
|
||||||
|
deleteZ(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vector<ExecCmd*> v;
|
||||||
|
for (vector<ExecCmd*>::iterator it = m_viewers.begin();
|
||||||
|
it != m_viewers.end(); it++) {
|
||||||
|
if (*it)
|
||||||
|
v.push_back(*it);
|
||||||
|
}
|
||||||
|
m_viewers = v;
|
||||||
|
|
||||||
if (recollNeedsExit)
|
if (recollNeedsExit)
|
||||||
fileExit();
|
fileExit();
|
||||||
}
|
}
|
||||||
@ -558,14 +598,16 @@ void RclMain::periodic100()
|
|||||||
// re-enabled by the indexing status check
|
// re-enabled by the indexing status check
|
||||||
void RclMain::toggleIndexing()
|
void RclMain::toggleIndexing()
|
||||||
{
|
{
|
||||||
if (idxthread_getStatus() == IDXTS_NULL) {
|
if (m_idxproc) {
|
||||||
// Indexing was in progress, stop it
|
// Indexing was in progress, request stop. Let the periodic
|
||||||
stop_indexing();
|
// routine check for the results.
|
||||||
periodictimer->setInterval(1000);
|
kill(m_idxproc->getChildPid(), SIGTERM);
|
||||||
fileToggleIndexingAction->setText(tr("Update &Index"));
|
|
||||||
} else {
|
} else {
|
||||||
start_indexing(false);
|
list<string> args;
|
||||||
periodictimer->setInterval(100);
|
args.push_back("-c");
|
||||||
|
args.push_back(theconfig->getConfDir());
|
||||||
|
m_idxproc = new ExecCmd;
|
||||||
|
m_idxproc->startExec("recollindex", args, false, false);
|
||||||
fileToggleIndexingAction->setText(tr("Stop &Indexing"));
|
fileToggleIndexingAction->setText(tr("Stop &Indexing"));
|
||||||
}
|
}
|
||||||
fileToggleIndexingAction->setEnabled(FALSE);
|
fileToggleIndexingAction->setEnabled(FALSE);
|
||||||
@ -574,15 +616,14 @@ void RclMain::toggleIndexing()
|
|||||||
// Start a db query and set the reslist docsource
|
// Start a db query and set the reslist docsource
|
||||||
void RclMain::startSearch(RefCntr<Rcl::SearchData> sdata)
|
void RclMain::startSearch(RefCntr<Rcl::SearchData> sdata)
|
||||||
{
|
{
|
||||||
LOGDEB(("RclMain::startSearch. Indexing %s\n",
|
LOGDEB(("RclMain::startSearch. Indexing %s\n", m_idxproc?"on":"off"));
|
||||||
idxthread_getStatus() == IDXTS_NULL?"on":"off"));
|
|
||||||
emit searchReset();
|
emit searchReset();
|
||||||
m_source = RefCntr<DocSequence>();
|
m_source = RefCntr<DocSequence>();
|
||||||
|
|
||||||
// The db may have been closed at the end of indexing
|
// The db may have been closed at the end of indexing
|
||||||
string reason;
|
string reason;
|
||||||
// If indexing is being performed, we reopen the db at each query.
|
// If indexing is being performed, we reopen the db at each query.
|
||||||
if (!maybeOpenDb(reason, idxthread_getStatus() == IDXTS_NULL)) {
|
if (!maybeOpenDb(reason, m_idxproc != 0)) {
|
||||||
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -970,7 +1011,7 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod)
|
|||||||
QMessageBox::warning(0, tr("Warning"),
|
QMessageBox::warning(0, tr("Warning"),
|
||||||
tr("Index not up to date for this file. "
|
tr("Index not up to date for this file. "
|
||||||
"Refusing to risk showing the wrong "
|
"Refusing to risk showing the wrong "
|
||||||
"data. Click ok to update the "
|
"entry. Click Ok to update the "
|
||||||
"index for this file, then re-run the "
|
"index for this file, then re-run the "
|
||||||
"query when indexing is done. "
|
"query when indexing is done. "
|
||||||
"Else, Cancel."),
|
"Else, Cancel."),
|
||||||
@ -980,7 +1021,8 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod)
|
|||||||
if (rep == QMessageBox::Ok) {
|
if (rep == QMessageBox::Ok) {
|
||||||
LOGDEB(("Requesting index update for %s\n",
|
LOGDEB(("Requesting index update for %s\n",
|
||||||
doc.url.c_str()));
|
doc.url.c_str()));
|
||||||
start_indexing(false, vector<Rcl::Doc>(1, doc));
|
vector<Rcl::Doc> docs(1, doc);
|
||||||
|
updateIdxForDocs(docs);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1023,6 +1065,30 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod)
|
|||||||
curPreview->makeDocCurrent(doc, docnum);
|
curPreview->makeDocCurrent(doc, docnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RclMain::updateIdxForDocs(vector<Rcl::Doc>& docs)
|
||||||
|
{
|
||||||
|
if (m_idxproc) {
|
||||||
|
QMessageBox::warning(0, tr("Warning"),
|
||||||
|
tr("Can't update index: indexer running"),
|
||||||
|
QMessageBox::Ok,
|
||||||
|
QMessageBox::NoButton);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> paths;
|
||||||
|
if (ConfIndexer::docsToPaths(docs, paths)) {
|
||||||
|
list<string> args;
|
||||||
|
args.push_back("-c");
|
||||||
|
args.push_back(theconfig->getConfDir());
|
||||||
|
args.push_back("-i");
|
||||||
|
args.insert(args.end(), paths.begin(), paths.end());
|
||||||
|
m_idxproc = new ExecCmd;
|
||||||
|
m_idxproc->startExec("recollindex", args, false, false);
|
||||||
|
fileToggleIndexingAction->setText(tr("Stop &Indexing"));
|
||||||
|
}
|
||||||
|
fileToggleIndexingAction->setEnabled(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a preview window for a given document, no linking to result list
|
* Open a preview window for a given document, no linking to result list
|
||||||
*
|
*
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qmainwindow.h>
|
#include <qmainwindow.h>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
#include "sortseq.h"
|
#include "sortseq.h"
|
||||||
#include "preview_w.h"
|
#include "preview_w.h"
|
||||||
@ -66,7 +67,7 @@ public:
|
|||||||
displayingTable(0),
|
displayingTable(0),
|
||||||
m_idNoStem(0),
|
m_idNoStem(0),
|
||||||
m_idAllStem(0),
|
m_idAllStem(0),
|
||||||
m_idxStatusAck(false),
|
m_idxproc(0),
|
||||||
m_sortspecnochange(false),
|
m_sortspecnochange(false),
|
||||||
m_periodicToggle(0)
|
m_periodicToggle(0)
|
||||||
{
|
{
|
||||||
@ -80,6 +81,7 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
virtual bool close();
|
virtual bool close();
|
||||||
virtual void fileExit();
|
virtual void fileExit();
|
||||||
|
virtual void idxStatus();
|
||||||
virtual void periodic100();
|
virtual void periodic100();
|
||||||
virtual void toggleIndexing();
|
virtual void toggleIndexing();
|
||||||
virtual void startSearch(RefCntr<Rcl::SearchData> sdata);
|
virtual void startSearch(RefCntr<Rcl::SearchData> sdata);
|
||||||
@ -155,11 +157,12 @@ private:
|
|||||||
bool displayingTable;
|
bool displayingTable;
|
||||||
QAction *m_idNoStem;
|
QAction *m_idNoStem;
|
||||||
QAction *m_idAllStem;
|
QAction *m_idAllStem;
|
||||||
|
QFileSystemWatcher m_watcher;
|
||||||
|
|
||||||
vector<ExecCmd*> m_viewers;
|
vector<ExecCmd*> m_viewers;
|
||||||
|
ExecCmd *m_idxproc; // Indexing process
|
||||||
map<QString, QAction*> m_stemLangToId;
|
map<QString, QAction*> m_stemLangToId;
|
||||||
vector<string> m_catgbutvec;
|
vector<string> m_catgbutvec;
|
||||||
bool m_idxStatusAck; // Did we act on last status?
|
|
||||||
DocSeqFiltSpec m_filtspec;
|
DocSeqFiltSpec m_filtspec;
|
||||||
bool m_sortspecnochange;
|
bool m_sortspecnochange;
|
||||||
DocSeqSortSpec m_sortspec;
|
DocSeqSortSpec m_sortspec;
|
||||||
@ -175,6 +178,7 @@ private:
|
|||||||
virtual void showIndexSched(bool modal);
|
virtual void showIndexSched(bool modal);
|
||||||
virtual void showCronTool(bool modal);
|
virtual void showCronTool(bool modal);
|
||||||
virtual void showRTITool(bool modal);
|
virtual void showRTITool(bool modal);
|
||||||
|
virtual void updateIdxForDocs(vector<Rcl::Doc>&);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RCLMAIN_W_H
|
#endif // RCLMAIN_W_H
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "rcldb.h"
|
#include "rcldb.h"
|
||||||
#include "idxthread.h"
|
|
||||||
#include "ptmutex.h"
|
#include "ptmutex.h"
|
||||||
|
|
||||||
// Misc declarations in need of sharing between the UI files
|
// Misc declarations in need of sharing between the UI files
|
||||||
@ -41,7 +40,6 @@ extern void forgetTempFile(string &fn);
|
|||||||
|
|
||||||
extern Rcl::Db *rcldb;
|
extern Rcl::Db *rcldb;
|
||||||
extern int recollNeedsExit;
|
extern int recollNeedsExit;
|
||||||
extern int startIndexingAfterConfig; // 1st startup
|
|
||||||
extern void startManual(const string& helpindex);
|
extern void startManual(const string& helpindex);
|
||||||
|
|
||||||
#ifdef RCL_USE_ASPELL
|
#ifdef RCL_USE_ASPELL
|
||||||
|
|||||||
@ -30,7 +30,6 @@ SOURCES += \
|
|||||||
confgui/confguiindex.cpp \
|
confgui/confguiindex.cpp \
|
||||||
crontool.cpp \
|
crontool.cpp \
|
||||||
guiutils.cpp \
|
guiutils.cpp \
|
||||||
idxthread.cpp \
|
|
||||||
main.cpp \
|
main.cpp \
|
||||||
preview_w.cpp \
|
preview_w.cpp \
|
||||||
rclhelp.cpp \
|
rclhelp.cpp \
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#ifndef TEST_EXECMD
|
#ifndef TEST_EXECMD
|
||||||
#include "autoconfig.h"
|
#include "autoconfig.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -138,7 +139,7 @@ public:
|
|||||||
int status;
|
int status;
|
||||||
if (m_parent->m_pid > 0) {
|
if (m_parent->m_pid > 0) {
|
||||||
pid_t grp = getpgid(m_parent->m_pid);
|
pid_t grp = getpgid(m_parent->m_pid);
|
||||||
LOGDEB2(("ExecCmd: killpg(%d, SIGTERM)\n", grp));
|
LOGDEB(("ExecCmd: killpg(%d, SIGTERM)\n", grp));
|
||||||
int ret = killpg(grp, SIGTERM);
|
int ret = killpg(grp, SIGTERM);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
@ -385,7 +386,10 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
|||||||
// Normal return: deactivate cleaner, wait() will do the cleanup
|
// Normal return: deactivate cleaner, wait() will do the cleanup
|
||||||
e.inactivate();
|
e.inactivate();
|
||||||
|
|
||||||
return ExecCmd::wait(ret);
|
int ret1 = ExecCmd::wait();
|
||||||
|
if (ret)
|
||||||
|
return -1;
|
||||||
|
return ret1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExecCmd::send(const string& data)
|
int ExecCmd::send(const string& data)
|
||||||
@ -457,17 +461,46 @@ int ExecCmd::getline(string& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for command status and clean up all resources.
|
// Wait for command status and clean up all resources.
|
||||||
int ExecCmd::wait(bool haderror)
|
int ExecCmd::wait()
|
||||||
{
|
{
|
||||||
ExecCmdRsrc e(this);
|
ExecCmdRsrc e(this);
|
||||||
int status = -1;
|
int status = -1;
|
||||||
if (!m_killRequest && m_pid > 0) {
|
if (!m_killRequest && m_pid > 0) {
|
||||||
if (waitpid(m_pid, &status, 0) < 0)
|
if (waitpid(m_pid, &status, 0) < 0) {
|
||||||
|
LOGERR(("ExecCmd::waitpid: returned -1 errno %d\n", errno));
|
||||||
status = -1;
|
status = -1;
|
||||||
|
}
|
||||||
LOGDEB(("ExecCmd::wait: got status 0x%x\n", status));
|
LOGDEB(("ExecCmd::wait: got status 0x%x\n", status));
|
||||||
m_pid = -1;
|
m_pid = -1;
|
||||||
}
|
}
|
||||||
return haderror ? -1 : status;
|
// Let the ExecCmdRsrc cleanup
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExecCmd::maybereap(int *status)
|
||||||
|
{
|
||||||
|
ExecCmdRsrc e(this);
|
||||||
|
*status = -1;
|
||||||
|
|
||||||
|
if (m_pid <= 0) {
|
||||||
|
// Already waited for ??
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = waitpid(m_pid, status, WNOHANG);
|
||||||
|
if (pid < 0) {
|
||||||
|
LOGERR(("ExecCmd::maybereap: returned -1 errno %d\n", errno));
|
||||||
|
m_pid = -1;
|
||||||
|
return true;
|
||||||
|
} else if (pid == 0) {
|
||||||
|
LOGDEB1(("ExecCmd::maybereap: not exited yet\n"));
|
||||||
|
e.inactivate();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LOGDEB(("ExecCmd::maybereap: got status 0x%x\n", status));
|
||||||
|
m_pid = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In child process. Set up pipes, environment, and exec command.
|
// In child process. Set up pipes, environment, and exec command.
|
||||||
@ -591,8 +624,11 @@ void ReExec::init(int argc, char *args[])
|
|||||||
free(cd);
|
free(cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reexecute myself, as close as possible to the initial exec
|
||||||
void ReExec::reexec()
|
void ReExec::reexec()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if 0
|
||||||
char *cwd;
|
char *cwd;
|
||||||
cwd = getcwd(0,0);
|
cwd = getcwd(0,0);
|
||||||
FILE *fp = stdout; //fopen("/tmp/exectrace", "w");
|
FILE *fp = stdout; //fopen("/tmp/exectrace", "w");
|
||||||
@ -604,10 +640,13 @@ void ReExec::reexec()
|
|||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Try to get back to the initial working directory
|
||||||
if (m_cfd < 0 || fchdir(m_cfd) < 0) {
|
if (m_cfd < 0 || fchdir(m_cfd) < 0) {
|
||||||
if (fp) fprintf(fp, "fchdir failed, trying chdir\n");
|
LOGINFO(("ReExec::reexec: fchdir failed, trying chdir\n"));
|
||||||
if (!m_curdir.empty() && chdir(m_curdir.c_str())) {
|
if (!m_curdir.empty() && chdir(m_curdir.c_str())) {
|
||||||
if (fp) fprintf(fp, "chdir failed too\n");
|
LOGERR(("ReExec::reexec: chdir failed\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -120,7 +120,7 @@ class ExecCmd {
|
|||||||
* @param args the argument list (NOT including argv[0]).
|
* @param args the argument list (NOT including argv[0]).
|
||||||
* @param input Input to send TO the command.
|
* @param input Input to send TO the command.
|
||||||
* @param output Output FROM the command.
|
* @param output Output FROM the command.
|
||||||
* @return the exec ouput status (0 if ok).
|
* @return the exec ouput status (0 if ok), or -1
|
||||||
*/
|
*/
|
||||||
int doexec(const string &cmd, const list<string>& args,
|
int doexec(const string &cmd, const list<string>& args,
|
||||||
const string *input = 0,
|
const string *input = 0,
|
||||||
@ -135,7 +135,11 @@ class ExecCmd {
|
|||||||
int send(const string& data);
|
int send(const string& data);
|
||||||
int receive(string& data, int cnt = -1);
|
int receive(string& data, int cnt = -1);
|
||||||
int getline(string& data);
|
int getline(string& data);
|
||||||
int wait(bool haderror = false);
|
int wait();
|
||||||
|
/** Wait with WNOHANG set.
|
||||||
|
@return true if process exited, false else.
|
||||||
|
@param O: status, the wait(2) call's status value */
|
||||||
|
bool maybereap(int *status);
|
||||||
|
|
||||||
pid_t getChildPid() {return m_pid;}
|
pid_t getChildPid() {return m_pid;}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user