Switch to side-by-side view

--- a/src/index/recollindex.cpp
+++ b/src/index/recollindex.cpp
@@ -1,5 +1,5 @@
 #ifndef lint
-static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.6 2005-01-26 13:03:02 dockes Exp $ (C) 2004 J.F.Dockes";
+static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.7 2005-01-29 15:41:11 dockes Exp $ (C) 2004 J.F.Dockes";
 #endif
 
 #include <sys/stat.h>
@@ -7,6 +7,8 @@
 #include <strings.h>
 
 #include <iostream>
+#include <list>
+#include <map>
 
 #include "pathut.h"
 #include "conftree.h"
@@ -30,39 +32,51 @@
 class DirIndexer {
     FsTreeWalker walker;
     RclConfig *config;
-    string topdir;
+    list<string> *topdirs;
     string dbdir;
     Rcl::Db db;
  public:
-    DirIndexer(RclConfig *cnf, const string &dbd, const string &top) 
-	: config(cnf), topdir(top), dbdir(dbd)
+    DirIndexer(RclConfig *cnf, const string &dbd, list<string> *top) 
+	: config(cnf), topdirs(top), dbdir(dbd)
     { }
 
     friend FsTreeWalker::Status 
       indexfile(void *, const std::string &, const struct stat *, 
 		FsTreeWalker::CbFlag);
 
-    void index();
+    bool index();
 };
 
-void DirIndexer::index()
+bool DirIndexer::index()
 {
     if (!db.open(dbdir, Rcl::Db::DbUpd)) {
-	cerr << "Error opening database in " << dbdir << " for " <<
-	    topdir << endl;
-	return;
-    }
-    walker.walk(topdir, indexfile, this);
+	LOGERR(("DirIndexer::index: error opening database in %s\n", 
+		dbdir.c_str()));
+	return false;
+    }
+    for (list<string>::const_iterator it = topdirs->begin();
+	 it != topdirs->end(); it++) {
+	LOGDEB(("DirIndexer::index: Indexing %s into %s\n", it->c_str(), 
+		dbdir.c_str()));
+	if (walker.walk(*it, indexfile, this) != FsTreeWalker::FtwOk) {
+	    LOGERR(("DirIndexer::index: error while indexing %s\n", 
+		    it->c_str()));
+	    db.close();
+	    return false;
+	}
+    }
+    db.purge();
     if (!db.close()) {
-	cerr << "Error closing database in " << dbdir << " for " <<
-	    topdir << endl;
-	return;
-    }
+	LOGERR(("DirIndexer::index: error closing database in %s\n", 
+		dbdir.c_str()));
+	return false;
+    }
+    return true;
 }
 
 /** 
  * This function gets called for every file and directory found by the
- * tree walker. It checks with the db is the file has changed and needs to
+ * tree walker. It checks with the db if the file has changed and needs to
  * be reindexed. If so, it calls an appropriate handler depending on the mime
  * type, which is responsible for populating an Rcl::Doc.
  * Accent and majuscule handling are performed by the db module when doing
@@ -119,34 +133,89 @@
     return FsTreeWalker::FtwOk;
 }
 
+DirIndexer *indexer;
+
+static void cleanup()
+{
+    delete indexer;
+    indexer = 0;
+}
+
+static void sigcleanup(int sig)
+{
+    fprintf(stderr, "sigcleanup\n");
+    cleanup();
+    exit(1);
+}
 
 int main(int argc, const char **argv)
 {
-    RclConfig *config = new RclConfig;
-
-    if (!config->ok())
+    atexit(cleanup);
+    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+	signal(SIGHUP, sigcleanup);
+    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+	signal(SIGINT, sigcleanup);
+    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+	signal(SIGQUIT, sigcleanup);
+    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+	signal(SIGTERM, sigcleanup);
+
+    RclConfig config;
+    if (!config.ok())
 	cerr << "Config could not be built" << endl;
 
-    ConfTree *conf = config->getConfig();
-    
+    ConfTree *conf = config.getConfig();
+
+    // Retrieve the list of directories to be indexed.
     string topdirs;
     if (conf->get("topdirs", topdirs, "") == 0) {
 	cerr << "No top directories in configuration" << endl;
 	exit(1);
     }
-    vector<string> tdl;
-    if (ConfTree::stringToStrings(topdirs, tdl)) {
-	for (unsigned int i = 0; i < tdl.size(); i++) {
-	    string topdir = tdl[i];
-	    cout << topdir << endl;
-	    string dbdir;
-	    if (conf->get("dbdir", dbdir, topdir) == 0) {
-		cerr << "No database directory in configuration for " 
-		     << topdir << endl;
-		exit(1);
-	    }
-	    DirIndexer indexer(config, dbdir, topdir);
-	    indexer.index();
-	}
-    }
-}
+
+    // Group the directories by database: it is important that all
+    // directories for a database be indexed at once so that deleted
+    // file cleanup works 
+    vector<string> tdl; // List of directories to be indexed
+    if (!ConfTree::stringToStrings(topdirs, tdl)) {
+	cerr << "Parse error for directory list" << endl;
+	exit(1);
+    }
+
+    vector<string>::iterator dirit;
+    map<string, list<string> > dbmap;
+    map<string, list<string> >::iterator dbit;
+    for (dirit = tdl.begin(); dirit != tdl.end(); dirit++) {
+	string db;
+	if (conf->get("dbdir", db, *dirit) == 0) {
+	    cerr << "No database directory in configuration for " 
+		 << *dirit << endl;
+	    exit(1);
+	}
+	dbit = dbmap.find(db);
+	if (dbit == dbmap.end()) {
+	    list<string> l;
+	    l.push_back(*dirit);
+	    dbmap[db] = l;
+	} else {
+	    dbit->second.push_back(*dirit);
+	}
+    }
+
+    for (dbit = dbmap.begin(); dbit != dbmap.end(); dbit++) {
+	cout << dbit->first << " -> ";
+	list<string>::const_iterator dit;
+	for (dit = dbit->second.begin(); dit != dbit->second.end(); dit++) {
+	    cout << *dit << " ";
+	}
+	cout << endl;
+	indexer = new DirIndexer(&config, dbit->first, &dbit->second);
+	if (!indexer->index()) {
+	    delete indexer;
+	    indexer = 0;
+	    exit(1);
+	}
+	delete indexer;
+	indexer = 0;
+    }
+}