00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include "chert_positionlist.h"
00024
00025 #include <xapian/types.h>
00026
00027 #include "bitstream.h"
00028 #include "debuglog.h"
00029 #include "pack.h"
00030
00031 #include <string>
00032 #include <vector>
00033
00034 using namespace std;
00035
00036 void
00037 ChertPositionListTable::set_positionlist(Xapian::docid did,
00038 const string & tname,
00039 Xapian::PositionIterator pos,
00040 const Xapian::PositionIterator &pos_end,
00041 bool check_for_update)
00042 {
00043 LOGCALL_VOID(DB, "ChertPositionList::set_positionlist", did | tname | pos | pos_end | check_for_update);
00044 Assert(pos != pos_end);
00045
00046
00047 vector<Xapian::termpos> poscopy(pos, pos_end);
00048
00049 string key = make_key(did, tname);
00050
00051 string s;
00052 pack_uint(s, poscopy.back());
00053
00054 if (poscopy.size() > 1) {
00055 BitWriter wr(s);
00056 wr.encode(poscopy[0], poscopy.back());
00057 wr.encode(poscopy.size() - 2, poscopy.back() - poscopy[0]);
00058 wr.encode_interpolative(poscopy, 0, poscopy.size() - 1);
00059 swap(s, wr.freeze());
00060 }
00061
00062 if (check_for_update) {
00063 string old_tag;
00064 if (get_exact_entry(key, old_tag) && s == old_tag)
00065 return;
00066 }
00067 add(key, s);
00068 }
00069
00070 Xapian::termcount
00071 ChertPositionListTable::positionlist_count(Xapian::docid did,
00072 const string & term) const
00073 {
00074 LOGCALL_VOID(DB, "ChertPositionListTable::positionlist_count", did | term);
00075
00076 string data;
00077 if (!get_exact_entry(make_key(did, term), data)) {
00078
00079 return 0;
00080 }
00081
00082 const char * pos = data.data();
00083 const char * end = pos + data.size();
00084 Xapian::termpos pos_last;
00085 if (!unpack_uint(&pos, end, &pos_last)) {
00086 throw Xapian::DatabaseCorruptError("Position list data corrupt");
00087 }
00088 if (pos == end) {
00089
00090 return 1;
00091 }
00092
00093
00094 BitReader rd(data, pos - data.data());
00095 Xapian::termpos pos_first = rd.decode(pos_last);
00096 Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
00097 return pos_size;
00098 }
00099
00101
00102 bool
00103 ChertPositionList::read_data(const ChertTable * table, Xapian::docid did,
00104 const string & tname)
00105 {
00106 LOGCALL_VOID(DB, "ChertPositionList::read_data", table | did | tname);
00107
00108 have_started = false;
00109 positions.clear();
00110
00111 string data;
00112 if (!table->get_exact_entry(ChertPositionListTable::make_key(did, tname), data)) {
00113
00114 current_pos = positions.begin();
00115 return false;
00116 }
00117
00118 const char * pos = data.data();
00119 const char * end = pos + data.size();
00120 Xapian::termpos pos_last;
00121 if (!unpack_uint(&pos, end, &pos_last)) {
00122 throw Xapian::DatabaseCorruptError("Position list data corrupt");
00123 }
00124 if (pos == end) {
00125
00126 positions.push_back(pos_last);
00127 current_pos = positions.begin();
00128 return true;
00129 }
00130
00131 BitReader rd(data, pos - data.data());
00132 Xapian::termpos pos_first = rd.decode(pos_last);
00133 Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
00134 positions.resize(pos_size);
00135 positions[0] = pos_first;
00136 positions.back() = pos_last;
00137 rd.decode_interpolative(positions, 0, pos_size - 1);
00138
00139 current_pos = positions.begin();
00140 return true;
00141 }
00142
00143 Xapian::termcount
00144 ChertPositionList::get_size() const
00145 {
00146 LOGCALL(DB, Xapian::termcount, "ChertPositionList::get_size", NO_ARGS);
00147 RETURN(positions.size());
00148 }
00149
00150 Xapian::termpos
00151 ChertPositionList::get_position() const
00152 {
00153 LOGCALL(DB, Xapian::termpos, "ChertPositionList::get_position", NO_ARGS);
00154 Assert(have_started);
00155 RETURN(*current_pos);
00156 }
00157
00158 void
00159 ChertPositionList::next()
00160 {
00161 LOGCALL_VOID(DB, "ChertPositionList::next", NO_ARGS);
00162
00163 if (!have_started) {
00164 have_started = true;
00165 } else {
00166 Assert(!at_end());
00167 ++current_pos;
00168 }
00169 }
00170
00171 void
00172 ChertPositionList::skip_to(Xapian::termpos termpos)
00173 {
00174 LOGCALL_VOID(DB, "ChertPositionList::skip_to", termpos);
00175 if (!have_started) {
00176 have_started = true;
00177 }
00178 while (!at_end() && *current_pos < termpos) ++current_pos;
00179 }
00180
00181 bool
00182 ChertPositionList::at_end() const
00183 {
00184 LOGCALL(DB, bool, "ChertPositionList::at_end", NO_ARGS);
00185 RETURN(current_pos == positions.end());
00186 }