#include "autoconfig.h"
#ifdef RCL_MONITOR
#ifndef lint
static char rcsid[] = "@(#$Id: rclmonprc.cpp,v 1.2 2006-10-17 14:41:59 dockes Exp $ (C) 2006 J.F.Dockes";
#endif
/*
* 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.
*/
/**
* Recoll real time monitor processing. This file has the code to retrieve
* event from the event queue and do the database-side processing, and the
* initialization function.
*/
#include <pthread.h>
#include "debuglog.h"
#include "rclmon.h"
#include "debuglog.h"
#include "indexer.h"
typedef map<string, RclMonEvent> queue_type;
class RclEQData {
public:
queue_type m_queue;
RclConfig *m_config;
bool m_ok;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
RclEQData()
: m_config(0), m_ok(false)
{
if (!pthread_mutex_init(&m_mutex, 0) && !pthread_cond_init(&m_cond, 0))
m_ok = true;
}
};
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();
}
RclMonEvent RclMonEventQueue::pop()
{
RclMonEvent ev;
if (!empty()) {
ev = m_data->m_queue.begin()->second;
m_data->m_queue.erase(m_data->m_queue.begin());
}
return ev;
}
/** Wait until there is something to process on the queue.
* Must be called with the queue locked
*/
bool RclMonEventQueue::wait()
{
if (!empty())
return true;
if (pthread_cond_wait(&m_data->m_cond, &m_data->m_mutex)) {
LOGERR(("RclMonEventQueue::wait: pthread_cond_wait failed\n"));
return false;
}
return true;
}
bool RclMonEventQueue::lock()
{
if (pthread_mutex_lock(&m_data->m_mutex)) {
LOGERR(("RclMonEventQueue::lock: pthread_mutex_lock failed\n"));
return false;
}
return true;
}
bool RclMonEventQueue::unlock()
{
if (pthread_mutex_unlock(&m_data->m_mutex)) {
LOGERR(("RclMonEventQueue::lock: pthread_mutex_unlock failed\n"));
return false;
}
return true;
}
void RclMonEventQueue::setConfig(RclConfig *cnf)
{
m_data->m_config = cnf;
}
RclConfig *RclMonEventQueue::getConfig()
{
return m_data->m_config;
}
bool RclMonEventQueue::ok()
{
if (m_data == 0)
return false;
return m_data->m_ok;
}
void RclMonEventQueue::setTerminate()
{
lock();
m_data->m_ok = false;
pthread_cond_broadcast(&m_data->m_cond);
unlock();
}
bool RclMonEventQueue::pushEvent(const RclMonEvent &ev)
{
LOGDEB2(("RclMonEventQueue::pushEvent for %s\n", ev.m_path.c_str()));
lock();
// It seems that a newer event always override any older. TBVerified ?
m_data->m_queue[ev.m_path] = ev;
pthread_cond_broadcast(&m_data->m_cond);
unlock();
return true;
}
pthread_t rcv_thrid;
void *rcv_result;
extern void *rclMonRcvRun(void *);
extern int stopindexing;
bool startMonitor(RclConfig *conf, bool nofork)
{
rclEQ.setConfig(conf);
if (pthread_create(&rcv_thrid, 0, &rclMonRcvRun, &rclEQ) != 0) {
LOGERR(("start_monitoring: cant create event-receiving thread\n"));
return false;
}
if (!rclEQ.lock()) {
return false;
}
LOGDEB(("start_monitoring: entering main loop\n"));
while (rclEQ.wait()) {
LOGDEB2(("startMonitor: wait returned\n"));
if (stopindexing || !rclEQ.ok())
break;
list<string> modified;
list<string> deleted;
// Process event queue
while (!rclEQ.empty()) {
// Retrieve event
RclMonEvent ev = rclEQ.pop();
switch (ev.m_etyp) {
case RclMonEvent::RCLEVT_MODIFY:
LOGDEB(("Monitor: Modify/Check on %s\n", ev.m_path.c_str()));
modified.push_back(ev.m_path);
break;
case RclMonEvent::RCLEVT_DELETE:
LOGDEB(("Monitor: Delete on %s\n", ev.m_path.c_str()));
deleted.push_back(ev.m_path);
break;
case RclMonEvent::RCLEVT_RENAME:
LOGDEB(("Monitor: Rename on %s\n", ev.m_path.c_str()));
break;
default:
LOGDEB(("Monitor: got Other on %s\n", ev.m_path.c_str()));
}
}
// Unlock queue before processing lists
rclEQ.unlock();
// Process
indexfiles(conf, modified);
// Lock queue before waiting again
rclEQ.lock();
}
LOGERR(("start_monitoring: rclEQ::wait() failed\n"));
return false;
}
#endif // RCL_MONITOR