diff --git a/src/index/indexer.cpp b/src/index/indexer.cpp index ccf9eb94..94fdea23 100644 --- a/src/index/indexer.cpp +++ b/src/index/indexer.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: indexer.cpp,v 1.41 2006-10-24 14:28:38 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: indexer.cpp,v 1.42 2006-10-25 10:52:02 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -133,7 +133,7 @@ bool DbIndexer::indexDb(bool resetbefore, list *topdirs) } // Create stemming databases. We also remove those which are not -// configured. +// configured. bool DbIndexer::createStemmingDatabases() { string slangs; @@ -202,6 +202,12 @@ bool DbIndexer::createAspellDict() reason.c_str())); return false; } + // The close would be done in our destructor, but we want status here + if (!m_db.close()) { + LOGERR(("DbIndexer::indexfiles: error closing database in %s\n", + m_dbdir.c_str())); + return false; + } #endif return true; } diff --git a/src/index/rclmon.h b/src/index/rclmon.h index 8072bc25..2698ddba 100644 --- a/src/index/rclmon.h +++ b/src/index/rclmon.h @@ -2,7 +2,7 @@ #define _RCLMON_H_INCLUDED_ #include "autoconfig.h" #ifdef RCL_MONITOR -/* @(#$Id: rclmon.h,v 1.5 2006-10-24 14:28:38 dockes Exp $ (C) 2006 J.F.Dockes */ +/* @(#$Id: rclmon.h,v 1.6 2006-10-25 10:52:02 dockes Exp $ (C) 2006 J.F.Dockes */ /** * Definitions for the real-time monitoring recoll. * We're interested in file modifications, deletions and renaming. @@ -30,7 +30,7 @@ using std::multimap; class RclMonEvent { public: enum EvType {RCLEVT_NONE, RCLEVT_MODIFY, RCLEVT_DELETE, - RCLEVT_DIRCREATE, RCLEVT_RENAME}; + RCLEVT_DIRCREATE}; string m_path; string m_opath; EvType m_etyp; diff --git a/src/index/rclmonprc.cpp b/src/index/rclmonprc.cpp index 07247ed0..98a40b3b 100644 --- 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.5 2006-10-24 14:28:38 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rclmonprc.cpp,v 1.6 2006-10-25 10:52:02 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -76,6 +76,7 @@ bool RclMonEventQueue::empty() return m_data == 0 ? true : m_data->m_queue.empty(); } +// Must be called with the queue locked RclMonEvent RclMonEventQueue::pop() { RclMonEvent ev; @@ -91,8 +92,11 @@ RclMonEvent RclMonEventQueue::pop() */ bool RclMonEventQueue::wait(int seconds, bool *top) { - if (!empty()) + LOGDEB(("RclMonEventQueue::wait\n")); + if (!empty()) { + LOGDEB(("RclMonEventQueue:: imm return\n")); return true; + } int err; if (seconds > 0) { @@ -105,6 +109,7 @@ bool RclMonEventQueue::wait(int seconds, bool *top) pthread_cond_timedwait(&m_data->m_cond, &m_data->m_mutex, &to))) { if (err == ETIMEDOUT) { *top = true; + LOGDEB(("RclMonEventQueue:: timeout\n")); return true; } LOGERR(("RclMonEventQueue::wait:pthread_cond_timedwait failed" @@ -118,19 +123,23 @@ bool RclMonEventQueue::wait(int seconds, bool *top) return false; } } + LOGDEB(("RclMonEventQueue:: normal return\n")); return true; } bool RclMonEventQueue::lock() { + LOGDEB(("RclMonEventQueue:: lock\n")); if (pthread_mutex_lock(&m_data->m_mutex)) { LOGERR(("RclMonEventQueue::lock: pthread_mutex_lock failed\n")); return false; } + LOGDEB(("RclMonEventQueue:: lock return\n")); return true; } bool RclMonEventQueue::unlock() { + LOGDEB(("RclMonEventQueue:: unlock\n")); if (pthread_mutex_unlock(&m_data->m_mutex)) { LOGERR(("RclMonEventQueue::lock: pthread_mutex_unlock failed\n")); return false; @@ -159,6 +168,7 @@ bool RclMonEventQueue::ok() void RclMonEventQueue::setTerminate() { + LOGDEB(("RclMonEventQueue:: setTerminate\n")); lock(); m_data->m_ok = false; pthread_cond_broadcast(&m_data->m_cond); @@ -167,7 +177,7 @@ void RclMonEventQueue::setTerminate() bool RclMonEventQueue::pushEvent(const RclMonEvent &ev) { - LOGDEB2(("RclMonEventQueue::pushEvent for %s\n", ev.m_path.c_str())); + LOGDEB(("RclMonEventQueue::pushEvent for %s\n", ev.m_path.c_str())); lock(); // It seems that a newer event is always correct to override any // older. TBVerified ? @@ -268,7 +278,8 @@ bool startMonitor(RclConfig *conf, bool nofork) // indexing activity since the last such operation, we'll update the // auxiliary data (stemming and spelling) while (rclEQ.wait(10 * 60, &timedout)) { - LOGDEB2(("startMonitor: wait returned\n")); + // Queue is locked. + if (!rclEQ.ok()) break; list modified; @@ -287,15 +298,13 @@ bool startMonitor(RclConfig *conf, bool nofork) 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 if (!modified.empty()) { if (!indexfiles(conf, modified)) @@ -309,7 +318,7 @@ bool startMonitor(RclConfig *conf, bool nofork) } if (timedout) { - LOGDEB2(("Monitor: queue wait timed out\n")); + LOGDEB(("Monitor: queue wait timed out\n")); // Timed out. there must not be much activity around here. // If anything was modified, process the end-of-indexing // tasks: stemming and spelling database creations. @@ -323,6 +332,7 @@ bool startMonitor(RclConfig *conf, bool nofork) // Lock queue before waiting again rclEQ.lock(); } + LOGDEB(("Monitor: returning\n")); return true; } #endif // RCL_MONITOR diff --git a/src/index/rclmonrcv.cpp b/src/index/rclmonrcv.cpp index 322a0eb3..4f4dfece 100644 --- a/src/index/rclmonrcv.cpp +++ b/src/index/rclmonrcv.cpp @@ -1,7 +1,7 @@ #include "autoconfig.h" #ifdef RCL_MONITOR #ifndef lint -static char rcsid[] = "@(#$Id: rclmonrcv.cpp,v 1.6 2006-10-24 09:09:36 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rclmonrcv.cpp,v 1.7 2006-10-25 10:52:02 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -68,14 +68,17 @@ public: { LOGDEB2(("rclMonRcvRun: processone %s m_mon %p m_mon->ok %d\n", fn.c_str(), m_mon, m_mon?m_mon->ok():0)); - // Create watch when entering directory + if (flg == FsTreeWalker::FtwDirEnter) { - // Empty whatever events we may already have on queue + // Create watch when entering directory, but first empty + // whatever events we may already have on queue while (m_queue->ok() && m_mon->ok()) { RclMonEvent ev; if (m_mon->getEvent(ev, 0)) { - m_queue->pushEvent(ev); + if (ev.m_etyp != RclMonEvent::RCLEVT_NONE) + m_queue->pushEvent(ev); } else { + LOGDEB(("rclMonRcvRun: no event pending\n")); break; } } @@ -135,29 +138,24 @@ void *rclMonRcvRun(void *q) } // Forever wait for monitoring events and add them to queue: - LOGDEB2(("rclMonRcvRun: waiting for events. queue->ok() %d\n", queue->ok())); + LOGDEB2(("rclMonRcvRun: waiting for events. q->ok() %d\n", queue->ok())); while (queue->ok() && mon->ok()) { RclMonEvent ev; - // Note: under Linux, I could find no way to get the select + // Note: I could find no way to get the select // call to return when a signal is delivered to the process // (it goes to the main thread, from which I tried to close or - // write to the select fd, with no effect. So set a + // write to the select fd, with no effect). So set a // timeout so that an intr will be detected - if (mon->getEvent(ev, -#ifdef linux - 2 -#else - -1 -#endif - )) { + if (mon->getEvent(ev, 2)) { if (ev.m_etyp == RclMonEvent::RCLEVT_DIRCREATE) { mon->addWatch(ev.m_path, true); } - queue->pushEvent(ev); + if (ev.m_etyp != RclMonEvent::RCLEVT_NONE) + queue->pushEvent(ev); } } - LOGDEB(("rclMonRcvRun: exiting\n")); + LOGINFO(("rclMonRcvRun: exiting\n")); queue->setTerminate(); return 0; } @@ -252,6 +250,8 @@ bool RclFAM::addWatch(const string& path, bool isdir) return true; } +// Note: return false only for queue empty or error +// Return EVT_NONE for bad event to keep queue processing going bool RclFAM::getEvent(RclMonEvent& ev, int secs) { if (!ok()) @@ -263,31 +263,36 @@ bool RclFAM::getEvent(RclMonEvent& ev, int secs) FD_ZERO(&readfds); FD_SET(fam_fd, &readfds); - LOGDEB2(("RclFAM::getEvent: select\n")); + LOGDEB(("RclFAM::getEvent: select\n")); struct timeval timeout; if (secs >= 0) { memset(&timeout, 0, sizeof(timeout)); timeout.tv_sec = secs; } int ret; - if ((ret=select(fam_fd + 1, &readfds, 0, 0, secs >= 0 ? &timeout : 0)) < 0) { + if ((ret=select(fam_fd+1, &readfds, 0, 0, secs >= 0 ? &timeout : 0)) < 0) { LOGERR(("RclFAM::getEvent: select failed, errno %d\n", errno)); close(); return false; } else if (ret == 0) { // timeout + LOGDEB(("RclFAM::getEvent: select timeout\n")); return false; } + LOGDEB(("RclFAM::getEvent: select return\n")); + if (!FD_ISSET(fam_fd, &readfds)) return false; + LOGDEB(("RclFAM::getEvent: call FAMNextEvent\n")); FAMEvent fe; if (FAMNextEvent(&m_conn, &fe) < 0) { LOGERR(("RclFAM::getEvent: FAMNextEvent failed, errno %d\n", errno)); close(); return false; } + LOGDEB(("RclFAM::getEvent: FAMNextEvent returned\n")); map::const_iterator it; if ((fe.filename[0] != '/') && @@ -326,7 +331,11 @@ bool RclFAM::getEvent(RclMonEvent& ev, int secs) case FAMAcknowledge: case FAMEndExist: default: - return false; + // Have to return something, this is different from an empty queue, + // esp if we are trying to empty it... + LOGDEB(("RclFAM::getEvent: got move event !\n")); + ev.m_etyp = RclMonEvent::RCLEVT_NONE; + break; } return true; } @@ -432,10 +441,13 @@ bool RclIntf::addWatch(const string& path, bool) return true; } +// Note: return false only for queue empty or error +// Return EVT_NONE for bad event to keep queue processing going bool RclIntf::getEvent(RclMonEvent& ev, int secs) { if (!ok()) return false; + ev.m_etyp = RclMonEvent::RCLEVT_NONE; LOGDEB2(("RclIntf::getEvent:\n")); if (m_evp == 0) { @@ -483,7 +495,7 @@ bool RclIntf::getEvent(RclMonEvent& ev, int secs) map::const_iterator it; if ((it = m_wdtopath.find(evp->wd)) == m_wdtopath.end()) { LOGERR(("RclIntf::getEvent: unknown wd\n")); - return false; + return true; } ev.m_path = it->second; @@ -502,13 +514,13 @@ bool RclIntf::getEvent(RclMonEvent& ev, int secs) if (path_isdir(ev.m_path)) { ev.m_etyp = RclMonEvent::RCLEVT_DIRCREATE; } else { - // Will get modify event - return false; + // Return null event. Will get modify event later + return true; } } else { LOGDEB(("RclIntf::getEvent: unhandled event %s 0x%x %s\n", event_name(evp->mask), evp->mask, ev.m_path.c_str())); - return false; + return true; } return true; } diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index c43cd8ba..5bd7dcea 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.83 2006-10-24 09:28:30 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.84 2006-10-25 10:52:02 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -96,6 +96,8 @@ class Native { { } ~Native() { + if (m_iswritable) + LOGDEB(("Rcl::Db: xapian will close. Flush may take some time\n")); delete enquire; }