indexing: create lock / pid file

This commit is contained in:
Jean-Francois Dockes 2011-01-08 19:24:26 +01:00
parent 9d26fe43cf
commit 166399fd62
6 changed files with 182 additions and 11 deletions

View File

@ -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()
{

View File

@ -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();

View File

@ -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)

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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_ */