Reduce overheads of PostList positional data support
[xapian.git] / xapian-core / backends / glass / glass_valuelist.cc
blob2def4af64a9ba0d3f51231f7c659b53f506d1cf6
1 /** @file glass_valuelist.cc
2 * @brief Glass class for value streams.
3 */
4 /* Copyright (C) 2007,2008,2009 Olly Betts
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.
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.
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 USA
21 #include <config.h>
23 #include "glass_valuelist.h"
25 #include "glass_cursor.h"
26 #include "glass_database.h"
27 #include "omassert.h"
28 #include "str.h"
30 using namespace Glass;
31 using namespace std;
33 bool
34 GlassValueList::update_reader()
36 Xapian::docid first_did = docid_from_key(slot, cursor->current_key);
37 if (!first_did) return false;
39 cursor->read_tag();
40 const string & tag = cursor->current_tag;
41 reader.assign(tag.data(), tag.size(), first_did);
42 return true;
45 GlassValueList::~GlassValueList()
47 delete cursor;
50 Xapian::docid
51 GlassValueList::get_docid() const
53 Assert(!at_end());
54 return reader.get_docid();
57 Xapian::valueno
58 GlassValueList::get_valueno() const
60 return slot;
63 std::string
64 GlassValueList::get_value() const
66 Assert(!at_end());
67 return reader.get_value();
70 bool
71 GlassValueList::at_end() const
73 return cursor == NULL;
76 void
77 GlassValueList::next()
79 if (!cursor) {
80 cursor = db->get_postlist_cursor();
81 if (!cursor) return;
82 cursor->find_entry_ge(make_valuechunk_key(slot, 1));
83 } else if (!reader.at_end()) {
84 reader.next();
85 if (!reader.at_end()) return;
86 cursor->next();
89 if (!cursor->after_end()) {
90 if (update_reader()) {
91 if (!reader.at_end()) return;
95 // We've reached the end.
96 delete cursor;
97 cursor = NULL;
100 void
101 GlassValueList::skip_to(Xapian::docid did)
103 if (!cursor) {
104 cursor = db->get_postlist_cursor();
105 if (!cursor) return;
106 } else if (!reader.at_end()) {
107 reader.skip_to(did);
108 if (!reader.at_end()) return;
111 if (!cursor->find_entry(make_valuechunk_key(slot, did))) {
112 if (update_reader()) {
113 reader.skip_to(did);
114 if (!reader.at_end()) return;
116 // The requested docid is between two chunks.
117 cursor->next();
120 // Either an exact match, or in a gap before the start of a chunk.
121 if (!cursor->after_end()) {
122 if (update_reader()) {
123 if (!reader.at_end()) return;
127 // We've reached the end.
128 delete cursor;
129 cursor = NULL;
132 bool
133 GlassValueList::check(Xapian::docid did)
135 if (!cursor) {
136 cursor = db->get_postlist_cursor();
137 if (!cursor) return true;
138 } else if (!reader.at_end()) {
139 // Check for the requested docid in the current block.
140 reader.skip_to(did);
141 if (!reader.at_end()) return true;
144 // Try moving to the appropriate chunk.
145 if (!cursor->find_entry(make_valuechunk_key(slot, did))) {
146 // We're in a chunk which might contain the docid.
147 if (update_reader()) {
148 reader.skip_to(did);
149 if (!reader.at_end()) return true;
151 return false;
154 // We had an exact match for a chunk starting with specified docid.
155 Assert(!cursor->after_end());
156 if (!update_reader()) {
157 // We found the exact key we built, so it must match the slot.
158 // Therefore update_reader() "can't possibly fail".
159 Assert(false);
162 return true;
165 string
166 GlassValueList::get_description() const
168 string desc("GlassValueList(slot=");
169 desc += str(slot);
170 desc += ')';
171 return desc;