diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index 1b1a272d..5ed57706 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -108,25 +108,20 @@ static inline string make_parentterm(const string& udi) bool Db::Native::subDocs(const string &udi, vector& docids) { LOGDEB2(("subDocs: [%s]\n", uniterm.c_str())); - string ermsg; string pterm = make_parentterm(udi); - for (int tries = 0; tries < 2; tries++) { - try { - 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")); - xrdb.reopen(); - } XCATCHERROR(ermsg); - if (!ermsg.empty()) - break; + + XAPTRY(docids.clear(); + docids.insert(docids.begin(), xrdb.postlist_begin(pterm), + xrdb.postlist_end(pterm)), + xrdb, m_rcldb->m_reason); + + if (!m_rcldb->m_reason.empty()) { + LOGERR(("Rcl::Db::subDocs: %s\n", m_rcldb->m_reason.c_str())); + return false; + } else { + LOGDEB(("Db::Native::subDocs: returning %d ids\n", docids.size())); + return true; } - LOGERR(("Rcl::Db::subDocs: %s\n", ermsg.c_str())); - return false; } // Only ONE field name inside the index data record differs from the @@ -206,6 +201,9 @@ static list noPrefixList(const list& in) // Build a document abstract by extracting text chunks around the query terms // This uses the db termlists, not the original document. +// +// DatabaseModified and other general exceptions are catched and +// possibly retried by our caller string Db::Native::makeAbstract(Xapian::docid docid, Query *query) { Chrono chron; @@ -655,20 +653,14 @@ bool Db::adjustdbs() int Db::docCnt() { int res = -1; - string ermsg; - if (m_ndb && m_ndb->m_isopen) { - try { - res = m_ndb->xdb().get_doccount(); - } catch (const Xapian::DatabaseModifiedError &e) { - LOGDEB(("Db::docCnt: got modified error. reopen/retry\n")); - // 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())); + if (!m_ndb || !m_ndb->m_isopen) + return -1; + + XAPTRY(res = m_ndb->xdb().get_doccount(), m_ndb->xrdb, m_reason); + + if (!m_reason.empty()) { + LOGERR(("Db::docCnt: got error: %s\n", m_reason.c_str())); + return -1; } return res; } @@ -1125,15 +1117,14 @@ bool Db::needUpdate(const string &udi, const string& sig) // the actual document file, or, for a multi-document file, the // pseudo-doc we create to stand for the file itself. - // We try twice in case database needs to be reopened. (Ulterior - // note: this does not make sense as we are the sole writer!) + // We try twice in case database needs to be reopened. for (int tries = 0; tries < 2; tries++) { try { // Get the doc or pseudo-doc 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())); + LOGDEB(("Db::needUpdate:yes (new): [%s]\n", uniterm.c_str())); return true; } Xapian::Document doc = m_ndb->xrdb.get_document(*docid); @@ -1148,9 +1139,9 @@ bool Db::needUpdate(const string &udi, const string& sig) osig.c_str(), sig.c_str())); // Db is not up to date. Let's index the file return true; - } + } - LOGDEB(("Db::needUpdate: uptodate: [%s]\n", uniterm.c_str())); + LOGDEB(("Db::needUpdate:no: [%s]\n", uniterm.c_str())); // Up to date. @@ -1173,13 +1164,14 @@ bool Db::needUpdate(const string &udi, const string& sig) return false; } catch (const Xapian::DatabaseModifiedError &e) { LOGDEB(("Db::needUpdate: got modified error. reopen/retry\n")); - m_ndb->xdb().reopen(); - } XCATCHERROR(ermsg); - if (!ermsg.empty()) - break; + m_reason = e.get_msg(); + m_ndb->xrdb.reopen(); + continue; + } XCATCHERROR(m_reason); + break; } LOGERR(("Db::needUpdate: error while checking existence: %s\n", - ermsg.c_str())); + m_reason.c_str())); return true; } @@ -1393,7 +1385,7 @@ bool Db::termMatch(MatchType typ, const string &lang, { if (!m_ndb || !m_ndb->m_isopen) return false; - Xapian::Database db = m_ndb->xdb(); + Xapian::Database xdb = m_ndb->xdb(); res.clear(); @@ -1417,7 +1409,10 @@ bool Db::termMatch(MatchType typ, const string &lang, res.unique(); for (list::iterator it = res.begin(); it != res.end(); it++) { - it->wcf = db.get_collection_freq(it->term); + XAPTRY(it->wcf = xdb.get_collection_freq(it->term), + xdb, m_reason); + if (!m_reason.empty()) + return false; LOGDEB1(("termMatch: %d [%s]\n", it->wcf, it->term.c_str())); } } else { @@ -1446,34 +1441,44 @@ bool Db::termMatch(MatchType typ, const string &lang, } LOGDEB(("termMatch: initsec: [%s]\n", is.c_str())); - string ermsg; - try { - Xapian::TermIterator it = db.allterms_begin(); - if (!is.empty()) - it.skip_to(is.c_str()); - for (int n = 0; it != db.allterms_end(); it++) { - // If we're beyond the terms matching the initial string, end - if (!is.empty() && (*it).find(is) != 0) - break; - string term; - if (!prefix.empty()) - term = (*it).substr(prefix.length()); - else - term = *it; - if (typ == ET_WILD) { - if (fnmatch(droot.c_str(), term.c_str(), 0) == FNM_NOMATCH) - continue; - } else { - if (regexec(®, term.c_str(), 0, 0, 0)) - continue; - } - // Do we want stem expansion here? We don't do it for now - res.push_back(TermMatchEntry(term, it.get_termfreq())); - ++n; - } - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("termMatch: %s\n", ermsg.c_str())); + for (int tries = 0; tries < 2; tries++) { + try { + Xapian::TermIterator it = xdb.allterms_begin(); + if (!is.empty()) + it.skip_to(is.c_str()); + for (int n = 0; it != xdb.allterms_end(); it++) { + // If we're beyond the terms matching the initial + // string, end + if (!is.empty() && (*it).find(is) != 0) + break; + string term; + if (!prefix.empty()) + term = (*it).substr(prefix.length()); + else + term = *it; + if (typ == ET_WILD) { + if (fnmatch(droot.c_str(), term.c_str(), 0) == + FNM_NOMATCH) + continue; + } else { + if (regexec(®, term.c_str(), 0, 0, 0)) + continue; + } + // Do we want stem expansion here? We don't do it for now + res.push_back(TermMatchEntry(term, it.get_termfreq())); + ++n; + } + m_reason.erase(); + break; + } catch (const Xapian::DatabaseModifiedError &e) { + m_reason = e.get_msg(); + xdb.reopen(); + continue; + } XCATCHERROR(m_reason); + break; + } + if (!m_reason.empty()) { + LOGERR(("termMatch: %s\n", m_reason.c_str())); return false; } @@ -1508,12 +1513,9 @@ TermIter *Db::termWalkOpen() TermIter *tit = new TermIter; if (tit) { tit->db = m_ndb->xdb(); - string ermsg; - try { - tit->it = tit->db.allterms_begin(); - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("Db::termWalkOpen: xapian error: %s\n", ermsg.c_str())); + XAPTRY(tit->it = tit->db.allterms_begin(), tit->db, m_reason); + if (!m_reason.empty()) { + LOGERR(("Db::termWalkOpen: xapian error: %s\n", m_reason.c_str())); return 0; } } @@ -1521,15 +1523,15 @@ TermIter *Db::termWalkOpen() } bool Db::termWalkNext(TermIter *tit, string &term) { - string ermsg; - try { + XAPTRY( if (tit && tit->it != tit->db.allterms_end()) { term = *(tit->it)++; return true; } - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("Db::termWalkOpen: xapian error: %s\n", ermsg.c_str())); + , tit->db, m_reason); + + if (!m_reason.empty()) { + LOGERR(("Db::termWalkOpen: xapian error: %s\n", m_reason.c_str())); } return false; } @@ -1544,13 +1546,12 @@ bool Db::termExists(const string& word) { if (!m_ndb || !m_ndb->m_isopen) return 0; - string ermsg; - try { - if (!m_ndb->xdb().term_exists(word)) - return false; - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("Db::termWalkOpen: xapian error: %s\n", ermsg.c_str())); + + XAPTRY(if (!m_ndb->xdb().term_exists(word)) return false, + m_ndb->xrdb, m_reason); + + if (!m_reason.empty()) { + LOGERR(("Db::termWalkOpen: xapian error: %s\n", m_reason.c_str())); return false; } return true; @@ -1573,27 +1574,14 @@ bool Db::stemDiffers(const string& lang, const string& word, bool Db::makeDocAbstract(Doc &doc, Query *query, string& abstract) { LOGDEB1(("Db::makeDocAbstract: exti %d\n", exti)); - if (!m_ndb) { + if (!m_ndb || !m_ndb->m_isopen) { LOGERR(("Db::makeDocAbstract: no db\n")); return false; } - m_reason.erase(); - for (int i = 0; i < 2; i++) { - try { - abstract = m_ndb->makeAbstract(doc.xdocid, query); - m_reason.erase(); - break; - } catch (const Xapian::DatabaseModifiedError &error) { - LOGDEB(("Db:makeDocAbstract: caught DatabaseModified\n")); - m_reason = error.get_msg(); - m_ndb->xdb().reopen(); - } catch (const Xapian::Error & error) { - LOGERR(("Db::makeDocAbstract: exception: %s\n", - error.get_msg().c_str())); - m_reason = error.get_msg(); - break; - } - } + + XAPTRY(abstract = m_ndb->makeAbstract(doc.xdocid, query), + m_ndb->xrdb, m_reason); + return m_reason.empty() ? true : false; } @@ -1609,25 +1597,32 @@ bool Db::getDoc(const string &udi, Doc &doc) doc.pc = 100; string uniterm = make_uniterm(udi); - string ermsg; - try { - 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 - doc.pc = -1; - LOGINFO(("Db:getDoc: no such doc in index: [%s] (len %d)\n", - uniterm.c_str(), uniterm.length())); - return true; - } - 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); - if (!ermsg.empty()) { - LOGERR(("Db::getDoc: %s\n", ermsg.c_str())); + for (int tries = 0; tries < 2; tries++) { + try { + 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 + doc.pc = -1; + LOGINFO(("Db:getDoc: no such doc in index: [%s] (len %d)\n", + uniterm.c_str(), uniterm.length())); + return true; + } + 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); + } catch (const Xapian::DatabaseModifiedError &e) { + m_reason = e.get_msg(); + m_ndb->xrdb.reopen(); + continue; + } XCATCHERROR(m_reason); + break; } + + LOGERR(("Db::getDoc: %s\n", m_reason.c_str())); return false; } diff --git a/src/rcldb/rcldb_p.h b/src/rcldb/rcldb_p.h index 6b2f8d15..ab9524af 100644 --- a/src/rcldb/rcldb_p.h +++ b/src/rcldb/rcldb_p.h @@ -31,6 +31,20 @@ enum value_slot { MSG = "Caught unknown xapian exception"; \ } +#define XAPTRY(STMTTOTRY, XAPDB, ERSTR) \ + for (int tries = 0; tries < 2; tries++) { \ + try { \ + STMTTOTRY; \ + ERSTR.erase(); \ + break; \ + } catch (const Xapian::DatabaseModifiedError &e) { \ + ERSTR = e.get_msg(); \ + XAPDB.reopen(); \ + continue; \ + } XCATCHERROR(ERSTR); \ + break; \ + } + class Query; // A class for data and methods that would have to expose diff --git a/src/rcldb/rclquery.cpp b/src/rcldb/rclquery.cpp index 7c308cae..eecd4893 100644 --- a/src/rcldb/rclquery.cpp +++ b/src/rcldb/rclquery.cpp @@ -151,34 +151,44 @@ bool Query::setQuery(RefCntr sdata) m_reason += sdata->getReason(); return false; } - m_nq->query = xq; - string ermsg; + m_nq->xquery = xq; + string d; - try { - m_nq->enquire = new Xapian::Enquire(m_db->m_ndb->xrdb); - if (m_collapseDuplicates) { - m_nq->enquire->set_collapse_key(Rcl::VALUE_MD5); - } else { - m_nq->enquire->set_collapse_key(Xapian::BAD_VALUENO); - } - if (!m_sortField.empty()) { - if (m_sorter) { - delete (QSorter*)m_sorter; - m_sorter = 0; - } - m_sorter = new QSorter(m_sortField); - // It really seems there is a xapian bug about sort order, we - // invert here. - m_nq->enquire->set_sort_by_key((QSorter*)m_sorter, - !m_sortAscending); - } - m_nq->enquire->set_query(m_nq->query); - m_nq->mset = Xapian::MSet(); - // Get the query description and trim the "Xapian::Query" - d = m_nq->query.get_description(); - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGDEB(("Query::SetQuery: xapian error %s\n", ermsg.c_str())); + for (int tries = 0; tries < 2; tries++) { + try { + m_nq->xenquire = new Xapian::Enquire(m_db->m_ndb->xrdb); + if (m_collapseDuplicates) { + m_nq->xenquire->set_collapse_key(Rcl::VALUE_MD5); + } else { + m_nq->xenquire->set_collapse_key(Xapian::BAD_VALUENO); + } + if (!m_sortField.empty()) { + if (m_sorter) { + delete (QSorter*)m_sorter; + m_sorter = 0; + } + m_sorter = new QSorter(m_sortField); + // It really seems there is a xapian bug about sort order, we + // invert here. + m_nq->xenquire->set_sort_by_key((QSorter*)m_sorter, + !m_sortAscending); + } + m_nq->xenquire->set_query(m_nq->xquery); + m_nq->xmset = Xapian::MSet(); + // Get the query description and trim the "Xapian::Query" + d = m_nq->xquery.get_description(); + m_reason.erase(); + break; + } catch (const Xapian::DatabaseModifiedError &e) { + m_reason = e.get_msg(); + m_db->m_ndb->xrdb.reopen(); + continue; + } XCATCHERROR(m_reason); + break; + } + + if (!m_reason.empty()) { + LOGDEB(("Query::SetQuery: xapian error %s\n", m_reason.c_str())); return false; } @@ -202,8 +212,8 @@ bool Query::getQueryTerms(list& terms) Xapian::TermIterator it; string ermsg; try { - for (it = m_nq->query.get_terms_begin(); - it != m_nq->query.get_terms_end(); it++) { + for (it = m_nq->xquery.get_terms_begin(); + it != m_nq->xquery.get_terms_end(); it++) { terms.push_back(*it); } } XCATCHERROR(ermsg); @@ -216,7 +226,7 @@ bool Query::getQueryTerms(list& terms) bool Query::getMatchTerms(const Doc& doc, list& terms) { - if (ISNULL(m_nq) || !m_nq->enquire) { + if (ISNULL(m_nq) || !m_nq->xenquire) { LOGERR(("Query::getMatchTerms: no query opened\n")); return -1; } @@ -224,15 +234,14 @@ bool Query::getMatchTerms(const Doc& doc, list& terms) terms.clear(); Xapian::TermIterator it; Xapian::docid id = Xapian::docid(doc.xdocid); - string ermsg; - try { - for (it=m_nq->enquire->get_matching_terms_begin(id); - it != m_nq->enquire->get_matching_terms_end(id); it++) { - terms.push_back(*it); - } - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("getQueryTerms: xapian error: %s\n", ermsg.c_str())); + + XAPTRY(terms.insert(terms.begin(), + m_nq->xenquire->get_matching_terms_begin(id), + m_nq->xenquire->get_matching_terms_end(id)), + m_db->m_ndb->xrdb, m_reason); + + if (!m_reason.empty()) { + LOGERR(("getQueryTerms: xapian error: %s\n", m_reason.c_str())); return false; } @@ -246,25 +255,23 @@ static const int qquantum = 30; // the search job in there, this can be long int Query::getResCnt() { - if (ISNULL(m_nq) || !m_nq->enquire) { + if (ISNULL(m_nq) || !m_nq->xenquire) { LOGERR(("Query::getResCnt: no query opened\n")); return -1; } - string ermsg; + int ret = -1; - if (m_nq->mset.size() <= 0) { + if (m_nq->xmset.size() <= 0) { Chrono chron; - try { - m_nq->mset = m_nq->enquire->get_mset(0, qquantum,0, m_nq->decider); - ret = m_nq->mset.get_matches_lower_bound(); - } catch (const Xapian::DatabaseModifiedError &error) { - m_db->m_ndb->xrdb.reopen(); - m_nq->mset = m_nq->enquire->get_mset(0, qquantum,0, m_nq->decider); - ret = m_nq->mset.get_matches_lower_bound(); - } XCATCHERROR(ermsg); + + XAPTRY(m_nq->xmset = + m_nq->xenquire->get_mset(0, qquantum,0, m_nq->decider); + ret = m_nq->xmset.get_matches_lower_bound(), + m_db->m_ndb->xrdb, m_reason); + LOGDEB(("Query::getResCnt: %d mS\n", chron.millis())); - if (!ermsg.empty()) - LOGERR(("enquire->get_mset: exception: %s\n", ermsg.c_str())); + if (!m_reason.empty()) + LOGERR(("xenquire->get_mset: exception: %s\n", m_reason.c_str())); } return ret; } @@ -282,7 +289,7 @@ int Query::getResCnt() bool Query::getDoc(int exti, Doc &doc) { LOGDEB1(("Query::getDoc: exti %d\n", exti)); - if (ISNULL(m_nq) || !m_nq->enquire) { + if (ISNULL(m_nq) || !m_nq->xenquire) { LOGERR(("Query::getDoc: no query opened\n")); return false; } @@ -301,31 +308,29 @@ bool Query::getDoc(int exti, Doc &doc) while (exti >= (int)m_nq->m_dbindices.size()) { LOGDEB(("Query::getDoc: fetching %d starting at %d\n", qquantum, first)); - try { - m_nq->mset = m_nq->enquire->get_mset(first, qquantum); - } catch (const Xapian::DatabaseModifiedError &error) { - m_db->m_ndb->xrdb.reopen(); - m_nq->mset = m_nq->enquire->get_mset(first, qquantum); - } catch (const Xapian::Error & error) { - LOGERR(("enquire->get_mset: exception: %s\n", - error.get_msg().c_str())); - m_reason = error.get_msg(); - return false; + + XAPTRY(m_nq->xmset = m_nq->xenquire->get_mset(first, qquantum), + m_db->m_ndb->xrdb, m_reason); + + if (!m_reason.empty()) { + LOGERR(("enquire->get_mset: exception: %s\n", + m_reason.c_str())); + return false; } - if (m_nq->mset.empty()) { + if (m_nq->xmset.empty()) { LOGDEB(("Query::getDoc: got empty mset\n")); return false; } - first = m_nq->mset.get_firstitem(); - for (unsigned int i = 0; i < m_nq->mset.size() ; i++) { + first = m_nq->xmset.get_firstitem(); + for (unsigned int i = 0; i < m_nq->xmset.size() ; i++) { LOGDEB(("Query::getDoc: [%d]\n", i)); - Xapian::Document xdoc = m_nq->mset[i].get_document(); + Xapian::Document xdoc = m_nq->xmset[i].get_document(); if ((*m_nq->postfilter)(xdoc)) { m_nq->m_dbindices.push_back(first + i); } } - first = first + m_nq->mset.size(); + first = first + m_nq->xmset.size(); } } xapi = m_nq->m_dbindices[exti]; @@ -334,34 +339,31 @@ bool Query::getDoc(int exti, Doc &doc) } // From there on, we work with a xapian enquire item number. Fetch it - int first = m_nq->mset.get_firstitem(); - int last = first + m_nq->mset.size() -1; + int first = m_nq->xmset.get_firstitem(); + int last = first + m_nq->xmset.size() -1; if (!(xapi >= first && xapi <= last)) { LOGDEB(("Fetching for first %d, count %d\n", xapi, qquantum)); - try { - m_nq->mset = m_nq->enquire->get_mset(xapi, qquantum, - 0, m_nq->decider); - } catch (const Xapian::DatabaseModifiedError &error) { - m_db->m_ndb->xrdb.reopen(); - m_nq->mset = m_nq->enquire->get_mset(xapi, qquantum, - 0, m_nq->decider); - } catch (const Xapian::Error & error) { - LOGERR(("enquire->get_mset: exception: %s\n", - error.get_msg().c_str())); - m_reason = error.get_msg(); - return false; + XAPTRY(m_nq->xmset = m_nq->xenquire->get_mset(xapi, qquantum, + 0, m_nq->decider), + m_db->m_ndb->xrdb, m_reason); + + if (!m_reason.empty()) { + LOGERR(("enquire->get_mset: exception: %s\n", m_reason.c_str())); + return false; } - if (m_nq->mset.empty()) + if (m_nq->xmset.empty()) { + LOGDEB(("enquire->get_mset: got empty result\n")); return false; - first = m_nq->mset.get_firstitem(); - last = first + m_nq->mset.size() -1; + } + first = m_nq->xmset.get_firstitem(); + last = first + m_nq->xmset.size() -1; } LOGDEB1(("Query::getDoc: Qry [%s] win [%d-%d] Estimated results: %d", m_nq->query.get_description().c_str(), - first, last, m_nq->mset.get_matches_lower_bound())); + first, last, m_nq->xmset.get_matches_lower_bound())); Xapian::Document xdoc; Xapian::docid docid = 0; @@ -370,41 +372,42 @@ bool Query::getDoc(int exti, Doc &doc) m_reason.erase(); for (int xaptries=0; xaptries < 2; xaptries++) { try { - xdoc = m_nq->mset[xapi-first].get_document(); - docid = *(m_nq->mset[xapi-first]); - pc = m_nq->mset.convert_to_percent(m_nq->mset[xapi-first]); + xdoc = m_nq->xmset[xapi-first].get_document(); + docid = *(m_nq->xmset[xapi-first]); + pc = m_nq->xmset.convert_to_percent(m_nq->xmset[xapi-first]); data = xdoc.get_data(); m_reason.erase(); break; } catch (Xapian::DatabaseModifiedError &error) { // retry or end of loop - LOGDEB(("getDoc: caught DatabaseModified\n")); m_reason = error.get_msg(); continue; } XCATCHERROR(m_reason); break; } - + if (!m_reason.empty()) { + LOGERR(("Query::getDoc: %s\n", m_reason.c_str())); + return false; + } // Parse xapian document's data and populate doc fields - return m_reason.empty() ? - m_db->m_ndb->dbDataToRclDoc(docid, data, doc, pc) : false; + return m_db->m_ndb->dbDataToRclDoc(docid, data, doc, pc); } list Query::expand(const Doc &doc) { list res; - if (ISNULL(m_nq) || !m_nq->enquire) { + if (ISNULL(m_nq) || !m_nq->xenquire) { LOGERR(("Query::expand: no query opened\n")); return res; } - string ermsg; + for (int tries = 0; tries < 2; tries++) { try { Xapian::RSet rset; rset.add_document(Xapian::docid(doc.xdocid)); // We don't exclude the original query terms. - Xapian::ESet eset = m_nq->enquire->get_eset(20, rset, false); + Xapian::ESet eset = m_nq->xenquire->get_eset(20, rset, false); LOGDEB(("ESet terms:\n")); // We filter out the special terms for (Xapian::ESetIterator it = eset.begin(); @@ -416,16 +419,21 @@ list Query::expand(const Doc &doc) if (res.size() >= 10) break; } - } catch (const Xapian::DatabaseModifiedError &error) { - continue; - } XCATCHERROR(ermsg); - if (!ermsg.empty()) { - LOGERR(("Query::expand: xapian error %s\n", ermsg.c_str())); - res.clear(); - } + m_reason.erase(); + break; + } catch (const Xapian::DatabaseModifiedError &e) { + m_reason = e.get_msg(); + m_db->m_ndb->xrdb.reopen(); + continue; + } XCATCHERROR(m_reason); break; } + if (!m_reason.empty()) { + LOGERR(("Query::expand: xapian error %s\n", m_reason.c_str())); + res.clear(); + } + return res; } diff --git a/src/rcldb/rclquery_p.h b/src/rcldb/rclquery_p.h index 19c61033..0e003fe8 100644 --- a/src/rcldb/rclquery_p.h +++ b/src/rcldb/rclquery_p.h @@ -20,7 +20,7 @@ public: /** query descriptor: terms and subqueries joined by operators * (or/and etc...) */ - Xapian::Query query; + Xapian::Query xquery; /** In case there is a postq filter: sequence of db indices that match */ vector m_dbindices; @@ -47,13 +47,13 @@ public: Xapian::MatchDecider *decider; // Xapian does the filtering Xapian::MatchDecider *postfilter; // Result filtering done by Recoll - Xapian::Enquire *enquire; // Open query descriptor. - Xapian::MSet mset; // Partial result set + Xapian::Enquire *xenquire; // Open query descriptor. + Xapian::MSet xmset; // Partial result set // Term frequencies for current query. See makeAbstract, setQuery map termfreqs; Native(Query *q) - : m_q(q), decider(0), postfilter(0), enquire(0) + : m_q(q), decider(0), postfilter(0), xenquire(0) { } ~Native() { clear(); @@ -62,7 +62,7 @@ public: m_dbindices.clear(); delete decider; decider = 0; delete postfilter; postfilter = 0; - delete enquire; enquire = 0; + delete xenquire; xenquire = 0; termfreqs.clear(); } };