xapian-core  2.1.0
postlisttree.h
Go to the documentation of this file.
1 
4 /* Copyright 2017,2019,2026 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (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  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see
18  * <https://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef XAPIAN_INCLUDED_POSTLISTTREE_H
22 #define XAPIAN_INCLUDED_POSTLISTTREE_H
23 
24 #include "backends/multi.h"
25 #include "backends/postlist.h"
26 #include "valuestreamdocument.h"
27 
28 class PostListTree {
29  PostList* pl = NULL;
30 
31  bool use_cached_max_weight = false;
32 
34 
36 
38 
39  double max_weight;
40 
43 
50  PostList** shard_pls = nullptr;
51 
63  double* max_after = nullptr;
64 
67 
74 
76 
78 
79  public:
81  Xapian::Database& db_,
82  const Xapian::Weight& wtscheme)
83  : need_doclength(wtscheme.get_sumpart_needs_doclength_()),
84  need_unique_terms(wtscheme.get_sumpart_needs_uniqueterms_()),
85  need_wdfdocmax(wtscheme.get_sumpart_needs_wdfdocmax_()),
86  vsdoc(vsdoc_),
87  db(db_) {}
88 
91  for (Xapian::doccount i = 0; i != n_shards; ++i)
92  delete shard_pls[i];
93  n_shards = 0;
94  shard_pls = nullptr;
95  delete[] max_after;
96  max_after = nullptr;
97  }
98 
101  }
102 
108 
109  double set_postlists(PostList** pls, Xapian::doccount n_shards_) {
110  shard_pls = pls;
111  n_shards = n_shards_;
112  while (shard_pls[current_shard] == NULL) {
113  ++current_shard;
115  }
117  shard_db = db.internal.get();
118  if (n_shards > 1) {
119  auto multidb = static_cast<const MultiDatabase*>(shard_db);
120  shard_db = multidb->shards[current_shard];
121  }
122  if (current_shard > 0)
124  max_after = new double[n_shards];
125  double m = 0.0;
127  do {
128  --i;
129  max_after[i] = m;
130  if (shard_pls[i])
131  m = std::max(m, shard_pls[i]->recalc_maxweight());
132  } while (i > 0);
133  max_weight = m;
134  use_cached_max_weight = true;
135  return m;
136  }
137 
138  double recalc_maxweight() {
139  if (!use_cached_max_weight) {
140  double m = max_after[current_shard];
141  if (max_weight > m) {
143  max_weight = std::max(w, m);
144  } else {
145  // The max_weight value is already tight on
146  // max_after[current_shard] so we know that max_weight can't
147  // reduce for this shard.
148  }
149  use_cached_max_weight = true;
150  }
151  return max_weight;
152  }
153 
154  void force_recalc() {
155  use_cached_max_weight = false;
156  }
157 
160  }
161 
163  return shard_db->get_doclength(shard_did);
164  }
165 
166  double get_weight() const {
167  Xapian::termcount doclen = 0, unique_terms = 0, wdfdocmax = 0;
168  get_doc_stats(pl->get_docid(), doclen, unique_terms, wdfdocmax);
169  return pl->get_weight(doclen, unique_terms, wdfdocmax);
170  }
171 
173  bool next(double w_min) {
174  if (w_min > 0.0 && recalc_maxweight() < w_min) {
175  // We can't now achieve w_min so we're done.
176  return false;
177  }
178 
179  while (true) {
180  PostList* result = pl->next(w_min);
181  if (rare(result)) {
182  delete pl;
183  shard_pls[current_shard] = pl = result;
184  if (usual(!pl->at_end())) {
185  if (w_min > 0.0) {
186  use_cached_max_weight = false;
187  if (recalc_maxweight() < w_min) {
188  // We can't now achieve w_min so we're done.
189  return false;
190  }
191  }
192  return true;
193  }
194  } else {
195  if (usual(!pl->at_end())) {
196  return true;
197  }
198  }
199 
200  do {
201  if (++current_shard == n_shards)
202  return false;
203  } while (shard_pls[current_shard] == NULL);
205  shard_db = db.internal.get();
206  if (n_shards > 1) {
207  auto multidb = static_cast<const MultiDatabase*>(shard_db);
208  shard_db = multidb->shards[current_shard];
209  }
211  use_cached_max_weight = false;
212  }
213  }
214 
215  void get_doc_stats(Xapian::docid shard_did,
216  Xapian::termcount& doclen,
217  Xapian::termcount& unique_terms,
218  Xapian::termcount& wdfdocmax) const {
219  // Fetching the document length and number of unique terms is work we
220  // can avoid if the weighting scheme doesn't use them.
222  if (need_doclength)
223  doclen = shard_db->get_doclength(shard_did);
224  if (need_unique_terms)
225  unique_terms = shard_db->get_unique_terms(shard_did);
226  if (need_wdfdocmax)
227  wdfdocmax = shard_db->get_wdfdocmax(shard_did);
228  }
229  }
230 
232  return pl->count_matching_subqs();
233  }
234 
235  std::string get_description() const {
236  std::string desc = "PostListTree(";
237  for (Xapian::doccount i = 0; i != n_shards; ++i) {
238  if (i == current_shard)
239  desc += '*';
240  if (shard_pls[i]) {
241  desc += shard_pls[i]->get_description();
242  desc += ',';
243  } else {
244  desc += "NULL,";
245  }
246  }
247  desc.back() = ')';
248  return desc;
249  }
250 };
251 
252 #endif // XAPIAN_INCLUDED_POSTLISTTREE_H
Sharded database backend.
Xapian::Database::Internal * shard_db
Definition: postlisttree.h:77
Xapian::doccount n_shards
The number of shards.
Definition: postlisttree.h:66
Xapian::Database & db
Definition: postlisttree.h:75
bool need_wdfdocmax
Definition: postlisttree.h:37
PostList * pl
Definition: postlisttree.h:29
bool need_doclength
Definition: postlisttree.h:33
PostList ** shard_pls
The postlists for the shards.
Definition: postlisttree.h:50
double set_postlists(PostList **pls, Xapian::doccount n_shards_)
Definition: postlisttree.h:109
bool need_unique_terms
Definition: postlisttree.h:35
Xapian::termcount get_doclength(Xapian::docid shard_did) const
Definition: postlisttree.h:162
void force_recalc()
Definition: postlisttree.h:154
Xapian::docid get_docid() const
Definition: postlisttree.h:158
bool * get_max_weight_cached_flag_ptr()
Return pointer to flag to set to false to invalidate cached max weight.
Definition: postlisttree.h:107
ValueStreamDocument & vsdoc
Document proxy used for valuestream caching.
Definition: postlisttree.h:73
double recalc_maxweight()
Definition: postlisttree.h:138
double max_weight
Definition: postlisttree.h:39
double * max_after
The maximum weight any shards after each index could return.
Definition: postlisttree.h:63
Xapian::termcount count_matching_subqs() const
Definition: postlisttree.h:231
void get_doc_stats(Xapian::docid shard_did, Xapian::termcount &doclen, Xapian::termcount &unique_terms, Xapian::termcount &wdfdocmax) const
Definition: postlisttree.h:215
std::string get_description() const
Definition: postlisttree.h:235
bool next(double w_min)
Return false if we're done.
Definition: postlisttree.h:173
double get_weight() const
Definition: postlisttree.h:166
Xapian::doccount current_shard
The current shard.
Definition: postlisttree.h:42
PostListTree(ValueStreamDocument &vsdoc_, Xapian::Database &db_, const Xapian::Weight &wtscheme)
Definition: postlisttree.h:80
void delete_postlists()
Delete all the PostList objects.
Definition: postlisttree.h:90
bool use_cached_max_weight
Definition: postlisttree.h:31
A document which gets its values from a ValueStreamManager.
void new_shard(Xapian::doccount n)
Virtual base class for Database internals.
virtual termcount get_wdfdocmax(docid did) const =0
Get the max wdf in document.
virtual termcount get_doclength(docid did) const =0
virtual termcount get_unique_terms(docid did) const =0
Get the number of unique terms in document.
An indexed database of documents.
Definition: database.h:75
Xapian::Internal::intrusive_ptr_nonnull< Internal > internal
Definition: database.h:95
Abstract base class for postlists.
Definition: postlist.h:40
virtual PostList * next(double w_min)=0
Advance the current position to the next document in the postlist.
virtual Xapian::docid get_docid() const =0
Return the current docid.
virtual double recalc_maxweight()=0
Recalculate the upper bound on what get_weight() can return.
virtual bool at_end() const =0
Return true if the current position is past the last entry in this list.
virtual std::string get_description() const =0
Return a string description of this object.
virtual double get_weight(Xapian::termcount doclen, Xapian::termcount unique_terms, Xapian::termcount wdfdocmax) const =0
Return the weight contribution for the current position.
virtual Xapian::termcount count_matching_subqs() const
Count the number of leaf subqueries which match at the current position.
Definition: postlist.cc:59
Abstract base class for weighting schemes.
Definition: weight.h:38
#define usual(COND)
Definition: config.h:617
#define rare(COND)
Definition: config.h:616
Multi-database support functions.
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
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:64
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
#define Assert(COND)
Definition: omassert.h:122
Abstract base class for postlists.
A document which gets its values from a ValueStreamManager.