|
a/src/rcldb/rcldb.cpp |
|
b/src/rcldb/rcldb.cpp |
1 |
#ifndef lint
|
1 |
#ifndef lint
|
2 |
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.123 2007-09-07 08:05:19 dockes Exp $ (C) 2004 J.F.Dockes";
|
2 |
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.124 2007-10-24 08:42:59 dockes Exp $ (C) 2004 J.F.Dockes";
|
3 |
#endif
|
3 |
#endif
|
4 |
/*
|
4 |
/*
|
5 |
* This program is free software; you can redistribute it and/or modify
|
5 |
* This program is free software; you can redistribute it and/or modify
|
6 |
* it under the terms of the GNU General Public License as published by
|
6 |
* it under the terms of the GNU General Public License as published by
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
... |
|
... |
102 |
|
102 |
|
103 |
// Querying
|
103 |
// Querying
|
104 |
Xapian::Database db;
|
104 |
Xapian::Database db;
|
105 |
Xapian::Query query; // query descriptor: terms and subqueries
|
105 |
Xapian::Query query; // query descriptor: terms and subqueries
|
106 |
// joined by operators (or/and etc...)
|
106 |
// joined by operators (or/and etc...)
|
|
|
107 |
Xapian::MatchDecider *decider;
|
107 |
Xapian::Enquire *enquire; // Open query descriptor.
|
108 |
Xapian::Enquire *enquire; // Open query descriptor.
|
108 |
Xapian::MSet mset; // Partial result set
|
109 |
Xapian::MSet mset; // Partial result set
|
109 |
|
110 |
|
110 |
// Term frequencies for current query. See makeAbstract, setQuery
|
111 |
// Term frequencies for current query. See makeAbstract, setQuery
|
111 |
map<string, double> m_termfreqs;
|
112 |
map<string, double> m_termfreqs;
|
112 |
|
113 |
|
113 |
Native(Db *db)
|
114 |
Native(Db *db)
|
114 |
: m_db(db),
|
115 |
: m_db(db),
|
115 |
m_isopen(false), m_iswritable(false), enquire(0)
|
116 |
m_isopen(false), m_iswritable(false), decider(0), enquire(0)
|
116 |
{ }
|
117 |
{ }
|
117 |
|
118 |
|
118 |
~Native() {
|
119 |
~Native() {
|
|
|
120 |
delete decider;
|
119 |
delete enquire;
|
121 |
delete enquire;
|
120 |
}
|
122 |
}
|
121 |
|
123 |
|
122 |
string makeAbstract(Xapian::docid id, const list<string>& terms);
|
124 |
string makeAbstract(Xapian::docid id, const list<string>& terms);
|
123 |
|
125 |
|
|
... |
|
... |
132 |
* unique term for replace_document, and for retrieving by
|
134 |
* unique term for replace_document, and for retrieving by
|
133 |
* path/ipath (history)
|
135 |
* path/ipath (history)
|
134 |
*/
|
136 |
*/
|
135 |
bool subDocs(const string &hash, vector<Xapian::docid>& docids);
|
137 |
bool subDocs(const string &hash, vector<Xapian::docid>& docids);
|
136 |
|
138 |
|
137 |
/** Keep this inline */
|
139 |
};
|
138 |
bool filterMatch(Db *rdb, Xapian::Document &xdoc) {
|
140 |
|
|
|
141 |
class FilterMatcher : public Xapian::MatchDecider {
|
|
|
142 |
public:
|
|
|
143 |
FilterMatcher(const string &topdir)
|
|
|
144 |
: m_topdir(topdir)
|
|
|
145 |
{}
|
|
|
146 |
virtual ~FilterMatcher() {}
|
|
|
147 |
|
|
|
148 |
virtual bool operator()(const Xapian::Document &xdoc) const {
|
139 |
// Parse xapian document's data and populate doc fields
|
149 |
// Parse xapian document's data and populate doc fields
|
140 |
string data = xdoc.get_data();
|
150 |
string data = xdoc.get_data();
|
141 |
ConfSimple parms(&data);
|
151 |
ConfSimple parms(&data);
|
142 |
|
152 |
|
143 |
// The only filtering for now is on file path (subtree)
|
153 |
// The only filtering for now is on file path (subtree)
|
144 |
string url;
|
154 |
string url;
|
145 |
parms.get(string("url"), url);
|
155 |
parms.get(string("url"), url);
|
146 |
url = url.substr(7);
|
156 |
LOGDEB2(("FilterMatcher topdir [%s] url [%s]\n",
|
147 |
LOGDEB2(("Rcl::Db::Native:filter filter [%s] fn [%s]\n",
|
|
|
148 |
rdb->m_filterTopDir.c_str(), url.c_str()));
|
157 |
m_topdir.c_str(), url.c_str()));
|
149 |
if (url.find(rdb->m_filterTopDir) == 0)
|
158 |
if (url.find(m_topdir, 7) == 7) {
|
|
|
159 |
LOGDEB(("FilterMatcher: MATCH\n"));
|
150 |
return true;
|
160 |
return true;
|
|
|
161 |
} else {
|
|
|
162 |
LOGDEB(("FilterMatcher: NO MATCH\n"));
|
151 |
return false;
|
163 |
return false;
|
|
|
164 |
}
|
|
|
165 |
}
|
152 |
}
|
166 |
|
|
|
167 |
private:
|
|
|
168 |
string m_topdir;
|
153 |
};
|
169 |
};
|
154 |
|
170 |
|
155 |
/* See comment in class declaration */
|
171 |
/* See comment in class declaration */
|
156 |
bool Native::subDocs(const string &hash, vector<Xapian::docid>& docids)
|
172 |
bool Native::subDocs(const string &hash, vector<Xapian::docid>& docids)
|
157 |
{
|
173 |
{
|
158 |
docids.clear();
|
174 |
docids.clear();
|
159 |
string qterm = "Q"+ hash + "|";
|
175 |
string qterm = "Q"+ hash + "|";
|
160 |
string ermsg;
|
176 |
string ermsg;
|
|
... |
|
... |
1422 |
}
|
1438 |
}
|
1423 |
m_reason.erase();
|
1439 |
m_reason.erase();
|
1424 |
LOGDEB(("Db::setQuery:\n"));
|
1440 |
LOGDEB(("Db::setQuery:\n"));
|
1425 |
|
1441 |
|
1426 |
m_filterTopDir = sdata->getTopdir();
|
1442 |
m_filterTopDir = sdata->getTopdir();
|
|
|
1443 |
delete m_ndb->decider;
|
|
|
1444 |
m_ndb->decider = 0;
|
|
|
1445 |
if (!m_filterTopDir.empty())
|
|
|
1446 |
m_ndb->decider = new FilterMatcher(m_filterTopDir);
|
1427 |
m_dbindices.clear();
|
1447 |
m_dbindices.clear();
|
1428 |
m_qOpts = opts;
|
1448 |
m_qOpts = opts;
|
1429 |
m_ndb->m_termfreqs.clear();
|
1449 |
m_ndb->m_termfreqs.clear();
|
1430 |
|
1450 |
|
1431 |
Xapian::Query xq;
|
1451 |
Xapian::Query xq;
|
|
... |
|
... |
1758 |
if (!m_ndb || !m_ndb->enquire) {
|
1778 |
if (!m_ndb || !m_ndb->enquire) {
|
1759 |
LOGERR(("Db::getDoc: no query opened\n"));
|
1779 |
LOGERR(("Db::getDoc: no query opened\n"));
|
1760 |
return false;
|
1780 |
return false;
|
1761 |
}
|
1781 |
}
|
1762 |
|
1782 |
|
1763 |
// For now the only post-query filter is on dir subtree
|
|
|
1764 |
bool postqfilter = !m_filterTopDir.empty();
|
|
|
1765 |
LOGDEB1(("Topdir %s postqflt %d\n", m_asdata.topdir.c_str(), postqfilter));
|
|
|
1766 |
|
|
|
1767 |
int xapi;
|
1783 |
int xapi;
|
1768 |
if (postqfilter) {
|
1784 |
if (m_ndb->decider) {
|
1769 |
// There is a postquery filter, does this fall in already known area ?
|
1785 |
// There is a postquery filter, does this fall in already known area ?
|
1770 |
if (exti >= (int)m_dbindices.size()) {
|
1786 |
if (exti >= (int)m_dbindices.size()) {
|
1771 |
// Have to fetch xapian docs and filter until we get
|
1787 |
// Have to fetch xapian docs and filter until we get
|
1772 |
// enough or fail
|
1788 |
// enough or fail
|
1773 |
m_dbindices.reserve(exti+1);
|
1789 |
m_dbindices.reserve(exti+1);
|
|
... |
|
... |
1794 |
}
|
1810 |
}
|
1795 |
first = m_ndb->mset.get_firstitem();
|
1811 |
first = m_ndb->mset.get_firstitem();
|
1796 |
for (unsigned int i = 0; i < m_ndb->mset.size() ; i++) {
|
1812 |
for (unsigned int i = 0; i < m_ndb->mset.size() ; i++) {
|
1797 |
LOGDEB(("Db::getDoc: [%d]\n", i));
|
1813 |
LOGDEB(("Db::getDoc: [%d]\n", i));
|
1798 |
Xapian::Document xdoc = m_ndb->mset[i].get_document();
|
1814 |
Xapian::Document xdoc = m_ndb->mset[i].get_document();
|
1799 |
if (m_ndb->filterMatch(this, xdoc)) {
|
1815 |
if ((*m_ndb->decider)(xdoc)) {
|
1800 |
m_dbindices.push_back(first + i);
|
1816 |
m_dbindices.push_back(first + i);
|
1801 |
}
|
1817 |
}
|
1802 |
}
|
1818 |
}
|
1803 |
first = first + m_ndb->mset.size();
|
1819 |
first = first + m_ndb->mset.size();
|
1804 |
}
|
1820 |
}
|
1805 |
}
|
1821 |
}
|
1806 |
xapi = m_dbindices[exti];
|
1822 |
xapi = m_dbindices[exti];
|
1807 |
} else {
|
1823 |
} else {
|
1808 |
xapi = exti;
|
1824 |
xapi = exti;
|
1809 |
}
|
1825 |
}
|
1810 |
|
|
|
1811 |
|
1826 |
|
1812 |
// From there on, we work with a xapian enquire item number. Fetch it
|
1827 |
// From there on, we work with a xapian enquire item number. Fetch it
|
1813 |
int first = m_ndb->mset.get_firstitem();
|
1828 |
int first = m_ndb->mset.get_firstitem();
|
1814 |
int last = first + m_ndb->mset.size() -1;
|
1829 |
int last = first + m_ndb->mset.size() -1;
|
1815 |
|
1830 |
|