indexing: create lock / pid file
This commit is contained in:
parent
9d26fe43cf
commit
166399fd62
@ -850,6 +850,10 @@ string RclConfig::getStopfile()
|
||||
{
|
||||
return path_cat(getConfDir(), "stoplist.txt");
|
||||
}
|
||||
string RclConfig::getPidfile()
|
||||
{
|
||||
return path_cat(getConfDir(), "index.pid");
|
||||
}
|
||||
|
||||
list<string>& RclConfig::getSkippedNames()
|
||||
{
|
||||
|
||||
@ -135,6 +135,8 @@ class RclConfig {
|
||||
string getDbDir();
|
||||
/** Get stoplist file name */
|
||||
string getStopfile();
|
||||
/** Get indexing pid file */
|
||||
string getPidfile();
|
||||
|
||||
/** Get list of skipped file names for current keydir */
|
||||
list<string>& getSkippedNames();
|
||||
|
||||
@ -206,6 +206,16 @@ RclConfig *RclConfig::getMainConfig()
|
||||
return config;
|
||||
}
|
||||
|
||||
void lockorexit(Pidfile *pidfile)
|
||||
{
|
||||
pid_t pid;
|
||||
if ((pid = pidfile->open()) != 0) {
|
||||
cerr << "Can't become exclusive indexer: " << pidfile->getreason() <<
|
||||
". Return (other pid?): " << pid << endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
string a_config;
|
||||
@ -268,12 +278,16 @@ int main(int argc, const char **argv)
|
||||
exit(1);
|
||||
}
|
||||
bool rezero(op_flags & OPT_z);
|
||||
Pidfile pidfile(config->getPidfile());
|
||||
|
||||
if (setpriority(PRIO_PGRP, 0, 20) != 0) {
|
||||
LOGINFO(("recollindex: can't setpriority(), errno %d\n", errno));
|
||||
}
|
||||
|
||||
|
||||
if (op_flags & (OPT_i|OPT_e)) {
|
||||
lockorexit(&pidfile);
|
||||
pidfile.write_pid();
|
||||
|
||||
list<string> filenames;
|
||||
|
||||
if (argc == 0) {
|
||||
@ -316,6 +330,7 @@ int main(int argc, const char **argv)
|
||||
} else if (op_flags & OPT_m) {
|
||||
if (argc != 0)
|
||||
Usage();
|
||||
lockorexit(&pidfile);
|
||||
if (!(op_flags&OPT_D)) {
|
||||
LOGDEB(("recollindex: daemonizing\n"));
|
||||
daemon(0,0);
|
||||
@ -325,6 +340,7 @@ int main(int argc, const char **argv)
|
||||
if (setpriority(PRIO_PGRP, 0, 20) != 0) {
|
||||
LOGINFO(("recollindex: can't setpriority(), errno %d\n", errno));
|
||||
}
|
||||
pidfile.write_pid();
|
||||
if (sleepsecs > 0) {
|
||||
LOGDEB(("recollindex: sleeping %d\n", sleepsecs));
|
||||
sleep(sleepsecs);
|
||||
@ -356,6 +372,8 @@ int main(int argc, const char **argv)
|
||||
cerr << "Not yet" << endl;
|
||||
return 1;
|
||||
} else {
|
||||
lockorexit(&pidfile);
|
||||
pidfile.write_pid();
|
||||
confindexer = new ConfIndexer(config, &updater);
|
||||
bool status = confindexer->index(rezero, ConfIndexer::IxTAll);
|
||||
if (!status)
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
/*
|
||||
* 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
|
||||
@ -17,6 +15,9 @@
|
||||
* 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>
|
||||
@ -27,6 +28,7 @@
|
||||
#include "idxthread.h"
|
||||
#include "smallut.h"
|
||||
#include "rclinit.h"
|
||||
#include "pathut.h"
|
||||
|
||||
static int stopindexing;
|
||||
static int startindexing;
|
||||
@ -79,16 +81,26 @@ void IdxThread::run()
|
||||
myconf->setKeyDir("");
|
||||
myconf->getConfParam("loglevel", &loglevel);
|
||||
DebugLog::getdbl()->setloglevel(loglevel);
|
||||
ConfIndexer *indexer = new ConfIndexer(myconf, this);
|
||||
if (indexer->index(rezero, ConfIndexer::IxTAll)) {
|
||||
indexingstatus = IDXTS_OK;
|
||||
indexingReason = "";
|
||||
} else {
|
||||
|
||||
Pidfile pidfile(myconf->getPidfile());
|
||||
if (pidfile.open() != 0) {
|
||||
indexingstatus = IDXTS_ERROR;
|
||||
indexingReason = "Indexing failed: " + indexer->getReason();
|
||||
indexingReason = "Indexing failed: other process active? " +
|
||||
pidfile.getreason();
|
||||
} else {
|
||||
pidfile.write_pid();
|
||||
ConfIndexer *indexer = new ConfIndexer(myconf, this);
|
||||
if (indexer->index(rezero, ConfIndexer::IxTAll)) {
|
||||
indexingstatus = IDXTS_OK;
|
||||
indexingReason = "";
|
||||
} else {
|
||||
indexingstatus = IDXTS_ERROR;
|
||||
indexingReason = "Indexing failed: " + indexer->getReason();
|
||||
}
|
||||
pidfile.close();
|
||||
delete indexer;
|
||||
}
|
||||
rezero = false;
|
||||
delete indexer;
|
||||
action_mutex.lock();
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,11 @@ static char rcsid[] = "@(#$Id: pathut.cpp,v 1.23 2008-11-24 15:47:40 dockes Exp
|
||||
#include <sys/param.h>
|
||||
#include <pwd.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// Let's include all files where statfs can be defined and hope for no
|
||||
// conflict...
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
@ -452,6 +456,96 @@ bool printableUrl(const string &fcharset, const string &in, string &out)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Pidfile::~Pidfile()
|
||||
{
|
||||
if (m_fd >= 0)
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
pid_t Pidfile::read_pid()
|
||||
{
|
||||
int fd = ::open(m_path.c_str(), O_RDONLY);
|
||||
if (fd == -1)
|
||||
return (pid_t)-1;
|
||||
|
||||
char buf[16];
|
||||
int error;
|
||||
int i = read(fd, buf, sizeof(buf) - 1);
|
||||
error = errno;
|
||||
::close(fd);
|
||||
if (i <= 0)
|
||||
return (pid_t)-1;
|
||||
buf[i] = '\0';
|
||||
char *endptr;
|
||||
pid_t pid = strtol(buf, &endptr, 10);
|
||||
if (endptr != &buf[i])
|
||||
return (pid_t)-1;
|
||||
return pid;
|
||||
}
|
||||
|
||||
int Pidfile::flopen()
|
||||
{
|
||||
const char *path = m_path.c_str();
|
||||
int operation = LOCK_EX | LOCK_NB;
|
||||
if ((m_fd = ::open(path, O_RDWR|O_CREAT, 0644)) == -1) {
|
||||
m_reason = "Open failed";
|
||||
return -1;
|
||||
}
|
||||
if (flock(m_fd, operation) == -1) {
|
||||
int serrno = errno;
|
||||
(void)::close(m_fd);
|
||||
errno = serrno;
|
||||
m_reason = "flock failed";
|
||||
return -1;
|
||||
}
|
||||
if (ftruncate(m_fd, 0) != 0) {
|
||||
/* can't happen [tm] */
|
||||
int serrno = errno;
|
||||
(void)::close(m_fd);
|
||||
errno = serrno;
|
||||
m_reason = "ftruncate failed";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t Pidfile::open()
|
||||
{
|
||||
if (flopen() < 0) {
|
||||
return read_pid();
|
||||
}
|
||||
return (pid_t)0;
|
||||
}
|
||||
|
||||
int Pidfile::write_pid()
|
||||
{
|
||||
/* truncate to allow multiple calls */
|
||||
if (ftruncate(m_fd, 0) == -1) {
|
||||
m_reason = "ftruncate failed";
|
||||
return -1;
|
||||
}
|
||||
char pidstr[20];
|
||||
sprintf(pidstr, "%u", int(getpid()));
|
||||
lseek(m_fd, 0, 0);
|
||||
if (::write(m_fd, pidstr, strlen(pidstr)) != (ssize_t)strlen(pidstr)) {
|
||||
m_reason = "write failed";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pidfile::close()
|
||||
{
|
||||
return ::close(m_fd);
|
||||
}
|
||||
|
||||
int Pidfile::remove()
|
||||
{
|
||||
return unlink(m_path.c_str());
|
||||
}
|
||||
|
||||
#else // TEST_PATHUT
|
||||
|
||||
#include <iostream>
|
||||
@ -522,7 +616,7 @@ int main(int argc, const char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "Usage: fsocc: trpathut <path>\n");
|
||||
exit(1);
|
||||
@ -537,6 +631,21 @@ int main(int argc, const char **argv)
|
||||
}
|
||||
printf("pc %d, megabytes %ld\n", pc, blocks);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
Pidfile pidfile("/tmp/pathutpidfile");
|
||||
pid_t pid;
|
||||
if ((pid = pidfile.open()) != 0) {
|
||||
cerr << "open failed. reason: " << pidfile.getreason() <<
|
||||
" return " << pid << endl;
|
||||
exit(1);
|
||||
}
|
||||
pidfile.write_pid();
|
||||
sleep(10);
|
||||
pidfile.close();
|
||||
pidfile.remove();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -101,4 +101,30 @@ private:
|
||||
string m_reason;
|
||||
};
|
||||
|
||||
/// Lock/pid file class. This is quite close to the pidfile_xxx
|
||||
/// utilities in FreeBSD with a bit more encapsulation. I'd have used
|
||||
/// the freebsd code if it was available elsewhere
|
||||
class Pidfile {
|
||||
public:
|
||||
Pidfile(const string& path) : m_path(path), m_fd(-1) {}
|
||||
~Pidfile();
|
||||
/// Open/create the pid file.
|
||||
/// @return 0 if ok, > 0 for pid of existing process, -1 for other error.
|
||||
pid_t open();
|
||||
/// Write pid into the pid file
|
||||
/// @return 0 ok, -1 error
|
||||
int write_pid();
|
||||
/// Close the pid file (unlocks)
|
||||
int close();
|
||||
/// Delete the pid file
|
||||
int remove();
|
||||
const string& getreason() {return m_reason;}
|
||||
private:
|
||||
string m_path;
|
||||
int m_fd;
|
||||
string m_reason;
|
||||
pid_t read_pid();
|
||||
int flopen();
|
||||
};
|
||||
|
||||
#endif /* _PATHUT_H_INCLUDED_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user