Branch data Line data Source code
1 : : /* multi_postlist.cc: interface to multiple database access
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002,2003,2004,2005,2007,2008,2009 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, write to the Free Software
18 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 : : * USA
20 : : */
21 : :
22 : : #include <config.h>
23 : :
24 : : #include "multi_postlist.h"
25 : :
26 : : #include "debuglog.h"
27 : : #include "omassert.h"
28 : : #include "utils.h"
29 : :
30 : : #ifdef XAPIAN_ASSERTIONS_PARANOID
31 : : #include "xapian/database.h"
32 : : #endif
33 : :
34 : 87 : MultiPostList::MultiPostList(std::vector<LeafPostList *> & pls,
35 : : const Xapian::Database &this_db_)
36 : : : postlists(pls),
37 : : this_db(this_db_),
38 : : finished(false),
39 : 87 : currdoc(0)
40 : : {
41 : 87 : multiplier = pls.size();
42 : 87 : }
43 : :
44 : :
45 : 87 : MultiPostList::~MultiPostList()
46 : : {
47 : 87 : std::vector<LeafPostList *>::iterator i;
48 [ + + ][ # # ]: 261 : for (i = postlists.begin(); i != postlists.end(); i++) {
[ # # ]
49 [ + - ][ # # ]: 174 : delete *i;
[ # # ]
50 : : }
51 : 87 : postlists.clear();
52 [ + - ][ # # ]: 87 : }
[ # # ]
53 : :
54 : : Xapian::doccount
55 : 0 : MultiPostList::get_termfreq_min() const
56 : : {
57 : : // Should never get called.
58 : : Assert(false);
59 : 0 : return 0;
60 : : }
61 : :
62 : : Xapian::doccount
63 : 0 : MultiPostList::get_termfreq_max() const
64 : : {
65 : 0 : return MultiPostList::get_termfreq_min();
66 : : }
67 : :
68 : : Xapian::doccount
69 : 0 : MultiPostList::get_termfreq_est() const
70 : : {
71 : 0 : return MultiPostList::get_termfreq_min();
72 : : }
73 : :
74 : : Xapian::weight
75 : 0 : MultiPostList::get_maxweight() const
76 : : {
77 : 0 : return MultiPostList::get_weight();
78 : : }
79 : :
80 : : Xapian::weight
81 : 0 : MultiPostList::get_weight() const
82 : : {
83 : : // Should never get called.
84 : : Assert(false);
85 : 0 : return 0;
86 : : }
87 : :
88 : : Xapian::weight
89 : 0 : MultiPostList::recalc_maxweight()
90 : : {
91 : 0 : return MultiPostList::get_weight();
92 : : }
93 : :
94 : : Xapian::docid
95 : 9327 : MultiPostList::get_docid() const
96 : : {
97 : : LOGCALL(DB, Xapian::docid, "MultiPostList::get_docid", NO_ARGS);
98 : : Assert(!at_end());
99 : : Assert(currdoc != 0);
100 : 9327 : RETURN(currdoc);
101 : : }
102 : :
103 : : Xapian::termcount
104 : 48 : MultiPostList::get_doclength() const
105 : : {
106 : : LOGCALL(DB, Xapian::termcount, "MultiPostList::get_doclength", NO_ARGS);
107 : : Assert(!at_end());
108 : : Assert(currdoc != 0);
109 : 48 : Xapian::termcount result = postlists[(currdoc - 1) % multiplier]->get_doclength();
110 : : AssertEqParanoid(result, this_db.get_doclength(get_docid()));
111 : 48 : RETURN(result);
112 : : }
113 : :
114 : : Xapian::termcount
115 : 18 : MultiPostList::get_wdf() const
116 : : {
117 : 18 : return postlists[(currdoc - 1) % multiplier]->get_wdf();
118 : : }
119 : :
120 : : PositionList *
121 : 0 : MultiPostList::open_position_list() const
122 : : {
123 : 0 : return postlists[(currdoc - 1) % multiplier]->open_position_list();
124 : : }
125 : :
126 : : PostList *
127 : 4773 : MultiPostList::next(Xapian::weight w_min)
128 : : {
129 : : LOGCALL(DB, PostList *, "MultiPostList::next", w_min);
130 : : Assert(!at_end());
131 : :
132 : 4773 : Xapian::docid newdoc = 0;
133 : 4773 : Xapian::docid offset = 1;
134 : 4773 : std::vector<LeafPostList *>::iterator i;
135 [ + + ]: 14319 : for (i = postlists.begin(); i != postlists.end(); i++) {
136 [ + + ]: 9546 : if (!(*i)->at_end()) {
137 : 9462 : Xapian::docid id = ((*i)->get_docid() - 1) * multiplier + offset;
138 : : // Check if it needs to be advanced
139 [ + + ]: 9462 : if (currdoc >= id) {
140 : 4686 : (*i)->next(w_min);
141 [ + + ]: 4686 : if (!(*i)->at_end()) {
142 : 4638 : id = ((*i)->get_docid() - 1) * multiplier + offset;
143 [ + + - + ]: 4638 : if (newdoc == 0 || id < newdoc) newdoc = id;
144 : : }
145 : : } else {
146 [ + + ][ + + ]: 4776 : if (newdoc == 0 || id < newdoc) newdoc = id;
147 : : }
148 : : }
149 : 9546 : offset++;
150 : : }
151 [ + + ]: 4773 : if (newdoc) {
152 : : LOGLINE(DB, "MultiPostList::next() newdoc=" << newdoc <<
153 : : " (olddoc=" << currdoc << ")");
154 : 4719 : currdoc = newdoc;
155 : : } else {
156 : : LOGLINE(DB, "MultiPostList::next() finished" <<
157 : : " (olddoc=" << currdoc << ")");
158 : 54 : finished = true;
159 : : }
160 : 4773 : RETURN(NULL);
161 : : }
162 : :
163 : : PostList *
164 : 18 : MultiPostList::skip_to(Xapian::docid did, Xapian::weight w_min)
165 : : {
166 : : LOGCALL(DB, PostList *, "MultiPostList::skip_to", did | w_min);
167 : : Assert(!at_end());
168 : 18 : Xapian::docid newdoc = 0;
169 : 18 : Xapian::docid offset = 0;
170 : 18 : Xapian::docid realdid = (did - 1) / multiplier + 2;
171 : 18 : Xapian::doccount dbnumber = (did - 1) % multiplier;
172 : 18 : std::vector<LeafPostList *>::iterator i;
173 [ + + ]: 54 : for (i = postlists.begin(); i != postlists.end(); i++) {
174 [ + + ]: 36 : if (offset == dbnumber) --realdid;
175 : 36 : ++offset;
176 : : Assert((realdid - 1) * multiplier + offset >= did);
177 : : Assert((realdid - 1) * multiplier + offset < did + multiplier);
178 [ + - ]: 36 : if (!(*i)->at_end()) {
179 : 36 : (*i)->skip_to(realdid, w_min);
180 [ + + ]: 36 : if (!(*i)->at_end()) {
181 : 30 : Xapian::docid id = ((*i)->get_docid() - 1) * multiplier + offset;
182 [ + + + + ]: 30 : if (newdoc == 0 || id < newdoc) newdoc = id;
183 : : }
184 : : }
185 : : }
186 [ + + ]: 18 : if (newdoc) {
187 : 15 : currdoc = newdoc;
188 : : } else {
189 : 3 : finished = true;
190 : : }
191 : 18 : RETURN(NULL);
192 : : }
193 : :
194 : : bool
195 : 4791 : MultiPostList::at_end() const
196 : : {
197 : 4791 : return finished;
198 : : }
199 : :
200 : : std::string
201 : 9 : MultiPostList::get_description() const
202 : : {
203 : 9 : std::string desc;
204 : :
205 : 9 : std::vector<LeafPostList *>::const_iterator i;
206 [ + + ]: 27 : for (i = postlists.begin(); i != postlists.end(); i++) {
207 [ + + ]: 18 : if (!desc.empty()) desc += ',';
208 : 18 : desc += (*i)->get_description();
209 : : }
210 : :
211 : 0 : return desc;
212 : : }
|