xapian-core  2.1.0
multi_database.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2017,2019,2020,2022,2024,2026 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see
16  * <https://www.gnu.org/licenses/>.
17  */
18 
19 #include <config.h>
20 
21 #include "multi_database.h"
22 
23 #include "backends/backends.h"
24 #include "backends/multi.h"
25 #include "clamp_cast.h"
26 #include "expand/ortermlist.h"
27 #include "expand/termlistmerger.h"
28 #include "multi_alltermslist.h"
29 #include "multi_postlist.h"
30 #include "multi_termlist.h"
31 #include "multi_valuelist.h"
32 #include "negate_unsigned.h"
33 
34 #include <memory>
35 #include <string_view>
36 
37 using namespace std;
38 
41 {
42  return clamp_cast<MultiDatabase::size_type>(shards.size());
43 }
44 
45 bool
47 {
48  bool result = false;
49  for (auto&& shard : shards) {
50  if (shard->reopen()) {
51  result = true;
52  }
53  }
54  return result;
55 }
56 
57 void
59 {
60  for (auto&& shard : shards) {
61  shard->close();
62  }
63 }
64 
65 PostList*
67 {
68  PostList** postlists = new PostList*[shards.size()];
69  size_t count = 0;
70  try {
71  for (auto&& shard : shards) {
72  postlists[count] = shard->open_post_list(term);
73  ++count;
74  }
75  return new MultiPostList(count, postlists);
76  } catch (...) {
77  while (count)
78  delete postlists[--count];
79  delete [] postlists;
80  throw;
81  }
82 }
83 
85 MultiDatabase::open_leaf_post_list(string_view, bool) const
86 {
87  // This should never get called.
88  Assert(false);
89  return NULL;
90 }
91 
92 TermList*
94 {
96 }
97 
98 TermList*
100 {
101  Xapian::doccount n_shards = shards.size();
102  auto shard_index = shard_number(did, n_shards);
103  auto shard = shards[shard_index];
104  Xapian::docid shard_did = shard_docid(did, n_shards);
105  TermList* res = shard->open_term_list(shard_did);
106  res->shard_index = shard_index;
107  return res;
108 }
109 
110 TermList*
111 MultiDatabase::open_allterms(string_view prefix) const
112 {
113  size_t count = 0;
114  TermList** termlists = new TermList*[shards.size()];
115  try {
116  for (auto&& shard : shards) {
117  termlists[count] = shard->open_allterms(prefix);
118  ++count;
119  }
120  return new MultiAllTermsList(count, termlists);
121  } catch (...) {
122  while (count)
123  delete termlists[--count];
124  delete [] termlists;
125  throw;
126  }
127 }
128 
129 bool
131 {
132  for (auto&& shard : shards) {
133  if (shard->has_positions()) {
134  return true;
135  }
136  }
137  return false;
138 }
139 
142 {
143  auto n_shards = shards.size();
144  auto shard = shards[shard_number(did, n_shards)];
145  auto shard_did = shard_docid(did, n_shards);
146  return shard->open_position_list(shard_did, term);
147 }
148 
151 {
152  Xapian::doccount result = 0;
153  for (auto&& shard : shards) {
154  auto old_result = result;
155  result += shard->get_doccount();
156  if (result < old_result)
157  throw Xapian::DatabaseError("doccount overflowed!");
158  }
159  return result;
160 }
161 
164 {
165  Xapian::docid result = 0;
166  Xapian::doccount n_shards = shards.size();
167  for (Xapian::doccount shard = 0; shard != n_shards; ++shard) {
168  Xapian::docid shard_lastdocid = shards[shard]->get_lastdocid();
169  if (shard_lastdocid == 0) {
170  // This shard is empty, so doesn't influence lastdocid for the
171  // combined database.
172  continue;
173  }
174  result = max(result, unshard(shard_lastdocid, shard, n_shards));
175  }
176  return result;
177 }
178 
181 {
182  Xapian::totallength result = 0;
183  for (auto&& shard : shards) {
184  auto old_result = result;
185  result += shard->get_total_length();
186  if (result < old_result)
187  throw Xapian::DatabaseError("Total document length overflowed!");
188  }
189  return result;
190 }
191 
192 void
194  Xapian::doccount* tf_ptr,
195  Xapian::termcount* cf_ptr) const
196 {
197  Assert(!term.empty());
198 
199  Xapian::doccount shard_tf;
200  Xapian::doccount* shard_tf_ptr = tf_ptr ? &shard_tf : NULL;
201  Xapian::doccount total_tf = 0;
202 
203  Xapian::termcount shard_cf;
204  Xapian::termcount* shard_cf_ptr = cf_ptr ? &shard_cf : NULL;
205  Xapian::termcount total_cf = 0;
206 
207  for (auto&& shard : shards) {
208  shard->get_freqs(term, shard_tf_ptr, shard_cf_ptr);
209  if (shard_tf_ptr) {
210  auto old_tf = total_tf;
211  total_tf += *shard_tf_ptr;
212  if (total_tf < old_tf)
213  throw Xapian::DatabaseError("termfreq overflowed!");
214  }
215  if (shard_cf_ptr) {
216  auto old_cf = total_cf;
217  total_cf += *shard_cf_ptr;
218  if (total_cf < old_cf)
219  throw Xapian::DatabaseError("Collection freq overflowed!");
220  }
221  }
222  if (tf_ptr) {
223  *tf_ptr = total_tf;
224  }
225  if (cf_ptr) {
226  *cf_ptr = total_cf;
227  }
228 }
229 
232 {
233  Xapian::termcount result = 0;
234  for (auto&& shard : shards) {
235  auto old_result = result;
236  result += shard->get_value_freq(slot);
237  if (result < old_result)
238  throw Xapian::DatabaseError("Value freq overflowed!");
239  }
240  return result;
241 }
242 
243 string
245 {
246  string result;
247  for (auto&& shard : shards) {
248  string shard_result = shard->get_value_lower_bound(slot);
249  if (shard_result.empty())
250  continue;
251  if (result.empty() || shard_result < result)
252  result = std::move(shard_result);
253  }
254  return result;
255 }
256 
257 string
259 {
260  string result;
261  for (auto&& shard : shards) {
262  string shard_result = shard->get_value_upper_bound(slot);
263  if (shard_result > result)
264  result = std::move(shard_result);
265  }
266  return result;
267 }
268 
271 {
272  // We want the smallest answer from amongst the shards, except that 0 means
273  // that all documents have length 0 (including the special case of there
274  // being no documents), so any non-zero answer should "beat" 0. To achieve
275  // this we find the *maximum* after negating each of the values (which
276  // since Xapian::termcount is an unsigned type leaves 0 alone but flips the
277  // order of all other values), then negate the answer again at the end.
278  static_assert(std::is_unsigned_v<Xapian::termcount>,
279  "Unsigned type required");
280  Xapian::termcount result = 0;
281  for (auto&& shard : shards) {
282  Xapian::termcount shard_result = shard->get_doclength_lower_bound();
283  result = max(result, negate_unsigned(shard_result));
284  }
285  return negate_unsigned(result);
286 }
287 
290 {
291  Xapian::termcount result = 0;
292  for (auto&& shard : shards) {
293  result = max(result, shard->get_doclength_upper_bound());
294  }
295  return result;
296 }
297 
300 {
301  Assert(!term.empty());
302 
303  Xapian::termcount result = 0;
304  for (auto&& shard : shards) {
305  result = max(result, shard->get_wdf_upper_bound(term));
306  }
307  return result;
308 }
309 
312 {
313  // We want the smallest answer from amongst the shards, except that 0 means
314  // that all documents have no unique terms (including the special case of
315  // there being no documents), so any non-zero answer should "beat" 0. To
316  // achieve this we find the *maximum* after negating each of the values
317  // (which since Xapian::termcount is an unsigned type leaves 0 alone but
318  // flips the order of all other values), then negate the answer again at
319  // the end.
320  static_assert(std::is_unsigned_v<Xapian::termcount>,
321  "Unsigned type required");
322  Xapian::termcount result = 0;
323  for (auto&& shard : shards) {
324  Xapian::termcount shard_result = shard->get_unique_terms_lower_bound();
325  result = max(result, negate_unsigned(shard_result));
326  }
327  return negate_unsigned(result);
328 }
329 
332 {
333  Xapian::termcount result = 0;
334  for (auto&& shard : shards) {
335  result = max(result, shard->get_unique_terms_upper_bound());
336  }
337  return result;
338 }
339 
340 ValueList*
342 {
343  SubValueList** valuelists = new SubValueList*[shards.size()];
344  unsigned count = 0;
345  try {
346  for (auto&& shard : shards) {
347  ValueList* vl = shard->open_value_list(slot);
348  valuelists[count] = new SubValueList(vl, count);
349  ++count;
350  }
351  return new MultiValueList(count, valuelists, slot);
352  } catch (...) {
353  while (count)
354  delete valuelists[--count];
355  delete [] valuelists;
356  throw;
357  }
358 }
359 
362 {
363  Assert(did != 0);
364 
365  auto n_shards = shards.size();
366  auto shard = shards[shard_number(did, n_shards)];
367  auto shard_did = shard_docid(did, n_shards);
368  return shard->get_doclength(shard_did);
369 }
370 
373 {
374  Assert(did != 0);
375 
376  auto n_shards = shards.size();
377  auto shard = shards[shard_number(did, n_shards)];
378  auto shard_did = shard_docid(did, n_shards);
379  return shard->get_unique_terms(shard_did);
380 }
381 
384 {
385  Assert(did != 0);
386 
387  auto n_shards = shards.size();
388  auto shard = shards[shard_number(did, n_shards)];
389  auto shard_did = shard_docid(did, n_shards);
390  return shard->get_wdfdocmax(shard_did);
391 }
392 
395 {
396  Assert(did != 0);
397 
398  auto n_shards = shards.size();
399  auto shard = shards[shard_number(did, n_shards)];
400  auto shard_did = shard_docid(did, n_shards);
401  return shard->open_document(shard_did, lazy);
402 }
403 
404 bool
406 {
407  for (auto&& shard : shards) {
408  if (shard->term_exists(term))
409  return true;
410  }
411  return false;
412 }
413 
414 void
416 {
417  for (auto&& shard : shards) {
418  shard->keep_alive();
419  }
420 }
421 
422 TermList*
424 {
425  vector<TermList*> termlists;
426  termlists.reserve(shards.size());
427 
428  try {
429  for (auto&& shard : shards) {
430  TermList* termlist = shard->open_spelling_termlist(word);
431  if (!termlist)
432  continue;
433  termlists.push_back(termlist);
434  }
435 
436  return make_termlist_merger(termlists);
437  } catch (...) {
438  for (auto&& termlist : termlists)
439  delete termlist;
440  throw;
441  }
442 }
443 
444 TermList*
446 {
447  vector<TermList*> termlists;
448  termlists.reserve(shards.size());
449 
450  try {
451  for (auto&& shard : shards) {
452  TermList* termlist = shard->open_spelling_wordlist();
453  if (!termlist)
454  continue;
455  termlists.push_back(termlist);
456  }
457 
458  return make_termlist_merger<FreqAdderOrTermList>(termlists);
459  } catch (...) {
460  for (auto&& termlist : termlists)
461  delete termlist;
462  throw;
463  }
464 }
465 
468 {
469  Xapian::doccount result = 0;
470  for (auto&& shard : shards) {
471  auto old_result = result;
472  result += shard->get_spelling_frequency(word);
473  if (result < old_result)
474  throw Xapian::DatabaseError("Spelling frequency overflowed!");
475  }
476  return result;
477 }
478 
479 TermList*
481 {
482  vector<TermList*> termlists;
483  termlists.reserve(shards.size());
484 
485  try {
486  for (auto&& shard : shards) {
487  TermList* termlist = shard->open_synonym_termlist(term);
488  if (!termlist)
489  continue;
490  termlists.push_back(termlist);
491  }
492 
493  return make_termlist_merger(termlists);
494  } catch (...) {
495  for (auto&& termlist : termlists)
496  delete termlist;
497  throw;
498  }
499 }
500 
501 TermList*
502 MultiDatabase::open_synonym_keylist(string_view prefix) const
503 {
504  vector<TermList*> termlists;
505  termlists.reserve(shards.size());
506 
507  try {
508  for (auto&& shard : shards) {
509  TermList* termlist = shard->open_synonym_keylist(prefix);
510  if (!termlist)
511  continue;
512  termlists.push_back(termlist);
513  }
514 
515  return make_termlist_merger(termlists);
516  } catch (...) {
517  for (auto&& termlist : termlists)
518  delete termlist;
519  throw;
520  }
521 }
522 
523 string
524 MultiDatabase::get_metadata(string_view key) const
525 {
526  return shards[0]->get_metadata(key);
527 }
528 
529 TermList*
530 MultiDatabase::open_metadata_keylist(string_view prefix) const
531 {
532  return shards[0]->open_metadata_keylist(prefix);
533 }
534 
535 string
537 {
538  string uuid;
539  for (auto&& shard : shards) {
540  const string& sub_uuid = shard->get_uuid();
541  // If any of the sub-databases have no uuid, we can't make a uuid for
542  // the combined database.
543  if (sub_uuid.empty())
544  return sub_uuid;
545  if (!uuid.empty())
546  uuid += ':';
547  uuid += sub_uuid;
548  }
549  return uuid;
550 }
551 
552 bool
554 {
555  for (auto&& shard : shards) {
556  if (shard->locked()) {
557  return true;
558  }
559  }
560  return false;
561 }
562 
563 void
565  std::string_view,
566  bool,
568 {
569  throw Xapian::InvalidOperationError("write_changesets_to_fd() with "
570  "more than one subdatabase");
571 }
572 
575 {
576  throw Xapian::InvalidOperationError("Database::get_revision() with "
577  "more than one subdatabase");
578 }
579 
580 void
582 {
583  // This method should only be called on a single shard.
584  Assert(false);
585 }
586 
587 int
589 {
590  // This method should only be called on a single shard.
591  Assert(false);
592  return BACKEND_UNKNOWN;
593 }
594 
595 void
597 {
598  for (auto&& shard : shards) {
599  shard->commit();
600  }
601 }
602 
603 void
605 {
606  for (auto&& shard : shards) {
607  shard->cancel();
608  }
609 }
610 
611 void
613 {
614  for (auto&& shard : shards) {
615  shard->begin_transaction(flushed);
616  }
617 }
618 
619 void
621 {
622  for (auto&& shard : shards) {
623  shard->end_transaction(do_commit);
624  }
625 }
626 
629 {
630  // With a single shard, add_document() uses docid (get_lastdocid() + 1)
631  // which seems a sensible invariant to preserve with multiple shards.
632  Xapian::docid did = UNSIGNED_OVERFLOW_OK(get_lastdocid() + 1);
633  if (rare(did == 0)) {
634  throw Xapian::DatabaseError("Run out of docids - you'll have to use "
635  "copydatabase to eliminate any gaps "
636  "before you can add more documents");
637  }
638 
639  auto n_shards = shards.size();
640  auto shard = shards[shard_number(did, n_shards)];
641  shard->replace_document(shard_docid(did, n_shards), doc);
642  return did;
643 }
644 
645 void
647 {
648  auto n_shards = shards.size();
649  auto shard = shards[shard_number(did, n_shards)];
650  shard->delete_document(shard_docid(did, n_shards));
651 }
652 
653 void
655 {
656  for (auto&& shard : shards) {
657  shard->delete_document(term);
658  }
659 }
660 
661 void
663 {
664  auto n_shards = shards.size();
665  auto shard = shards[shard_number(did, n_shards)];
666  shard->replace_document(shard_docid(did, n_shards), doc);
667 }
668 
671 {
672  auto n_shards = shards.size();
673  unique_ptr<PostList> pl(open_post_list(term));
674  if (!pl || (pl->next(), pl->at_end())) {
675  // unique_term not in the database, so this is just an add_document().
676  // Calculate which shard the next never used docid maps to.
677  Xapian::docid did = UNSIGNED_OVERFLOW_OK(get_lastdocid() + 1);
678  if (rare(did == 0)) {
679  throw Xapian::DatabaseError("Run out of docids - you'll have to "
680  "use copydatabase to eliminate any "
681  "gaps before you can add more "
682  "documents");
683  }
684  auto shard = shards[shard_number(did, n_shards)];
685  return shard->add_document(doc);
686  }
687 
688  Xapian::docid result = pl->get_docid();
689  auto replacing_shard = shards[shard_number(result, n_shards)];
690  replacing_shard->replace_document(shard_docid(result, n_shards), doc);
691 
692  // Delete any other occurrences of the unique term.
693  while (pl->next(), !pl->at_end()) {
694  Xapian::docid did = pl->get_docid();
695  auto shard = shards[shard_number(did, n_shards)];
696  shard->delete_document(shard_docid(did, n_shards));
697  }
698 
699  return result;
700 }
701 
702 void
704 {
705  Assert(did != 0);
706 
707  auto n_shards = shards.size();
708  auto shard = shards[shard_number(did, n_shards)];
709  auto shard_did = shard_docid(did, n_shards);
710  shard->request_document(shard_did);
711 }
712 
713 void
715  Xapian::termcount freqinc) const
716 {
717  shards[0]->add_spelling(word, freqinc);
718 }
719 
722  Xapian::termcount freqdec) const
723 {
724  for (auto&& shard : shards) {
725  freqdec = shard->remove_spelling(word, freqdec);
726  if (freqdec == 0)
727  break;
728  }
729  return freqdec;
730 }
731 
732 void
734  string_view synonym) const
735 {
736  shards[0]->add_synonym(term, synonym);
737 }
738 
739 void
741  string_view synonym) const
742 {
743  for (auto&& shard : shards) {
744  shard->remove_synonym(term, synonym);
745  }
746 }
747 
748 void
750 {
751  for (auto&& shard : shards) {
752  shard->clear_synonyms(term);
753  }
754 }
755 
756 void
757 MultiDatabase::set_metadata(string_view key, string_view value)
758 {
759  shards[0]->set_metadata(key, value);
760 }
761 
762 string
764  size_t length,
765  string_view prefix,
766  Xapian::termpos start_pos,
767  Xapian::termpos end_pos) const
768 {
769  Assert(did != 0);
770 
771  auto n_shards = shards.size();
772  auto shard = shards[shard_number(did, n_shards)];
773  auto shard_did = shard_docid(did, n_shards);
774  return shard->reconstruct_text(shard_did, length, prefix,
775  start_pos, end_pos);
776 }
777 
778 string
780 {
781  string desc;
782  for (auto&& shard : shards) {
783  if (!desc.empty()) {
784  desc += ", ";
785  }
786  desc += shard->get_description();
787  }
788  desc += ')';
789  return desc;
790 }
BACKEND_* constants.
@ BACKEND_UNKNOWN
Definition: backends.h:26
Cast a value to a type, clamping out of range values.
Abstract base class for leaf postlists.
Definition: leafpostlist.h:40
Class for merging AllTermsList objects from subdatabases.
Xapian::docid get_lastdocid() const
Return the last used document id of this (sub) database.
bool locked() const
Return true if the database is open for writing.
Xapian::totallength get_total_length() const
Return the total length of all documents in this database.
std::string get_value_upper_bound(Xapian::valueno slot) const
Get an upper bound on the values stored in the given value slot.
Xapian::termcount get_doclength(Xapian::docid did) const
TermList * open_synonym_termlist(std::string_view term) const
Open a termlist returning synonyms for a term.
Xapian::doccount get_spelling_frequency(std::string_view word) const
Return the number of times word was added as a spelling.
void add_spelling(std::string_view word, Xapian::termcount freqinc) const
Add a word to the spelling dictionary.
PostList * open_post_list(std::string_view term) const
Return a PostList suitable for use in a PostingIterator.
std::string get_value_lower_bound(Xapian::valueno slot) const
Get a lower bound on the values stored in the given value slot.
size_type size() const
TermList * open_allterms(std::string_view prefix) const
TermList * open_metadata_keylist(std::string_view prefix) const
Open a termlist returning each metadata key.
TermList * open_term_list(Xapian::docid did) const
std::string get_uuid() const
Get a UUID for the database.
Xapian::rev get_revision() const
Get revision number of database (if meaningful).
bool term_exists(std::string_view term) const
Xapian::termcount remove_spelling(std::string_view word, Xapian::termcount freqdec) const
Remove a word from the spelling dictionary.
LeafPostList * open_leaf_post_list(std::string_view term, bool need_read_pos) const
Create a LeafPostList for use during a match.
void clear_synonyms(std::string_view term) const
Clear all synonyms for a term.
bool has_positions() const
Check whether this database contains any positional information.
Xapian::termcount get_unique_terms(Xapian::docid did) const
Get the number of unique terms in document.
Xapian::termcount get_wdfdocmax(Xapian::docid did) const
Get the max wdf in document.
std::string get_metadata(std::string_view key) const
Get the metadata associated with a given key.
void add_synonym(std::string_view term, std::string_view synonym) const
Add a synonym for a term.
Xapian::termcount get_doclength_lower_bound() const
Get a lower bound on the length of a document in this DB.
TermList * open_spelling_termlist(std::string_view word) const
Create a termlist tree from trigrams of word.
std::string reconstruct_text(Xapian::docid did, size_t length, std::string_view prefix, Xapian::termpos start_pos, Xapian::termpos end_pos) const
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
TermList * open_synonym_keylist(std::string_view prefix) const
Open a termlist returning each term which has synonyms.
void invalidate_doc_object(Xapian::Document::Internal *obj) const
Notify the database that document is no longer valid.
PositionList * open_position_list(Xapian::docid did, std::string_view term) const
Xapian::termcount get_wdf_upper_bound(std::string_view term) const
Get an upper bound on the wdf of term term.
ValueList * open_value_list(Xapian::valueno slot) const
Open a value stream.
Xapian::doccount get_doccount() const
int get_backend_info(std::string *path) const
Get backend information about this database.
void remove_synonym(std::string_view term, std::string_view synonym) const
Remove a synonym for a term.
void request_document(Xapian::docid did) const
Request a document.
Xapian::docid add_document(const Xapian::Document &doc)
void end_transaction(bool do_commit)
End transaction.
void commit()
Commit pending modifications to the database.
void begin_transaction(bool flushed)
Begin transaction.
Xapian::termcount get_unique_terms_upper_bound() const
Get an upper bound on the unique terms size of a document in this DB.
void delete_document(Xapian::docid did)
Xapian::doccount get_value_freq(Xapian::valueno slot) const
Return the frequency of a given value slot.
void set_metadata(std::string_view key, std::string_view value)
Set the metadata associated with a given key.
TermList * open_spelling_wordlist() const
Return a termlist which returns the words which are spelling correction targets.
void cancel()
Cancel pending modifications to the database.
Xapian::termcount get_unique_terms_lower_bound() const
Get a lower bound on the unique terms size of a document in this DB.
Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy) const
Open a handle on a document.
bool reopen()
Reopen the database to the latest available revision.
void replace_document(Xapian::docid did, const Xapian::Document &doc)
void write_changesets_to_fd(int fd, std::string_view start_revision, bool need_whole_db, Xapian::ReplicationInfo *info)
Write a set of changesets to a file descriptor.
std::string get_description() const
Return a string describing this object.
TermList * open_term_list_direct(Xapian::docid did) const
Like open_term_list() but without MultiTermList wrapper.
void close()
Close the database.
void get_freqs(std::string_view term, Xapian::doccount *tf_ptr, Xapian::termcount *cf_ptr) const
Returns frequencies for a term.
Class for merging PostList objects from subdatabases.
Adapter class for a TermList in a multidatabase.
Class for merging ValueList objects from subdatabases.
DatabaseError indicates some sort of database related error.
Definition: error.h:355
Abstract base class for a document.
Class representing a document.
Definition: document.h:64
Abstract base class for postlists.
Definition: postlist.h:40
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:271
Abstract base class for iterating term positions in a document.
Definition: positionlist.h:32
Abstract base class for termlists.
Definition: termlist.h:42
size_t shard_index
Which shard of a multidatabase this is from.
Definition: termlist.h:126
Abstract base class for value streams.
Definition: valuelist.h:31
#define UNSIGNED_OVERFLOW_OK(X)
Definition: config.h:635
#define rare(COND)
Definition: config.h:616
string term
Multi-database support functions.
Xapian::doccount shard_number(Xapian::docid did, Xapian::doccount n_shards)
Convert docid in the multi-db to shard number.
Definition: multi.h:49
Xapian::docid shard_docid(Xapian::docid did, Xapian::doccount n_shards)
Convert docid in the multi-db to the docid in the shard.
Definition: multi.h:35
Xapian::docid unshard(Xapian::docid shard_did, Xapian::doccount shard, Xapian::doccount n_shards)
Convert shard number and shard docid to docid in multi-db.
Definition: multi.h:64
Class for merging AllTermsList objects from subdatabases.
Sharded database backend.
Class for merging PostList objects from subdatabases.
Adapter class for a TermList in a multidatabase.
Class for merging ValueList objects from subdatabases.
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:64
XAPIAN_REVISION_TYPE rev
Revision number of a database.
Definition: types.h:106
unsigned valueno
The number for a value slot in a document.
Definition: types.h:90
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:37
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:51
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
XAPIAN_TOTALLENGTH_TYPE totallength
The total length of all documents in a database.
Definition: types.h:112
Negate unsigned integer, avoiding compiler warnings.
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > negate_unsigned(T value)
#define Assert(COND)
Definition: omassert.h:122
Merge two TermList objects using an OR operation.
Information about the steps involved in performing a replication.
Definition: replication.h:32
Build tree to merge TermList objects.
TermList * make_termlist_merger(std::vector< TermList * > &termlists)