2 * @brief Class for merging PostList objects from subdatabases.
4 /* Copyright (C) 2007,2008,2009,2011,2017,2018,2020 Olly Betts
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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "multi_postlist.h"
23 #include <xapian/database.h>
25 #include "backends/multi.h"
26 #include "backends/postlist.h"
35 MultiPostList::~MultiPostList()
38 delete postlists
[--n_shards
];
44 MultiPostList::get_docid() const
50 MultiPostList::get_wdf() const
52 return postlists
[shard_number(docids
[0], n_shards
)]->get_wdf();
56 MultiPostList::get_weight(Xapian::termcount
,
58 Xapian::termcount
) const
60 // MultiPostList is only used by PostingIterator which should never call
67 MultiPostList::at_end() const
69 return docids_size
== 0;
73 MultiPostList::recalc_maxweight()
75 // MultiPostList is only used by PostingIterator which should never call
82 MultiPostList::open_position_list() const
84 return postlists
[shard_number(docids
[0], n_shards
)]->open_position_list();
88 MultiPostList::next(double w_min
)
90 if (docids_size
== 0) {
91 // Make a heap of the mapped docids so that the smallest is at the top
93 Xapian::doccount j
= 0;
94 for (Xapian::doccount i
= 0; i
!= n_shards
; ++i
) {
95 PostList
* pl
= postlists
[i
];
102 docids
[j
++] = unshard(pl
->get_docid(), i
, n_shards
);
106 Heap::make(docids
, docids
+ docids_size
,
107 std::greater
<Xapian::docid
>());
109 Xapian::docid old_did
= docids
[0];
110 Xapian::doccount shard
= shard_number(old_did
, n_shards
);
111 PostList
* pl
= postlists
[shard
];
114 Heap::pop(docids
, docids
+ docids_size
,
115 std::greater
<Xapian::docid
>());
117 postlists
[shard
] = NULL
;
120 docids
[0] = unshard(pl
->get_docid(), shard
, n_shards
);
121 Heap::replace(docids
, docids
+ docids_size
,
122 std::greater
<Xapian::docid
>());
130 MultiPostList::skip_to(Xapian::docid did
, double w_min
)
132 Xapian::doccount j
= 0;
133 if (docids_size
== 0) {
134 // Make a heap of the mapped docids so that the smallest is at the top
136 Xapian::docid shard_did
= shard_docid(did
, n_shards
);
137 Xapian::doccount shard
= shard_number(did
, n_shards
);
138 for (Xapian::doccount i
= 0; i
!= n_shards
; ++i
) {
139 PostList
* pl
= postlists
[i
];
141 pl
->skip_to(shard_did
+ (i
< shard
), w_min
);
146 docids
[j
++] = unshard(pl
->get_docid(), i
, n_shards
);
150 if (did
<= docids
[0])
152 // For a skip by < n_shards docids, pop/push may be more efficient than
153 // rebuilding the heap. For now, always just rebuild the heap unless
154 // we're just skipping the next docid, in which case do next() instead.
155 if (did
== docids
[0] + 1)
156 return MultiPostList::next(w_min
);
157 Xapian::docid shard_did
= shard_docid(did
, n_shards
);
158 Xapian::doccount shard
= shard_number(did
, n_shards
);
159 for (Xapian::doccount i
= 0; i
!= docids_size
; ++i
) {
160 Xapian::docid old_did
= docids
[i
];
162 Xapian::doccount old_shard
= shard_number(old_did
, n_shards
);
163 PostList
* pl
= postlists
[old_shard
];
164 pl
->skip_to(shard_did
+ (old_shard
< shard
), w_min
);
167 postlists
[old_shard
] = NULL
;
169 docids
[j
++] = unshard(pl
->get_docid(), old_shard
, n_shards
);
172 docids
[j
++] = old_did
;
177 Heap::make(docids
, docids
+ docids_size
, std::greater
<Xapian::docid
>());
183 MultiPostList::get_description() const
185 string desc
= "MultiPostList(";
186 for (Xapian::doccount i
= 0; i
!= n_shards
; ++i
) {
188 desc
+= postlists
[i
]->get_description();