xapian-core  1.4.25
database.cc
Go to the documentation of this file.
1 /* database.cc: Database::Internal base class.
2  *
3  * Copyright 1999,2000,2001 BrightStation PLC
4  * Copyright 2002 Ananova Ltd
5  * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2011,2014,2016 Olly Betts
6  * Copyright 2008 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 #include <config.h>
25 
26 #include "database.h"
27 
28 #include "xapian/error.h"
29 
30 #include "api/leafpostlist.h"
31 #include "omassert.h"
32 #include "slowvaluelist.h"
33 
34 #include <algorithm>
35 #include <string>
36 
37 using namespace std;
39 
40 namespace Xapian {
41 
42 Database::Internal::~Internal()
43 {
44 }
45 
46 void
47 Database::Internal::keep_alive()
48 {
49  // For the normal case of local databases, nothing needs to be done.
50 }
51 
52 
53 void
54 Database::Internal::readahead_for_query(const Xapian::Query &)
55 {
56 }
57 
59 Database::Internal::get_doclength_lower_bound() const
60 {
61  // A zero-length document can't contain any terms, so we ignore such
62  // documents for the purposes of this lower bound.
63  return 1;
64 }
65 
67 Database::Internal::get_doclength_upper_bound() const
68 {
69  // Not a very tight bound in general, but this is only a fall-back for
70  // backends which don't store these stats.
71  return min(get_total_length(), Xapian::totallength(Xapian::termcount(-1)));
72 }
73 
75 Database::Internal::get_wdf_upper_bound(const string & term) const
76 {
77  // Not a very tight bound in general, but this is only a fall-back for
78  // backends which don't store these stats.
80  get_freqs(term, NULL, &cf);
81  return cf;
82 }
83 
84 // Discard any exceptions - we're called from the destructors of derived
85 // classes so we can't safely throw.
86 void
87 Database::Internal::dtor_called()
88 {
89  try {
90  if (transaction_active()) {
91  cancel_transaction();
92  } else if (transaction_state == TRANSACTION_NONE) {
93  commit();
94  }
95  } catch (...) {
96  // We can't safely throw exceptions from a destructor in case an
97  // exception is already active and causing us to be destroyed.
98  }
99 }
100 
101 void
102 Database::Internal::commit()
103 {
104  // Writable databases should override this method.
105  Assert(false);
106 }
107 
108 void
109 Database::Internal::cancel()
110 {
111  // Writable databases should override this method.
112  Assert(false);
113 }
114 
115 void
116 Database::Internal::begin_transaction(bool flushed)
117 {
118  if (transaction_state != TRANSACTION_NONE) {
119  if (transaction_state == TRANSACTION_UNIMPLEMENTED)
120  throw Xapian::UnimplementedError("This backend doesn't implement transactions");
121  throw InvalidOperationError("Cannot begin transaction - transaction already in progress");
122  }
123  if (flushed) {
124  // N.B. Call commit() before we set transaction_state since commit()
125  // isn't allowing during a transaction.
126  commit();
127  transaction_state = TRANSACTION_FLUSHED;
128  } else {
129  transaction_state = TRANSACTION_UNFLUSHED;
130  }
131 }
132 
133 void
134 Database::Internal::commit_transaction()
135 {
136  if (!transaction_active()) {
137  if (transaction_state == TRANSACTION_UNIMPLEMENTED)
138  throw Xapian::UnimplementedError("This backend doesn't implement transactions");
139  throw InvalidOperationError("Cannot commit transaction - no transaction currently in progress");
140  }
141  bool flushed = (transaction_state == TRANSACTION_FLUSHED);
142  transaction_state = TRANSACTION_NONE;
143  // N.B. Call commit() after we clear transaction_state since commit()
144  // isn't allowing during a transaction.
145  if (flushed) commit();
146 }
147 
148 void
149 Database::Internal::cancel_transaction()
150 {
151  if (!transaction_active()) {
152  if (transaction_state == TRANSACTION_UNIMPLEMENTED)
153  throw Xapian::UnimplementedError("This backend doesn't implement transactions");
154  throw InvalidOperationError("Cannot cancel transaction - no transaction currently in progress");
155  }
156  transaction_state = TRANSACTION_NONE;
157  cancel();
158 }
159 
161 Database::Internal::add_document(const Xapian::Document &)
162 {
163  // Writable databases should override this method.
164  Assert(false);
165  return 0;
166 }
167 
168 void
169 Database::Internal::delete_document(Xapian::docid)
170 {
171  // Writable databases should override this method.
172  Assert(false);
173 }
174 
175 void
176 Database::Internal::delete_document(const string & unique_term)
177 {
178  // Default implementation - overridden for remote databases
179  intrusive_ptr<LeafPostList> pl(open_post_list(unique_term));
180  while (pl->next(), !pl->at_end()) {
181  delete_document(pl->get_docid());
182  }
183 }
184 
185 void
186 Database::Internal::replace_document(Xapian::docid, const Xapian::Document &)
187 {
188  // Writable databases should override this method.
189  Assert(false);
190 }
191 
193 Database::Internal::replace_document(const string & unique_term,
194  const Xapian::Document & document)
195 {
196  // Default implementation - overridden for remote databases
197  intrusive_ptr<LeafPostList> pl(open_post_list(unique_term));
198  pl->next();
199  if (pl->at_end()) {
200  return add_document(document);
201  }
202  Xapian::docid did = pl->get_docid();
203  replace_document(did, document);
204  while (pl->next(), !pl->at_end()) {
205  delete_document(pl->get_docid());
206  }
207  return did;
208 }
209 
210 ValueList *
211 Database::Internal::open_value_list(Xapian::valueno slot) const
212 {
213  return new SlowValueList(this, slot);
214 }
215 
216 TermList *
217 Database::Internal::open_spelling_termlist(const string &) const
218 {
219  // Only implemented for some database backends - others will just not
220  // suggest spelling corrections (or not contribute to them in a multiple
221  // database situation).
222  return NULL;
223 }
224 
225 TermList *
226 Database::Internal::open_spelling_wordlist() const
227 {
228  // Only implemented for some database backends - others will just not
229  // suggest spelling corrections (or not contribute to them in a multiple
230  // database situation).
231  return NULL;
232 }
233 
235 Database::Internal::get_spelling_frequency(const string &) const
236 {
237  // Only implemented for some database backends - others will just not
238  // suggest spelling corrections (or not contribute to them in a multiple
239  // database situation).
240  return 0;
241 }
242 
243 void
244 Database::Internal::add_spelling(const string &, Xapian::termcount) const
245 {
246  throw Xapian::UnimplementedError("This backend doesn't implement spelling correction");
247 }
248 
249 void
250 Database::Internal::remove_spelling(const string &, Xapian::termcount) const
251 {
252  throw Xapian::UnimplementedError("This backend doesn't implement spelling correction");
253 }
254 
255 TermList *
256 Database::Internal::open_synonym_termlist(const string &) const
257 {
258  // Only implemented for some database backends - others will just not
259  // expand synonyms (or not contribute to them in a multiple database
260  // situation).
261  return NULL;
262 }
263 
264 TermList *
265 Database::Internal::open_synonym_keylist(const string &) const
266 {
267  // Only implemented for some database backends - others will just not
268  // expand synonyms (or not contribute to them in a multiple database
269  // situation).
270  return NULL;
271 }
272 
273 void
274 Database::Internal::add_synonym(const string &, const string &) const
275 {
276  throw Xapian::UnimplementedError("This backend doesn't implement synonyms");
277 }
278 
279 void
280 Database::Internal::remove_synonym(const string &, const string &) const
281 {
282  throw Xapian::UnimplementedError("This backend doesn't implement synonyms");
283 }
284 
285 void
286 Database::Internal::clear_synonyms(const string &) const
287 {
288  throw Xapian::UnimplementedError("This backend doesn't implement synonyms");
289 }
290 
291 string
292 Database::Internal::get_metadata(const string &) const
293 {
294  return string();
295 }
296 
297 TermList *
298 Database::Internal::open_metadata_keylist(const string &) const
299 {
300  // Only implemented for some database backends - others will simply report
301  // there being no metadata keys.
302  return NULL;
303 }
304 
305 void
306 Database::Internal::set_metadata(const string &, const string &)
307 {
308  throw Xapian::UnimplementedError("This backend doesn't implement metadata");
309 }
310 
311 bool
312 Database::Internal::reopen()
313 {
314  // Database backends which don't support simultaneous update and reading
315  // probably don't need to do anything here. And since we didn't do
316  // anything we should return false to indicate that nothing has changed.
317  return false;
318 }
319 
320 void
321 Database::Internal::request_document(Xapian::docid /*did*/) const
322 {
323 }
324 
326 Database::Internal::collect_document(Xapian::docid did) const
327 {
328  // Open the document lazily - collect document is only called by
329  // Enquire::Internal::read_doc() for a given MSetItem, so we know that the
330  // document already exists.
331  return open_document(did, true);
332 }
333 
334 void
335 Database::Internal::write_changesets_to_fd(int, const string &, bool, ReplicationInfo *)
336 {
337  throw Xapian::UnimplementedError("This backend doesn't provide changesets");
338 }
339 
340 string
341 Database::Internal::get_revision_info() const
342 {
343  throw Xapian::UnimplementedError("This backend doesn't provide access to revision information");
344 }
345 
346 string
347 Database::Internal::get_uuid() const
348 {
349  return string();
350 }
351 
352 void
353 Database::Internal::invalidate_doc_object(Xapian::Document::Internal *) const
354 {
355  // Do nothing, by default.
356 }
357 
358 void
359 Database::Internal::get_used_docid_range(Xapian::docid &,
360  Xapian::docid &) const
361 {
362  throw Xapian::UnimplementedError("This backend doesn't implement get_used_docid_range()");
363 }
364 
365 bool
366 Database::Internal::locked() const
367 {
368  return false;
369 }
370 
371 }
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:80
#define Assert(COND)
Definition: omassert.h:122
virtual Xapian::docid get_docid() const =0
Return the current docid.
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:283
XAPIAN_TOTALLENGTH_TYPE totallength
The total length of all documents in a database.
Definition: types.h:139
A document in the database, possibly plus modifications.
Definition: document.h:43
Abstract base class for termlists.
Definition: termlist.h:39
STL namespace.
Abstract base class for leaf postlists.
Hierarchy of classes which Xapian can throw as exceptions.
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:72
Information about the steps involved in performing a replication.
Definition: replication.h:33
Slow implementation for backends which don&#39;t streamed values.
Abstract base class for value streams.
Definition: valuelist.h:31
virtual Internal * next(double w_min)=0
Advance the current position to the next document in the postlist.
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:38
unsigned valueno
The number for a value slot in a document.
Definition: types.h:108
virtual bool at_end() const =0
Return true if the current position is past the last entry in this list.
Various assertion macros.
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
Class representing a query.
Definition: query.h:46
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
A handle representing a document in a Xapian database.
Definition: document.h:61
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:325
Slow implementation for backends which don&#39;t streamed values.
Definition: slowvaluelist.h:32