Switch to side-by-side view

--- a/src/index/rclmonprc.cpp
+++ b/src/index/rclmonprc.cpp
@@ -2,7 +2,7 @@
 
 #ifdef RCL_MONITOR
 #ifndef lint
-static char rcsid[] = "@(#$Id: rclmonprc.cpp,v 1.3 2006-10-22 14:47:13 dockes Exp $ (C) 2006 J.F.Dockes";
+static char rcsid[] = "@(#$Id: rclmonprc.cpp,v 1.4 2006-10-24 12:48:09 dockes Exp $ (C) 2006 J.F.Dockes";
 #endif
 /*
  *   This program is free software; you can redistribute it and/or modify
@@ -28,14 +28,22 @@
  */
 
 #include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
 
 #include "debuglog.h"
 #include "rclmon.h"
 #include "debuglog.h"
 #include "indexer.h"
+#include "pathut.h"
 
 typedef map<string, RclMonEvent> queue_type;
 
+/** Private part of RclEQ: things that we don't wish to exist in the interface
+ *  include file.
+ */
 class RclEQData {
 public:
     queue_type m_queue;
@@ -51,16 +59,18 @@
     }
 };
 
-RclMonEventQueue rclEQ;
+static RclMonEventQueue rclEQ;
 
 RclMonEventQueue::RclMonEventQueue()
 {
     m_data = new RclEQData;
 }
+
 RclMonEventQueue::~RclMonEventQueue()
 {
     delete m_data;
 }
+
 bool RclMonEventQueue::empty()
 {
     return m_data == 0 ? true : m_data->m_queue.empty();
@@ -138,22 +148,91 @@
 {
     LOGDEB2(("RclMonEventQueue::pushEvent for %s\n", ev.m_path.c_str()));
     lock();
-    // It seems that a newer event always override any older. TBVerified ?
+    // It seems that a newer event is always correct to override any
+    // older. TBVerified ?
     m_data->m_queue[ev.m_path] = ev;
     pthread_cond_broadcast(&m_data->m_cond);
     unlock();
     return true;
 }
 
+static string pidfile;
+/** There can only be one real time indexing process running */
+static bool processlock(const string &confdir) 
+{
+    pidfile = path_cat(confdir, RCL_MONITOR_PIDFILENAME);
+    for (int i = 0; i < 2; i++) {
+	int fd = open(pidfile.c_str(), O_RDWR|O_CREAT|O_EXCL, 0644);
+	if (fd < 0) {
+	    if (errno != EEXIST) {
+		LOGERR(("processlock: cant create %s, errno %d\n",
+			pidfile.c_str(), errno));
+		return false;
+	    }
+	    if ((fd = open(pidfile.c_str(), O_RDONLY)) < 0) {
+		LOGERR(("processlock: cant open existing %s, errno %d\n",
+			pidfile.c_str(), errno));
+		return false;
+	    }
+	    char buf[20];
+	    memset(buf, 0, sizeof(buf));
+	    if (read(fd, buf, 19) < 0) {
+		LOGERR(("processlock: cant read existing %s, errno %d\n",
+			pidfile.c_str(), errno));
+		close(fd);
+		return false;
+	    }
+	    close(fd);
+	    int pid = atoi(buf);
+	    if (pid <= 0 || (kill(pid, 0) < 0 && errno == ESRCH)) {
+		// File exists but no process
+		if (unlink(pidfile.c_str()) < 0) {
+		    LOGERR(("processlock: cant unlink existing %s, errno %d\n",
+			    pidfile.c_str(), errno));
+		    return false;
+		}
+		// Let's retry
+		continue;
+	    } else {
+		// Other process running
+		return false;
+	    }
+	}
+
+	// File could be created, write my pid in there
+	char buf[20];
+	sprintf(buf, "%d\n", getpid());
+	if (write(fd, buf, strlen(buf)+1) != int(strlen(buf)+1)) {
+	    LOGERR(("processlock: cant write to %s, errno %d\n",
+		    pidfile.c_str(), errno));
+	    close(fd);
+	    return false;
+	}
+	close(fd);
+	// Ok
+	break;
+    }
+    return true;
+}
+
+static void processunlock()
+{
+    unlink(pidfile.c_str());
+}
+
 pthread_t rcv_thrid;
-void *rcv_result;
-extern void *rclMonRcvRun(void *);
 
 bool startMonitor(RclConfig *conf, bool nofork)
 {
+    if (!processlock(conf->getConfDir())) {
+	LOGERR(("startMonitor: lock error. Other process running ?\n"));
+	return false;
+    }
+    atexit(processunlock);
+
     rclEQ.setConfig(conf);
     if (pthread_create(&rcv_thrid, 0, &rclMonRcvRun, &rclEQ) != 0) {
-	LOGERR(("start_monitoring: cant create event-receiving thread\n"));
+	LOGERR(("startMonitor: cant create event-receiving thread\n"));
 	return false;
     }