Branch data Line data Source code
1 : : /* inmemory_database.h: C++ class definition for inmemory database access
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002 Ananova Ltd
5 : : * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Olly Betts
6 : : * Copyright 2006,2009 Lemur Consulting Ltd
7 : : *
8 : : * This program is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU General Public License as
10 : : * published by the Free Software Foundation; either version 2 of the
11 : : * License, or (at your option) any later version.
12 : : *
13 : : * This program is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program; if not, write to the Free Software
20 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 : : * USA
22 : : */
23 : :
24 : : #ifndef OM_HGUARD_INMEMORY_DATABASE_H
25 : : #define OM_HGUARD_INMEMORY_DATABASE_H
26 : :
27 : : #include "leafpostlist.h"
28 : : #include "termlist.h"
29 : : #include "database.h"
30 : : #include <map>
31 : : #include <vector>
32 : : #include <algorithm>
33 : : #include <xapian/document.h>
34 : : #include "inmemory_positionlist.h"
35 : : #include "internaltypes.h"
36 : : #include "omassert.h"
37 : : #include "noreturn.h"
38 : :
39 : : using namespace std;
40 : :
41 : : struct ValueStats;
42 : :
43 : : // Class representing a posting (a term/doc pair, and
44 : : // all the relevant positional information, is a single posting)
45 : 5588390 : class InMemoryPosting {
46 : : public:
47 : : Xapian::docid did;
48 : : bool valid;
49 : : vector<Xapian::termpos> positions; // Sorted vector of positions
50 : : Xapian::termcount wdf;
51 : :
52 : : // Merge two postings (same term/doc pair, new positional info)
53 : 268080 : void merge(const InMemoryPosting & post) {
54 : : Assert(did == post.did);
55 : :
56 : : positions.insert(positions.end(),
57 : : post.positions.begin(),
58 : 268080 : post.positions.end());
59 : : // FIXME - inefficient - use merge (and list<>)?
60 : 268080 : sort(positions.begin(), positions.end());
61 : 268080 : }
62 : : };
63 : :
64 : 10079049 : class InMemoryTermEntry {
65 : : public:
66 : : string tname;
67 : : vector<Xapian::termpos> positions; // Sorted vector of positions
68 : : Xapian::termcount wdf;
69 : :
70 : : // Merge two postings (same term/doc pair, new positional info)
71 : 268080 : void merge(const InMemoryTermEntry & post) {
72 : : Assert(tname == post.tname);
73 : :
74 : : positions.insert(positions.end(),
75 : : post.positions.begin(),
76 : 268080 : post.positions.end());
77 : : // FIXME - inefficient - use merge (and list<>)?
78 : 268080 : sort(positions.begin(), positions.end());
79 : 268080 : }
80 : : };
81 : :
82 : : // Compare by document ID
83 : : class InMemoryPostingLessThan {
84 : : public:
85 : 5361073 : int operator() (const InMemoryPosting &p1, const InMemoryPosting &p2)
86 : : {
87 : 5361073 : return p1.did < p2.did;
88 : : }
89 : : };
90 : :
91 : : // Compare by termname
92 : : class InMemoryTermEntryLessThan {
93 : : public:
94 : 5503787 : int operator() (const InMemoryTermEntry&p1, const InMemoryTermEntry&p2)
95 : : {
96 : 5503787 : return p1.tname < p2.tname;
97 : : }
98 : : };
99 : :
100 : : // Class representing a term and the documents indexing it
101 : 506482 : class InMemoryTerm {
102 : : public:
103 : : // Sorted list of documents indexing this term.
104 : : vector<InMemoryPosting> docs;
105 : :
106 : : Xapian::termcount term_freq;
107 : : Xapian::termcount collection_freq;
108 : :
109 : 101190 : InMemoryTerm() : term_freq(0), collection_freq(0) {}
110 : :
111 : : void add_posting(const InMemoryPosting & post);
112 : : };
113 : :
114 : : /// Class representing a document and the terms indexing it.
115 : 346210 : class InMemoryDoc {
116 : : public:
117 : : bool is_valid;
118 : : // Sorted list of terms indexing this document.
119 : : vector<InMemoryTermEntry> terms;
120 : :
121 : : /* Initialise invalid by default, so that resizing the termlist array
122 : : * doesn't create valid documents. */
123 : 12 : InMemoryDoc() : is_valid(false) {}
124 : :
125 : : // Initialise specifying validity.
126 : 39846 : InMemoryDoc(bool is_valid_) : is_valid(is_valid_) {}
127 : :
128 : : void add_posting(const InMemoryTermEntry & post);
129 : : };
130 : :
131 : : class InMemoryDatabase;
132 : :
133 : : /** A PostList in an inmemory database.
134 : : */
135 [ + - ][ # # ]: 47143 : class InMemoryPostList : public LeafPostList {
136 : : friend class InMemoryDatabase;
137 : : private:
138 : : vector<InMemoryPosting>::const_iterator pos;
139 : : vector<InMemoryPosting>::const_iterator end;
140 : : Xapian::doccount termfreq;
141 : : bool started;
142 : :
143 : : /** List of positions of the current term.
144 : : * This list is populated when read_position_list() is called.
145 : : */
146 : : InMemoryPositionList mypositions;
147 : :
148 : : Xapian::Internal::RefCntPtr<const InMemoryDatabase> db;
149 : :
150 : : InMemoryPostList(Xapian::Internal::RefCntPtr<const InMemoryDatabase> db,
151 : : const InMemoryTerm & imterm, const std::string & term_);
152 : : public:
153 : : Xapian::doccount get_termfreq() const;
154 : :
155 : : Xapian::docid get_docid() const; // Gets current docid
156 : : Xapian::termcount get_doclength() const; // Length of current document
157 : : Xapian::termcount get_wdf() const; // Within Document Frequency
158 : : PositionList * read_position_list();
159 : : PositionList * open_position_list() const;
160 : :
161 : : PostList *next(Xapian::weight w_min); // Moves to next docid
162 : :
163 : : PostList *skip_to(Xapian::docid did, Xapian::weight w_min); // Moves to next docid >= specified docid
164 : :
165 : : // True if we're off the end of the list.
166 : : bool at_end() const;
167 : :
168 : : string get_description() const;
169 : : };
170 : :
171 : : /** A PostList over all docs in an inmemory database.
172 : : */
173 [ + - ][ # # ]: 42 : class InMemoryAllDocsPostList : public LeafPostList {
174 : : friend class InMemoryDatabase;
175 : : private:
176 : : Xapian::docid did;
177 : :
178 : : Xapian::Internal::RefCntPtr<const InMemoryDatabase> db;
179 : :
180 : : InMemoryAllDocsPostList(Xapian::Internal::RefCntPtr<const InMemoryDatabase> db);
181 : : public:
182 : : Xapian::doccount get_termfreq() const;
183 : :
184 : : Xapian::docid get_docid() const; // Gets current docid
185 : : Xapian::termcount get_doclength() const; // Length of current document
186 : : Xapian::termcount get_wdf() const; // Within Document Frequency
187 : : PositionList * read_position_list();
188 : : PositionList * open_position_list() const;
189 : :
190 : : PostList *next(Xapian::weight w_min); // Moves to next docid
191 : :
192 : : PostList *skip_to(Xapian::docid did, Xapian::weight w_min); // Moves to next docid >= specified docid
193 : :
194 : : // True if we're off the end of the list
195 : : bool at_end() const;
196 : :
197 : : string get_description() const;
198 : : };
199 : :
200 : : // Term List
201 [ + - ][ # # ]: 398 : class InMemoryTermList : public TermList {
202 : : friend class InMemoryDatabase;
203 : : private:
204 : : vector<InMemoryTermEntry>::const_iterator pos;
205 : : vector<InMemoryTermEntry>::const_iterator end;
206 : : Xapian::termcount terms;
207 : : bool started;
208 : :
209 : : Xapian::Internal::RefCntPtr<const InMemoryDatabase> db;
210 : : Xapian::docid did;
211 : : Xapian::termcount document_length;
212 : :
213 : : InMemoryTermList(Xapian::Internal::RefCntPtr<const InMemoryDatabase> db,
214 : : Xapian::docid did,
215 : : const InMemoryDoc & doc,
216 : : Xapian::termcount len);
217 : : public:
218 : : Xapian::termcount get_approx_size() const;
219 : :
220 : : /// Collate weighting information for the current term.
221 : : void accumulate_stats(Xapian::Internal::ExpandStats & stats) const;
222 : :
223 : : string get_termname() const;
224 : : Xapian::termcount get_wdf() const; // Number of occurrences of term in current doc
225 : : Xapian::doccount get_termfreq() const; // Number of docs indexed by term
226 : : TermList * next();
227 : : TermList * skip_to(const std::string & term);
228 : : bool at_end() const;
229 : : Xapian::termcount positionlist_count() const;
230 : : Xapian::PositionIterator positionlist_begin() const;
231 : : };
232 : :
233 : : class InMemoryDocument;
234 : :
235 : : /** A database held entirely in memory.
236 : : *
237 : : * This is a prototype database, mainly used for debugging and testing.
238 : : */
239 : : class InMemoryDatabase : public Xapian::Database::Internal {
240 : : friend class InMemoryAllDocsPostList;
241 : : friend class InMemoryDocument;
242 : :
243 : : map<string, InMemoryTerm> postlists;
244 : : vector<InMemoryDoc> termlists;
245 : : vector<std::string> doclists;
246 : : vector<std::map<Xapian::valueno, string> > valuelists;
247 : : std::map<Xapian::valueno, ValueStats> valuestats;
248 : :
249 : : vector<Xapian::termcount> doclengths;
250 : :
251 : : std::map<string, string> metadata;
252 : :
253 : : Xapian::doccount totdocs;
254 : :
255 : : totlen_t totlen;
256 : :
257 : : bool positions_present;
258 : :
259 : : // Flag, true if the db has been closed.
260 : : bool closed;
261 : :
262 : : // Stop copy / assignment being allowed
263 : : InMemoryDatabase& operator=(const InMemoryDatabase &);
264 : : InMemoryDatabase(const InMemoryDatabase &);
265 : :
266 : : void make_term(const string & tname);
267 : :
268 : : bool doc_exists(Xapian::docid did) const;
269 : : Xapian::docid make_doc(const string & docdata);
270 : :
271 : : /* The common parts of add_doc and replace_doc */
272 : : void finish_add_doc(Xapian::docid did, const Xapian::Document &document);
273 : : void add_values(Xapian::docid did, const map<Xapian::valueno, string> &values_);
274 : :
275 : : void make_posting(InMemoryDoc * doc,
276 : : const string & tname,
277 : : Xapian::docid did,
278 : : Xapian::termpos position,
279 : : Xapian::termcount wdf,
280 : : bool use_position = true);
281 : :
282 : : //@{
283 : : /** Implementation of virtual methods: see Database for details.
284 : : */
285 : : void commit();
286 : : void cancel();
287 : :
288 : : Xapian::docid add_document(const Xapian::Document & document);
289 : : // Stop the default implementation of delete_document(term) and
290 : : // replace_document(term) from being hidden. This isn't really
291 : : // a problem as we only try to call them through the base class
292 : : // (where they aren't hidden) but some compilers generate a warning
293 : : // about the hiding.
294 : : #ifndef _MSC_VER
295 : : using Xapian::Database::Internal::delete_document;
296 : : using Xapian::Database::Internal::replace_document;
297 : : #endif
298 : : void delete_document(Xapian::docid did);
299 : : void replace_document(Xapian::docid did, const Xapian::Document & document);
300 : : //@}
301 : :
302 : : public:
303 : : /** Create and open an in-memory database.
304 : : *
305 : : * @exception Xapian::DatabaseOpeningError thrown if database can't be opened.
306 : : */
307 : : InMemoryDatabase();
308 : :
309 : : ~InMemoryDatabase();
310 : :
311 : : void reopen();
312 : : void close();
313 : 55846234 : bool is_closed() const { return closed; }
314 : :
315 : : Xapian::doccount get_doccount() const;
316 : :
317 : : Xapian::docid get_lastdocid() const;
318 : :
319 : : totlen_t get_total_length() const;
320 : : Xapian::doclength get_avlength() const;
321 : : Xapian::termcount get_doclength(Xapian::docid did) const;
322 : :
323 : : Xapian::doccount get_termfreq(const string & tname) const;
324 : : Xapian::termcount get_collection_freq(const string & tname) const;
325 : : Xapian::doccount get_value_freq(Xapian::valueno slot) const;
326 : : std::string get_value_lower_bound(Xapian::valueno slot) const;
327 : : std::string get_value_upper_bound(Xapian::valueno slot) const;
328 : : bool term_exists(const string & tname) const;
329 : : bool has_positions() const;
330 : :
331 : : LeafPostList * open_post_list(const string & tname) const;
332 : : TermList * open_term_list(Xapian::docid did) const;
333 : : Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy) const;
334 : :
335 : : std::string get_metadata(const std::string & key) const;
336 : : TermList * open_metadata_keylist(const std::string &prefix) const;
337 : : void set_metadata(const std::string & key, const std::string & value);
338 : :
339 : : Xapian::termcount positionlist_count(Xapian::docid did,
340 : : const string & tname) const;
341 : : PositionList * open_position_list(Xapian::docid did,
342 : : const string & tname) const;
343 : : TermList * open_allterms(const string & prefix) const;
344 : :
345 : : XAPIAN_NORETURN(static void throw_database_closed());
346 : : };
347 : :
348 : : #endif /* OM_HGUARD_INMEMORY_DATABASE_H */
|