Branch data Line data Source code
1 : : /* chert_termlist.cc: Termlists in a chert database
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002 Ananova Ltd
5 : : * Copyright 2002,2003,2004,2006,2007,2008,2010 Olly Betts
6 : : *
7 : : * This program is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU General Public License as
9 : : * published by the Free Software Foundation; either version 2 of the
10 : : * License, or (at your option) any later version.
11 : : *
12 : : * This program is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this program; if not, write to the Free Software
19 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 : : * USA
21 : : */
22 : :
23 : : #include <config.h>
24 : : #include "chert_termlist.h"
25 : :
26 : : #include "xapian/error.h"
27 : :
28 : : #include "expandweight.h"
29 : : #include "chert_positionlist.h"
30 : : #include "debuglog.h"
31 : : #include "omassert.h"
32 : : #include "pack.h"
33 : : #include "str.h"
34 : :
35 : : using namespace std;
36 : :
37 : 53733 : ChertTermList::ChertTermList(Xapian::Internal::RefCntPtr<const ChertDatabase> db_,
38 : : Xapian::docid did_)
39 : 53733 : : db(db_), did(did_), current_wdf(0), current_termfreq(0)
40 : : {
41 : : LOGCALL_CTOR(DB, "ChertTermList", db_ | did_);
42 : :
43 [ + + ][ # # ]: 53734 : if (!db->termlist_table.get_exact_entry(ChertTermListTable::make_key(did),
44 : : data))
45 : 3029 : throw Xapian::DocNotFoundError("No termlist for document " + str(did));
46 : :
47 : 50703 : pos = data.data();
48 : 50703 : end = pos + data.size();
49 : :
50 [ + + # # ]: 50703 : if (pos == end) {
51 : 9068 : doclen = 0;
52 : 9068 : termlist_size = 0;
53 : 9068 : return;
54 : : }
55 : :
56 : : // Read doclen
57 [ - + ][ # # ]: 41635 : if (!unpack_uint(&pos, end, &doclen)) {
58 : : const char *msg;
59 [ # # ][ # # ]: 0 : if (pos == 0) {
60 : 0 : msg = "Too little data for doclen in termlist";
61 : : } else {
62 : 0 : msg = "Overflowed value for doclen in termlist";
63 : : }
64 : 0 : throw Xapian::DatabaseCorruptError(msg);
65 : : }
66 : :
67 : : // Read termlist_size
68 [ - + ][ # # ]: 41635 : if (!unpack_uint(&pos, end, &termlist_size)) {
69 : : const char *msg;
70 [ # # ][ # # ]: 0 : if (pos == 0) {
71 : 0 : msg = "Too little data for list size in termlist";
72 : : } else {
73 : 0 : msg = "Overflowed value for list size in termlist";
74 : : }
75 : 0 : throw Xapian::DatabaseCorruptError(msg);
76 : : }
77 : 62823 : }
78 : :
79 : : chert_doclen_t
80 : 19094 : ChertTermList::get_doclength() const
81 : : {
82 : : LOGCALL(DB, chert_doclen_t, "ChertTermList::get_doclength", NO_ARGS);
83 : 19094 : RETURN(doclen);
84 : : }
85 : :
86 : : Xapian::termcount
87 : 46 : ChertTermList::get_approx_size() const
88 : : {
89 : : LOGCALL(DB, Xapian::termcount, "ChertTermList::get_approx_size", NO_ARGS);
90 : 46 : RETURN(termlist_size);
91 : : }
92 : :
93 : : void
94 : 1441 : ChertTermList::accumulate_stats(Xapian::Internal::ExpandStats & stats) const
95 : : {
96 : : LOGCALL_VOID(DB, "ChertTermList::accumulate_stats", stats);
97 : : Assert(!at_end());
98 : 1441 : stats.accumulate(current_wdf, doclen, get_termfreq(), db->get_doccount());
99 : 1441 : }
100 : :
101 : : string
102 : 108272 : ChertTermList::get_termname() const
103 : : {
104 : : LOGCALL(DB, string, "ChertTermList::get_termname", NO_ARGS);
105 : 108272 : RETURN(current_term);
106 : : }
107 : :
108 : : Xapian::termcount
109 : 82090 : ChertTermList::get_wdf() const
110 : : {
111 : : LOGCALL(DB, Xapian::termcount, "ChertTermList::get_wdf", NO_ARGS);
112 : 82090 : RETURN(current_wdf);
113 : : }
114 : :
115 : : Xapian::doccount
116 : 26955 : ChertTermList::get_termfreq() const
117 : : {
118 : : LOGCALL(DB, Xapian::doccount, "ChertTermList::get_termfreq", NO_ARGS);
119 [ + + ]: 26955 : if (current_termfreq == 0)
120 : 26953 : current_termfreq = db->get_termfreq(current_term);
121 : 26955 : RETURN(current_termfreq);
122 : : }
123 : :
124 : : TermList *
125 : 113525 : ChertTermList::next()
126 : : {
127 : : LOGCALL(DB, TermList *, "ChertTermList::next", NO_ARGS);
128 : : Assert(!at_end());
129 [ + + ]: 113525 : if (pos == end) {
130 : 50678 : pos = NULL;
131 : 50678 : RETURN(NULL);
132 : : }
133 : :
134 : : // Reset to 0 to indicate that the termfreq needs to be read.
135 : 62847 : current_termfreq = 0;
136 : :
137 : 62847 : bool wdf_in_reuse = false;
138 [ + + ]: 62847 : if (!current_term.empty()) {
139 : : // Find out how much of the previous term to reuse.
140 : 21212 : size_t len = static_cast<unsigned char>(*pos++);
141 [ + + ]: 21212 : if (len > current_term.size()) {
142 : : // The wdf is also stored in the "reuse" byte.
143 : 21200 : wdf_in_reuse = true;
144 : 21200 : size_t divisor = current_term.size() + 1;
145 : 21200 : current_wdf = len / divisor - 1;
146 : 21200 : len %= divisor;
147 : : }
148 : 21212 : current_term.resize(len);
149 : : }
150 : :
151 : : // Append the new tail to form the next term.
152 : 62847 : size_t append_len = static_cast<unsigned char>(*pos++);
153 : 62847 : current_term.append(pos, append_len);
154 : 62847 : pos += append_len;
155 : :
156 : : // Read the wdf if it wasn't packed into the reuse byte.
157 [ + + - + ]: 62847 : if (!wdf_in_reuse && !unpack_uint(&pos, end, ¤t_wdf)) {
[ - + ]
158 : : const char *msg;
159 [ # # ]: 0 : if (pos == 0) {
160 : 0 : msg = "Too little data for wdf in termlist";
161 : : } else {
162 : 0 : msg = "Overflowed value for wdf in termlist";
163 : : }
164 : 0 : throw Xapian::DatabaseCorruptError(msg);
165 : : }
166 : :
167 : 113525 : RETURN(NULL);
168 : : }
169 : :
170 : : TermList *
171 : 104 : ChertTermList::skip_to(const string & term)
172 : : {
173 : : LOGCALL(API, TermList *, "ChertTermList::skip_to", term);
174 [ + + ][ + + ]: 1030 : while (pos != NULL && current_term < term) {
[ + + ]
175 : 926 : (void)ChertTermList::next();
176 : : }
177 : 104 : RETURN(NULL);
178 : : }
179 : :
180 : : bool
181 : 113453 : ChertTermList::at_end() const
182 : : {
183 : : LOGCALL(DB, bool, "ChertTermList::at_end", NO_ARGS);
184 : 113453 : RETURN(pos == NULL);
185 : : }
186 : :
187 : : Xapian::termcount
188 : 11239 : ChertTermList::positionlist_count() const
189 : : {
190 : : LOGCALL(DB, Xapian::termcount, "ChertTermList::positionlist_count", NO_ARGS);
191 : 11239 : RETURN(db->position_table.positionlist_count(did, current_term));
192 : : }
193 : :
194 : : Xapian::PositionIterator
195 : 33842 : ChertTermList::positionlist_begin() const
196 : : {
197 : : LOGCALL(DB, Xapian::PositionIterator, "ChertTermList::positionlist_begin", NO_ARGS);
198 : : return Xapian::PositionIterator(
199 : 33842 : new ChertPositionList(&db->position_table, did, current_term));
200 : : }
|