Switch to side-by-side view

--- a/src/rcldb/rcldb.cpp
+++ b/src/rcldb/rcldb.cpp
@@ -91,7 +91,7 @@
     return uniterm;
 }
 // Compute parent term used to link documents to their parent document (if any)
-// "" + parent external udi
+// "F" + parent external udi
 static inline string make_parentterm(const string& udi)
 {
     // I prefer to be in possible conflict with omega than with
@@ -112,17 +112,15 @@
     string pterm = make_parentterm(udi);
     for (int tries = 0; tries < 2; tries++) {
 	try {
-	    Xapian::PostingIterator it = db.postlist_begin(pterm);
-	    for (; it != db.postlist_end(pterm); it++) {
+	    Xapian::PostingIterator it = xrdb.postlist_begin(pterm);
+	    for (; it != xrdb.postlist_end(pterm); it++) {
 		docids.push_back(*it);
 	    }
 	    LOGDEB(("Db::Native::subDocs: returning %d ids\n", docids.size()));
 	    return true;
 	} catch (const Xapian::DatabaseModifiedError &e) {
 	    LOGDEB(("Db::subDocs: got modified error. reopen/retry\n"));
-	    // Can't use reOpen() here, I'm a Native:: method, this
-	    // would delete my own object
-	    db = Xapian::Database(m_db->m_basedir);
+	    xrdb.reopen();
 	} XCATCHERROR(ermsg);
 	if (!ermsg.empty()) 
 	    break;
@@ -179,6 +177,7 @@
     return true;
 }
 
+// Remove prefixes (caps) from a list of terms.
 static list<string> noPrefixList(const list<string>& in) 
 {
     list<string> out;
@@ -198,7 +197,7 @@
     return out;
 }
 
-    //#define DEBUGABSTRACT  1
+//#define DEBUGABSTRACT  1
 #ifdef DEBUGABSTRACT
 #define LOGABS LOGDEB
 #else
@@ -211,7 +210,7 @@
 {
     Chrono chron;
     LOGDEB(("makeAbstract:%d: maxlen %d wWidth %d\n", chron.ms(),
-	     m_db->m_synthAbsLen, m_db->m_synthAbsWordCtxLen));
+	     m_rcldb->m_synthAbsLen, m_rcldb->m_synthAbsWordCtxLen));
 
     list<string> iterms;
     query->getQueryTerms(iterms);
@@ -223,11 +222,11 @@
 
     // Retrieve db-wide frequencies for the query terms
     if (query->m_nq->termfreqs.empty()) {
-	double doccnt = db.get_doccount();
+	double doccnt = xrdb.get_doccount();
 	if (doccnt == 0) doccnt = 1;
 	for (list<string>::const_iterator qit = terms.begin(); 
 	     qit != terms.end(); qit++) {
-	    query->m_nq->termfreqs[*qit] = db.get_termfreq(*qit) / doccnt;
+	    query->m_nq->termfreqs[*qit] = xrdb.get_termfreq(*qit) / doccnt;
 	    LOGABS(("makeAbstract: [%s] db freq %.1e\n", qit->c_str(), 
 		    query->m_nq->termfreqs[*qit]));
 	}
@@ -240,13 +239,13 @@
     // and show text around the less common search terms.
     map<string, double> termQcoefs;
     double totalweight = 0;
-    double doclen = db.get_doclength(docid);
+    double doclen = xrdb.get_doclength(docid);
     if (doclen == 0) doclen = 1;
     for (list<string>::const_iterator qit = terms.begin(); 
 	 qit != terms.end(); qit++) {
-	Xapian::TermIterator term = db.termlist_begin(docid);
+	Xapian::TermIterator term = xrdb.termlist_begin(docid);
 	term.skip_to(*qit);
-	if (term != db.termlist_end(docid) && *term == *qit) {
+	if (term != xrdb.termlist_end(docid) && *term == *qit) {
 	    double q = (term.get_wdf() / doclen) * query->m_nq->termfreqs[*qit];
 	    q = -log10(q);
 	    if (q < 3) {
@@ -300,7 +299,7 @@
     // with words. We used to limit the character size at the end, but
     // this damaged our careful selection of terms
     const unsigned int maxtotaloccs = 
-	m_db->m_synthAbsLen /(7 * (m_db->m_synthAbsWordCtxLen+1));
+	m_rcldb->m_synthAbsLen /(7 * (m_rcldb->m_synthAbsWordCtxLen+1));
     LOGABS(("makeAbstract:%d: mxttloccs %d\n", chron.ms(), maxtotaloccs));
     // This can't happen, but would crash us
     if (totalweight == 0.0) {
@@ -336,8 +335,8 @@
 	string emptys;
 	try {
 	    unsigned int occurrences = 0;
-	    for (pos = db.positionlist_begin(docid, qterm); 
-		 pos != db.positionlist_end(docid, qterm); pos++) {
+	    for (pos = xrdb.positionlist_begin(docid, qterm); 
+		 pos != xrdb.positionlist_end(docid, qterm); pos++) {
 		int ipos = *pos;
 		if (ipos < int(baseTextPosition)) // Not in text body
 		    continue;
@@ -350,9 +349,9 @@
 		// step by inserting empty strings. Special provisions
 		// for adding ellipsis and for positions overlapped by
 		// the match term.
-		unsigned int sta = MAX(0, ipos-m_db->m_synthAbsWordCtxLen);
+		unsigned int sta = MAX(0, ipos-m_rcldb->m_synthAbsWordCtxLen);
 		unsigned int sto = ipos + qtrmwrdcnt-1 + 
-		    m_db->m_synthAbsWordCtxLen;
+		    m_rcldb->m_synthAbsWordCtxLen;
 		for (unsigned int ii = sta; ii <= sto;  ii++) {
 		    if (ii == (unsigned int)ipos) {
 			sparseDoc[ii] = qterm;
@@ -402,8 +401,8 @@
 	Xapian::TermIterator term;
 	int cutoff = 500 * 1000;
 
-	for (term = db.termlist_begin(docid);
-	     term != db.termlist_end(docid); term++) {
+	for (term = xrdb.termlist_begin(docid);
+	     term != xrdb.termlist_end(docid); term++) {
 	    // Ignore prefixed terms
 	    if ('A' <= (*term).at(0) && (*term).at(0) <= 'Z')
 		continue;
@@ -413,8 +412,8 @@
 	    }
 
 	    Xapian::PositionIterator pos;
-	    for (pos = db.positionlist_begin(docid, *term); 
-		 pos != db.positionlist_end(docid, *term); pos++) {
+	    for (pos = xrdb.positionlist_begin(docid, *term); 
+		 pos != xrdb.positionlist_end(docid, *term); pos++) {
 		if (cutoff-- < 0) {
 		    LOGDEB(("makeAbstract: max term count cutoff\n"));
 		    break;
@@ -503,7 +502,7 @@
     LOGDEB2(("Db::~Db\n"));
     if (m_ndb == 0)
 	return;
-    LOGDEB(("Db::~Db: isopen %d m_iswritable %d\n", m_ndb->m_isopen, 
+    LOGDEB(("Db::~Db: isopen %d m_iswritable %d\n", m_ndb->m_isopen,
 	    m_ndb->m_iswritable));
     i_close(true);
 }
@@ -540,19 +539,19 @@
 	    {
 		int action = (mode == DbUpd) ? Xapian::DB_CREATE_OR_OPEN :
 		    Xapian::DB_CREATE_OR_OVERWRITE;
-		m_ndb->wdb = Xapian::WritableDatabase(dir, action);
+		m_ndb->xwdb = Xapian::WritableDatabase(dir, action);
 		m_ndb->m_iswritable = true;
 		// We open a readonly object in all cases (possibly in
 		// addition to the r/w one) because some operations
 		// are faster when performed through a Database: no
 		// forced flushes on allterms_begin(), ie, used in
 		// subDocs()
-		m_ndb->db = Xapian::Database(dir);
+		m_ndb->xrdb = Xapian::Database(dir);
 		LOGDEB(("Db::open: lastdocid: %d\n", 
-			m_ndb->wdb.get_lastdocid()));
+			m_ndb->xwdb.get_lastdocid()));
 		if (!keep_updated) {
 		    LOGDEB2(("Db::open: resetting updated\n"));
-		    updated.resize(m_ndb->wdb.get_lastdocid() + 1);
+		    updated.resize(m_ndb->xwdb.get_lastdocid() + 1);
 		    for (unsigned int i = 0; i < updated.size(); i++)
 			updated[i] = false;
 		}
@@ -561,7 +560,7 @@
 	case DbRO:
 	default:
 	    m_ndb->m_iswritable = false;
-	    m_ndb->db = Xapian::Database(dir);
+	    m_ndb->xrdb = Xapian::Database(dir);
 	    for (list<string>::iterator it = m_extraDbs.begin();
 		 it != m_extraDbs.end(); it++) {
 		string aerr;
@@ -569,7 +568,7 @@
 		aerr.erase();
 		try {
 		    // Make this non-fatal
-		    m_ndb->db.add_database(Xapian::Database(*it));
+		    m_ndb->xrdb.add_database(Xapian::Database(*it));
 		} XCATCHERROR(aerr);
 		if (!aerr.empty())
 		    LOGERR(("Db::Open: error while trying to add database "
@@ -579,9 +578,8 @@
 	}
 	// Check index format version. Must not try to check a just created or
 	// truncated db
-	if (mode != DbTrunc && m_ndb->db.get_doccount()>0) {
-	    Xapian::Database cdb = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
-	    string version = cdb.get_metadata(RCL_IDX_VERSION_KEY);
+	if (mode != DbTrunc && m_ndb->xdb().get_doccount() > 0) {
+	    string version = m_ndb->xdb().get_metadata(RCL_IDX_VERSION_KEY);
 	    if (version.compare(RCL_IDX_VERSION)) {
 		m_ndb->m_noversionwrite = true;
 		LOGERR(("Rcl::Db::open: file index [%s], software [%s]\n",
@@ -606,7 +604,6 @@
     LOGDEB2(("Db::close()\n"));
     return i_close(false);
 }
-
 bool Db::i_close(bool final)
 {
     if (m_ndb == 0)
@@ -621,7 +618,7 @@
 	bool w = m_ndb->m_iswritable;
 	if (w) {
 	    if (!m_ndb->m_noversionwrite)
-		m_ndb->wdb.set_metadata(RCL_IDX_VERSION_KEY, RCL_IDX_VERSION);
+		m_ndb->xwdb.set_metadata(RCL_IDX_VERSION_KEY, RCL_IDX_VERSION);
 	    LOGDEB(("Rcl::Db:close: xapian will close. May take some time\n"));
 	}
 	// Used to do a flush here. Cant see why it should be necessary.
@@ -642,7 +639,8 @@
     return false;
 }
 
-bool Db::reOpen()
+// Reopen the db with a changed list of additional dbs
+bool Db::adjustdbs()
 {
     if (m_ndb && m_ndb->m_isopen) {
 	if (!close())
@@ -660,13 +658,14 @@
     string ermsg;
     if (m_ndb && m_ndb->m_isopen) {
 	try {
-	    res = m_ndb->m_iswritable ? m_ndb->wdb.get_doccount() : 
-		m_ndb->db.get_doccount();
+	    res = m_ndb->xdb().get_doccount();
 	} catch (const Xapian::DatabaseModifiedError &e) {
 	    LOGDEB(("Db::docCnt: got modified error. reopen/retry\n"));
-	    reOpen();
-	    res = m_ndb->m_iswritable ? m_ndb->wdb.get_doccount() : 
-		m_ndb->db.get_doccount();
+            // Doesn't make sense if we are the writer !
+            if (m_ndb->m_iswritable)
+                return -1;
+	    m_ndb->xdb().reopen();
+	    res = m_ndb->xdb().get_doccount();
 	} XCATCHERROR(ermsg);
 	if (!ermsg.empty())
 	    LOGERR(("Db::docCnt: got error: %s\n", ermsg.c_str()));
@@ -685,7 +684,7 @@
     if (find(m_extraDbs.begin(), m_extraDbs.end(), dir) == m_extraDbs.end()) {
 	m_extraDbs.push_back(dir);
     }
-    return reOpen();
+    return adjustdbs();
 }
 
 bool Db::rmQueryDb(const string &dir)
@@ -703,7 +702,7 @@
 	    m_extraDbs.erase(it);
 	}
     }
-    return reOpen();
+    return adjustdbs();
 }
 
 bool Db::testDbDir(const string &dir)
@@ -1069,7 +1068,7 @@
     // Add db entry or update existing entry:
     try {
 	Xapian::docid did = 
-	    m_ndb->wdb.replace_document(uniterm, newdocument);
+	    m_ndb->xwdb.replace_document(uniterm, newdocument);
 	if (did < updated.size()) {
 	    updated[did] = true;
 	    LOGDEB(("Db::add: docid %d updated [%s]\n", did, fnc));
@@ -1083,7 +1082,7 @@
 	ermsg.erase();
 	// FIXME: is this ever actually needed?
 	try {
-	    m_ndb->wdb.add_document(newdocument);
+	    m_ndb->xwdb.add_document(newdocument);
 	    LOGDEB(("Db::add: %s added (failed re-seek for duplicate)\n", 
 		    fnc));
 	} XCATCHERROR(ermsg);
@@ -1100,7 +1099,7 @@
 	    ermsg.erase();
 	    LOGDEB(("Db::add: text size >= %d Mb, flushing\n", m_flushMb));
 	    try {
-		m_ndb->wdb.flush();
+		m_ndb->xwdb.flush();
 	    } XCATCHERROR(ermsg);
 	    if (!ermsg.empty()) {
 		LOGERR(("Db::add: flush() failed: %s\n", ermsg.c_str()));
@@ -1131,13 +1130,13 @@
     for (int tries = 0; tries < 2; tries++) {
 	try {
 	    // Get the doc or pseudo-doc
-	    Xapian::PostingIterator docid = m_ndb->db.postlist_begin(uniterm);
-	    if (docid == m_ndb->db.postlist_end(uniterm)) {
+	    Xapian::PostingIterator docid =m_ndb->xrdb.postlist_begin(uniterm);
+	    if (docid == m_ndb->xrdb.postlist_end(uniterm)) {
 		// If no document exist with this path, we do need update
 		LOGDEB(("Db::needUpdate: no path: [%s]\n", uniterm.c_str()));
 		return true;
 	    }
-	    Xapian::Document doc = m_ndb->db.get_document(*docid);
+	    Xapian::Document doc = m_ndb->xrdb.get_document(*docid);
 
 	    // Retrieve old file/doc signature from value
 	    string osig = doc.get_value(VALUE_SIG);
@@ -1174,7 +1173,7 @@
 	    return false;
 	} catch (const Xapian::DatabaseModifiedError &e) {
 	    LOGDEB(("Db::needUpdate: got modified error. reopen/retry\n"));
-	    reOpen();
+	    m_ndb->xdb().reopen();
 	} XCATCHERROR(ermsg);
 	if (!ermsg.empty())
 	    break;
@@ -1219,8 +1218,7 @@
     if (m_ndb == 0 || m_ndb->m_isopen == false)
 	return false;
 
-    return StemDb::createDb(m_ndb->m_iswritable ? m_ndb->wdb : m_ndb->db, 
-			     m_basedir, lang);
+    return StemDb::createDb(m_ndb->xdb(), m_basedir, lang);
 }
 
 /**
@@ -1246,7 +1244,7 @@
     // that any added document would go to the index. Kept here
     // because it doesn't really hurt.
     try {
-	m_ndb->wdb.flush();
+	m_ndb->xwdb.flush();
     } catch (...) {
 	LOGERR(("Db::purge: 1st flush failed\n"));
 
@@ -1257,7 +1255,7 @@
     for (Xapian::docid docid = 1; docid < updated.size(); ++docid) {
 	if (!updated[docid]) {
 	    try {
-		m_ndb->wdb.delete_document(docid);
+		m_ndb->xwdb.delete_document(docid);
 		LOGDEB(("Db::purge: deleted document #%d\n", docid));
 	    } catch (const Xapian::DocNotFoundError &) {
 		LOGDEB0(("Db::purge: document #%d not found\n", docid));
@@ -1270,7 +1268,7 @@
     }
 
     try {
-	m_ndb->wdb.flush();
+	m_ndb->xwdb.flush();
     } catch (...) {
 	LOGERR(("Db::purge: 2nd flush failed\n"));
     }
@@ -1281,9 +1279,9 @@
 bool Db::purgeFile(const string &udi)
 {
     LOGDEB(("Db:purgeFile: [%s]\n", udi.c_str()));
-    if (m_ndb == 0)
-	return false;
-    Xapian::WritableDatabase db = m_ndb->wdb;
+    if (m_ndb == 0 || !m_ndb->m_iswritable)
+	return false;
+    Xapian::WritableDatabase db = m_ndb->xwdb;
     string uniterm = make_uniterm(udi);
     string ermsg;
     try {
@@ -1395,7 +1393,7 @@
 {
     if (!m_ndb || !m_ndb->m_isopen)
 	return false;
-    Xapian::Database db = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
+    Xapian::Database db = m_ndb->xdb();
 
     res.clear();
 
@@ -1509,7 +1507,7 @@
 	return 0;
     TermIter *tit = new TermIter;
     if (tit) {
-	tit->db = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
+	tit->db = m_ndb->xdb();
 	string ermsg;
 	try {
 	    tit->it = tit->db.allterms_begin();
@@ -1546,10 +1544,9 @@
 {
     if (!m_ndb || !m_ndb->m_isopen)
 	return 0;
-    Xapian::Database db = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
     string ermsg;
     try {
-	if (!db.term_exists(word))
+	if (!m_ndb->xdb().term_exists(word))
 	    return false;
     } XCATCHERROR(ermsg);
     if (!ermsg.empty()) {
@@ -1589,7 +1586,7 @@
         } catch (const Xapian::DatabaseModifiedError &error) {
             LOGDEB(("Db:makeDocAbstract: caught DatabaseModified\n"));
             m_reason = error.get_msg();
-            reOpen();
+            m_ndb->xdb().reopen();
         } catch (const Xapian::Error & error) {
             LOGERR(("Db::makeDocAbstract: exception: %s\n", 
                     error.get_msg().c_str()));
@@ -1614,7 +1611,7 @@
     string uniterm = make_uniterm(udi);
     string ermsg;
     try {
-	if (!m_ndb->db.term_exists(uniterm)) {
+	if (!m_ndb->xrdb.term_exists(uniterm)) {
 	    // Document found in history no longer in the database.
 	    // We return true (because their might be other ok docs further)
 	    // but indicate the error with pc = -1
@@ -1623,8 +1620,8 @@
 		     uniterm.c_str(), uniterm.length()));
 	    return true;
 	}
-	Xapian::PostingIterator docid = m_ndb->db.postlist_begin(uniterm);
-	Xapian::Document xdoc = m_ndb->db.get_document(*docid);
+	Xapian::PostingIterator docid = m_ndb->xrdb.postlist_begin(uniterm);
+	Xapian::Document xdoc = m_ndb->xrdb.get_document(*docid);
 	string data = xdoc.get_data();
 	return m_ndb->dbDataToRclDoc(*docid, data, doc, 100);
     } XCATCHERROR(ermsg);