xapian-core  1.4.30
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 }
Slow implementation for backends which don't streamed values.
Definition: slowvaluelist.h:32
A document in the database, possibly plus modifications.
Definition: document.h:43
A handle representing a document in a Xapian database.
Definition: document.h:61
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:82
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:283
Class representing a query.
Definition: query.h:46
Abstract base class for termlists.
Definition: termlist.h:39
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:325
Abstract base class for value streams.
Definition: valuelist.h:31
Hierarchy of classes which Xapian can throw as exceptions.
API for working with Xapian databases.
Abstract base class for leaf postlists.
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:80
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:72
unsigned valueno
The number for a value slot in a document.
Definition: types.h:108
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:38
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
XAPIAN_TOTALLENGTH_TYPE totallength
The total length of all documents in a database.
Definition: types.h:139
Various assertion macros.
#define Assert(COND)
Definition: omassert.h:122
Slow implementation for backends which don't streamed values.
Information about the steps involved in performing a replication.
Definition: replication.h:33