xapian-core  2.0.0
multi_database.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2017,2019,2020,2022,2024 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 "expand/ortermlist.h"
26 #include "expand/termlistmerger.h"
27 #include "multi_alltermslist.h"
28 #include "multi_postlist.h"
29 #include "multi_termlist.h"
30 #include "multi_valuelist.h"
31 #include "negate_unsigned.h"
32 
33 #include <memory>
34 #include <string_view>
35 
36 using namespace std;
37 
40 {
41  return shards.size();
42 }
43 
44 bool
46 {
47  bool result = false;
48  for (auto&& shard : shards) {
49  if (shard->reopen()) {
50  result = true;
51  }
52  }
53  return result;
54 }
55 
56 void
58 {
59  for (auto&& shard : shards) {
60  shard->close();
61  }
62 }
63 
64 PostList*
66 {
67  PostList** postlists = new PostList*[shards.size()];
68  size_t count = 0;
69  try {
70  for (auto&& shard : shards) {
71  postlists[count] = shard->open_post_list(term);
72  ++count;
73  }
74  return new MultiPostList(count, postlists);
75  } catch (...) {
76  while (count)
77  delete postlists[--count];
78  delete [] postlists;
79  throw;
80  }
81 }
82 
84 MultiDatabase::open_leaf_post_list(string_view, bool) const
85 {
86  // This should never get called.
87  Assert(false);
88  return NULL;
89 }
90 
91 TermList*
93 {
95 }
96 
97 TermList*
99 {
100  Xapian::doccount n_shards = shards.size();
101  auto shard_index = shard_number(did, n_shards);
102  auto shard = shards[shard_index];
103  Xapian::docid shard_did = shard_docid(did, n_shards);
104  TermList* res = shard->open_term_list(shard_did);
105  res->shard_index = shard_index;
106  return res;
107 }
108 
109 TermList*
110 MultiDatabase::open_allterms(string_view prefix) const
111 {
112  size_t count = 0;
113  TermList** termlists = new TermList*[shards.size()];
114  try {
115  for (auto&& shard : shards) {
116  termlists[count] = shard->open_allterms(prefix);
117  ++count;
118  }
119  return new MultiAllTermsList(count, termlists);
120  } catch (...) {
121  while (count)
122  delete termlists[--count];
123  delete [] termlists;
124  throw;
125  }
126 }
127 
128 bool
130 {
131  for (auto&& shard : shards) {
132  if (shard->has_positions()) {
133  return true;
134  }
135  }
136  return false;
137 }
138 
141 {
142  auto n_shards = shards.size();
143  auto shard = shards[shard_number(did, n_shards)];
144  auto shard_did = shard_docid(did, n_shards);
145  return shard->open_position_list(shard_did, term);
146 }
147 
150 {
151  Xapian::doccount result = 0;
152  for (auto&& shard : shards) {
153  auto old_result = result;
154  result += shard->get_doccount();
155  if (result < old_result)
156  throw Xapian::DatabaseError("doccount overflowed!");
157  }
158  return result;
159 }
160 
163 {
164  Xapian::docid result = 0;
165  Xapian::doccount n_shards = shards.size();
166  for (Xapian::doccount shard = 0; shard != n_shards; ++shard) {
167  Xapian::docid shard_lastdocid = shards[shard]->get_lastdocid();
168  if (shard_lastdocid == 0) {
169  // This shard is empty, so doesn't influence lastdocid for the
170  // combined database.
171  continue;
172  }
173  result = max(result, unshard(shard_lastdocid, shard, n_shards));
174  }
175  return result;
176 }
177 
180 {
181  Xapian::totallength result = 0;
182  for (auto&& shard : shards) {
183  auto old_result = result;
184  result += shard->get_total_length();
185  if (result < old_result)
186  throw Xapian::DatabaseError("Total document length overflowed!");
187  }
188  return result;
189 }
190 
191 void
193  Xapian::doccount* tf_ptr,
194  Xapian::termcount* cf_ptr) const
195 {
196  Assert(!term.empty());
197 
198  Xapian::doccount shard_tf;
199  Xapian::doccount* shard_tf_ptr = tf_ptr ? &shard_tf : NULL;
200  Xapian::doccount total_tf = 0;
201 
202  Xapian::termcount shard_cf;
203  Xapian::termcount* shard_cf_ptr = cf_ptr ? &shard_cf : NULL;
204  Xapian::termcount total_cf = 0;
205 
206  for (auto&& shard : shards) {
207  shard->get_freqs(term, shard_tf_ptr, shard_cf_ptr);
208  if (shard_tf_ptr) {
209  auto old_tf = total_tf;
210  total_tf += *shard_tf_ptr;
211  if (total_tf < old_tf)
212  throw Xapian::DatabaseError("termfreq overflowed!");
213  }
214  if (shard_cf_ptr) {
215  auto old_cf = total_cf;
216  total_cf += *shard_cf_ptr;
217  if (total_cf < old_cf)
218  throw Xapian::DatabaseError("Collection freq overflowed!");
219  }
220  }
221  if (tf_ptr) {
222  *tf_ptr = total_tf;
223  }
224  if (cf_ptr) {
225  *cf_ptr = total_cf;
226  }
227 }
228 
231 {
232  Xapian::termcount result = 0;
233  for (auto&& shard : shards) {
234  auto old_result = result;
235  result += shard->get_value_freq(slot);
236  if (result < old_result)
237  throw Xapian::DatabaseError("Value freq overflowed!");
238  }
239  return result;
240 }
241 
242 string
244 {
245  string result;
246  for (auto&& shard : shards) {
247  string shard_result = shard->get_value_lower_bound(slot);
248  if (shard_result.empty())
249  continue;
250  if (result.empty() || shard_result < result)
251  result = std::move(shard_result);
252  }
253  return result;
254 }
255 
256 string
258 {
259  string result;
260  for (auto&& shard : shards) {
261  string shard_result = shard->get_value_upper_bound(slot);
262  if (shard_result > result)
263  result = std::move(shard_result);
264  }
265  return result;
266 }
267 
270 {
271  // We want the smallest answer from amongst the shards, except that 0 means
272  // that all documents have length 0 (including the special case of there
273  // being no documents), so any non-zero answer should "beat" 0. To achieve
274  // this we find the *maximum* after negating each of the values (which
275  // since Xapian::termcount is an unsigned type leaves 0 alone but flips the
276  // order of all other values), then negate the answer again at the end.
277  static_assert(std::is_unsigned_v<Xapian::termcount>,
278  "Unsigned type required");
279  Xapian::termcount result = 0;
280  for (auto&& shard : shards) {
281  Xapian::termcount shard_result = shard->get_doclength_lower_bound();
282  result = max(result, negate_unsigned(shard_result));
283  }
284  return negate_unsigned(result);
285 }
286 
289 {
290  Xapian::termcount result = 0;
291  for (auto&& shard : shards) {
292  result = max(result, shard->get_doclength_upper_bound());
293  }
294  return result;
295 }
296 
299 {
300  Assert(!term.empty());
301 
302  Xapian::termcount result = 0;
303  for (auto&& shard : shards) {
304  result = max(result, shard->get_wdf_upper_bound(term));
305  }
306  return result;
307 }
308 
311 {
312  // We want the smallest answer from amongst the shards, except that 0 means
313  // that all documents have no unique terms (including the special case of
314  // there being no documents), so any non-zero answer should "beat" 0. To
315  // achieve this we find the *maximum* after negating each of the values
316  // (which since Xapian::termcount is an unsigned type leaves 0 alone but
317  // flips the order of all other values), then negate the answer again at
318  // the end.
319  static_assert(std::is_unsigned_v<Xapian::termcount>,
320  "Unsigned type required");
321  Xapian::termcount result = 0;
322  for (auto&& shard : shards) {
323  Xapian::termcount shard_result = shard->get_unique_terms_lower_bound();
324  result = max(result, negate_unsigned(shard_result));
325  }
326  return negate_unsigned(result);
327 }
328 
331 {
332  Xapian::termcount result = 0;
333  for (auto&& shard : shards) {
334  result = max(result, shard->get_unique_terms_upper_bound());
335  }
336  return result;
337 }
338 
339 ValueList*
341 {
342  SubValueList** valuelists = new SubValueList*[shards.size()];
343  unsigned count = 0;
344  try {
345  for (auto&& shard : shards) {
346  ValueList* vl = shard->open_value_list(slot);
347  valuelists[count] = new SubValueList(vl, count);
348  ++count;
349  }
350  return new MultiValueList(count, valuelists, slot);
351  } catch (...) {
352  while (count)
353  delete valuelists[--count];
354  delete [] valuelists;
355  throw;
356  }
357 }
358 
361 {
362  Assert(did != 0);
363 
364  auto n_shards = shards.size();
365  auto shard = shards[shard_number(did, n_shards)];
366  auto shard_did = shard_docid(did, n_shards);
367  return shard->get_doclength(shard_did);
368 }
369 
372 {
373  Assert(did != 0);
374 
375  auto n_shards = shards.size();
376  auto shard = shards[shard_number(did, n_shards)];
377  auto shard_did = shard_docid(did, n_shards);
378  return shard->get_unique_terms(shard_did);
379 }
380 
383 {
384  Assert(did != 0);
385 
386  auto n_shards = shards.size();
387  auto shard = shards[shard_number(did, n_shards)];
388  auto shard_did = shard_docid(did, n_shards);
389  return shard->get_wdfdocmax(shard_did);
390 }
391 
394 {
395  Assert(did != 0);
396 
397  auto n_shards = shards.size();
398  auto shard = shards[shard_number(did, n_shards)];
399  auto shard_did = shard_docid(did, n_shards);
400  return shard->open_document(shard_did, lazy);
401 }
402 
403 bool
405 {
406  for (auto&& shard : shards) {
407  if (shard->term_exists(term))
408  return true;
409  }
410  return false;
411 }
412 
413 void
415 {
416  for (auto&& shard : shards) {
417  shard->keep_alive();
418  }
419 }
420 
421 TermList*
423 {
424  vector<TermList*> termlists;
425  termlists.reserve(shards.size());
426 
427  try {
428  for (auto&& shard : shards) {
429  TermList* termlist = shard->open_spelling_termlist(word);
430  if (!termlist)
431  continue;
432  termlists.push_back(termlist);
433  }
434 
435  return make_termlist_merger(termlists);
436  } catch (...) {
437  for (auto&& termlist : termlists)
438  delete termlist;
439  throw;
440  }
441 }
442 
443 TermList*
445 {
446  vector<TermList*> termlists;
447  termlists.reserve(shards.size());
448 
449  try {
450  for (auto&& shard : shards) {
451  TermList* termlist = shard->open_spelling_wordlist();
452  if (!termlist)
453  continue;
454  termlists.push_back(termlist);
455  }
456 
457  return make_termlist_merger<FreqAdderOrTermList>(termlists);
458  } catch (...) {
459  for (auto&& termlist : termlists)
460  delete termlist;
461  throw;
462  }
463 }
464 
467 {
468  Xapian::doccount result = 0;
469  for (auto&& shard : shards) {
470  auto old_result = result;
471  result += shard->get_spelling_frequency(word);
472  if (result < old_result)
473  throw Xapian::DatabaseError("Spelling frequency overflowed!");
474  }
475  return result;
476 }
477 
478 TermList*
480 {
481  vector<TermList*> termlists;
482  termlists.reserve(shards.size());
483 
484  try {
485  for (auto&& shard : shards) {
486  TermList* termlist = shard->open_synonym_termlist(term);
487  if (!termlist)
488  continue;
489  termlists.push_back(termlist);
490  }
491 
492  return make_termlist_merger(termlists);
493  } catch (...) {
494  for (auto&& termlist : termlists)
495  delete termlist;
496  throw;
497  }
498 }
499 
500 TermList*
501 MultiDatabase::open_synonym_keylist(string_view prefix) const
502 {
503  vector<TermList*> termlists;
504  termlists.reserve(shards.size());
505 
506  try {
507  for (auto&& shard : shards) {
508  TermList* termlist = shard->open_synonym_keylist(prefix);
509  if (!termlist)
510  continue;
511  termlists.push_back(termlist);
512  }
513 
514  return make_termlist_merger(termlists);
515  } catch (...) {
516  for (auto&& termlist : termlists)
517  delete termlist;
518  throw;
519  }
520 }
521 
522 string
523 MultiDatabase::get_metadata(string_view key) const
524 {
525  return shards[0]->get_metadata(key);
526 }
527 
528 TermList*
529 MultiDatabase::open_metadata_keylist(string_view prefix) const
530 {
531  return shards[0]->open_metadata_keylist(prefix);
532 }
533 
534 string
536 {
537  string uuid;
538  for (auto&& shard : shards) {
539  const string& sub_uuid = shard->get_uuid();
540  // If any of the sub-databases have no uuid, we can't make a uuid for
541  // the combined database.
542  if (sub_uuid.empty())
543  return sub_uuid;
544  if (!uuid.empty())
545  uuid += ':';
546  uuid += sub_uuid;
547  }
548  return uuid;
549 }
550 
551 bool
553 {
554  for (auto&& shard : shards) {
555  if (shard->locked()) {
556  return true;
557  }
558  }
559  return false;
560 }
561 
562 void
564  std::string_view,
565  bool,
567 {
568  throw Xapian::InvalidOperationError("write_changesets_to_fd() with "
569  "more than one subdatabase");
570 }
571 
574 {
575  throw Xapian::InvalidOperationError("Database::get_revision() with "
576  "more than one subdatabase");
577 }
578 
579 void
581 {
582  // This method should only be called on a single shard.
583  Assert(false);
584 }
585 
586 int
588 {
589  // This method should only be called on a single shard.
590  Assert(false);
591  return BACKEND_UNKNOWN;
592 }
593 
594 void
596 {
597  for (auto&& shard : shards) {
598  shard->commit();
599  }
600 }
601 
602 void
604 {
605  for (auto&& shard : shards) {
606  shard->cancel();
607  }
608 }
609 
610 void
612 {
613  for (auto&& shard : shards) {
614  shard->begin_transaction(flushed);
615  }
616 }
617 
618 void
620 {
621  for (auto&& shard : shards) {
622  shard->end_transaction(do_commit);
623  }
624 }
625 
628 {
629  // With a single shard, add_document() uses docid (get_lastdocid() + 1)
630  // which seems a sensible invariant to preserve with multiple shards.
631  Xapian::docid did = UNSIGNED_OVERFLOW_OK(get_lastdocid() + 1);
632  if (rare(did == 0)) {
633  throw Xapian::DatabaseError("Run out of docids - you'll have to use "
634  "copydatabase to eliminate any gaps "
635  "before you can add more documents");
636  }
637 
638  auto n_shards = shards.size();
639  auto shard = shards[shard_number(did, n_shards)];
640  shard->replace_document(shard_docid(did, n_shards), doc);
641  return did;
642 }
643 
644 void
646 {
647  auto n_shards = shards.size();
648  auto shard = shards[shard_number(did, n_shards)];
649  shard->delete_document(shard_docid(did, n_shards));
650 }
651 
652 void
654 {
655  for (auto&& shard : shards) {
656  shard->delete_document(term);
657  }
658 }
659 
660 void
662 {
663  auto n_shards = shards.size();
664  auto shard = shards[shard_number(did, n_shards)];
665  shard->replace_document(shard_docid(did, n_shards), doc);
666 }
667 
670 {
671  auto n_shards = shards.size();
672  unique_ptr<PostList> pl(open_post_list(term));
673  if (!pl || (pl->next(), pl->at_end())) {
674  // unique_term not in the database, so this is just an add_document().
675  // Calculate which shard the next never used docid maps to.
676  Xapian::docid did = UNSIGNED_OVERFLOW_OK(get_lastdocid() + 1);
677  if (rare(did == 0)) {
678  throw Xapian::DatabaseError("Run out of docids - you'll have to "
679  "use copydatabase to eliminate any "
680  "gaps before you can add more "
681  "documents");
682  }
683  auto shard = shards[shard_number(did, n_shards)];
684  return shard->add_document(doc);
685  }
686 
687  Xapian::docid result = pl->get_docid();
688  auto replacing_shard = shards[shard_number(result, n_shards)];
689  replacing_shard->replace_document(shard_docid(result, n_shards), doc);
690 
691  // Delete any other occurrences of the unique term.
692  while (pl->next(), !pl->at_end()) {
693  Xapian::docid did = pl->get_docid();
694  auto shard = shards[shard_number(did, n_shards)];
695  shard->delete_document(shard_docid(did, n_shards));
696  }
697 
698  return result;
699 }
700 
701 void
703 {
704  Assert(did != 0);
705 
706  auto n_shards = shards.size();
707  auto shard = shards[shard_number(did, n_shards)];
708  auto shard_did = shard_docid(did, n_shards);
709  shard->request_document(shard_did);
710 }
711 
712 void
714  Xapian::termcount freqinc) const
715 {
716  shards[0]->add_spelling(word, freqinc);
717 }
718 
721  Xapian::termcount freqdec) const
722 {
723  for (auto&& shard : shards) {
724  freqdec = shard->remove_spelling(word, freqdec);
725  if (freqdec == 0)
726  break;
727  }
728  return freqdec;
729 }
730 
731 void
733  string_view synonym) const
734 {
735  shards[0]->add_synonym(term, synonym);
736 }
737 
738 void
740  string_view synonym) const
741 {
742  for (auto&& shard : shards) {
743  shard->remove_synonym(term, synonym);
744  }
745 }
746 
747 void
749 {
750  for (auto&& shard : shards) {
751  shard->clear_synonyms(term);
752  }
753 }
754 
755 void
756 MultiDatabase::set_metadata(string_view key, string_view value)
757 {
758  shards[0]->set_metadata(key, value);
759 }
760 
761 string
763  size_t length,
764  string_view prefix,
765  Xapian::termpos start_pos,
766  Xapian::termpos end_pos) const
767 {
768  Assert(did != 0);
769 
770  auto n_shards = shards.size();
771  auto shard = shards[shard_number(did, n_shards)];
772  auto shard_did = shard_docid(did, n_shards);
773  return shard->reconstruct_text(shard_did, length, prefix,
774  start_pos, end_pos);
775 }
776 
777 string
779 {
780  string desc;
781  for (auto&& shard : shards) {
782  if (!desc.empty()) {
783  desc += ", ";
784  }
785  desc += shard->get_description();
786  }
787  desc += ')';
788  return desc;
789 }
BACKEND_* constants.
@ BACKEND_UNKNOWN
Definition: backends.h:26
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:626
#define rare(COND)
Definition: config.h:607
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:108
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:114
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)