[honey] More compact postlist chunk headers
[xapian.git] / xapian-core / backends / honey / honey_postlisttable.cc
blob3955a31584ed765d732294cff483df618d9b6c82
1 /** @file honey_postlisttable.cc
2 * @brief Subclass of HoneyTable which holds postlists.
3 */
4 /* Copyright (C) 2007,2008,2009,2010,2013,2014,2015,2016,2017 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
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 "honey_postlisttable.h"
25 #include "honey_cursor.h"
26 #include "honey_database.h"
27 #include "honey_postlist.h"
28 #include "honey_postlist_encodings.h"
30 #include <memory>
32 using namespace std;
34 HoneyPostList*
35 HoneyPostListTable::open_post_list(const HoneyDatabase* db,
36 const std::string& term,
37 bool need_pos) const
39 Assert(!term.empty());
40 // Try to position cursor first so we avoid creating HoneyPostList objects
41 // for terms which don't exist.
42 unique_ptr<HoneyCursor> cursor(cursor_get());
43 if (!cursor->find_exact(Honey::make_postingchunk_key(term))) {
44 // FIXME: Return NULL here and handle that in Query::Internal
45 // postlist() methods as we build the PostList tree.
46 // return NULL;
47 return new HoneyPostList(db, term, NULL);
50 if (need_pos)
51 return new HoneyPosPostList(db, term, cursor.release());
52 return new HoneyPostList(db, term, cursor.release());
55 void
56 HoneyPostListTable::get_freqs(const std::string& term,
57 Xapian::doccount* termfreq_ptr,
58 Xapian::termcount* collfreq_ptr) const
60 string chunk;
61 if (!get_exact_entry(Honey::make_postingchunk_key(term), chunk)) {
62 if (termfreq_ptr) *termfreq_ptr = 0;
63 if (collfreq_ptr) *collfreq_ptr = 0;
64 return;
67 const char* p = chunk.data();
68 const char* pend = p + chunk.size();
69 Xapian::doccount tf;
70 Xapian::termcount cf;
71 if (!decode_initial_chunk_header_freqs(&p, pend, tf, cf))
72 throw Xapian::DatabaseCorruptError("Postlist initial chunk header");
73 if (termfreq_ptr) *termfreq_ptr = tf;
74 if (collfreq_ptr) *collfreq_ptr = cf;
77 void
78 HoneyPostListTable::get_used_docid_range(Xapian::docid& first,
79 Xapian::docid& last) const
81 unique_ptr<HoneyCursor> cursor;
82 if (cursor->find_entry_ge(string("\0\xe0", 2))) {
83 first = 1;
84 } else {
85 // doccount == 0 should be handled by our caller.
86 Assert(!cursor->after_end());
87 const char* p = cursor->current_key.data();
88 const char* pend = p + cursor->current_key.size();
89 p += 2;
90 if (p[-2] != '\0' ||
91 p[-1] != '\xe0' ||
92 !unpack_uint_preserving_sort(&p, pend, &first) ||
93 p != pend) {
94 // Note that our caller checks for doccount == 0 and handles that.
95 throw Xapian::DatabaseCorruptError("Bad first doclen chunk");
99 cursor->find_entry_lt(string("\0\xe1", 2));
100 cursor->read_tag();
101 if (cursor->current_key.size() == 2) {
102 // Must be a single doclen chunk starting at 1.
103 AssertEq(cursor->current_key[0], '\0');
104 AssertEq(cursor->current_key[1], '\xe0');
105 last = cursor->current_tag.size() >> 2;
106 } else {
107 const char* p = cursor->current_key.data();
108 const char* pend = p + cursor->current_key.size();
109 p += 2;
110 if (p[-2] != '\0' ||
111 p[-1] != '\xe0' ||
112 !unpack_uint_preserving_sort(&p, pend, &last) ||
113 p != pend) {
114 throw Xapian::DatabaseCorruptError("Bad final doclen chunk");
116 last += (cursor->current_tag.size() >> 2) - 1;