00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024
00025 #include "autoptr.h"
00026 #include "omdebug.h"
00027 #include "quartz_alldocspostlist.h"
00028 #include "quartz_utils.h"
00029 #include "bcursor.h"
00030 #include "database.h"
00031 #include "utils.h"
00032
00033 #include <map>
00034
00035 QuartzDocIdListIterator::QuartzDocIdListIterator()
00036 : ranges(NULL),
00037 currrange(),
00038 currdocid(0)
00039 {
00040 DEBUGCALL(DB, void,
00041 "QuartzDocIdListIterator::QuartzDocIdListIterator", "");
00042 }
00043
00044 QuartzDocIdListIterator::QuartzDocIdListIterator(const map<Xapian::docid, Xapian::docid> * ranges_, int)
00045 : ranges(ranges_),
00046 currrange(ranges_->end()),
00047 currdocid(0)
00048 {
00049 }
00050
00051 QuartzDocIdListIterator::QuartzDocIdListIterator(const map<Xapian::docid, Xapian::docid> * ranges_)
00052 : ranges(ranges_),
00053 currrange(ranges_->begin()),
00054 currdocid(0)
00055 {
00056 DEBUGCALL(DB, void,
00057 "QuartzDocIdListIterator::QuartzDocIdListIterator", "ranges");
00058 if (currrange != ranges_->end()) {
00059 currdocid = currrange->first;
00060 }
00061
00062 map<Xapian::docid, Xapian::docid>::const_iterator i;
00063 for (i = ranges->begin(); i != ranges->end(); i++) {
00064 DEBUGLINE(DB, "Docid range begin=" << i->first << ", end=" << i->second);
00065 }
00066 }
00067
00068 QuartzDocIdListIterator::QuartzDocIdListIterator(const QuartzDocIdListIterator & other)
00069 : ranges(other.ranges),
00070 currrange(other.currrange),
00071 currdocid(other.currdocid)
00072 {
00073 DEBUGCALL(DB, void,
00074 "QuartzDocIdListIterator::~QuartzDocIdListIterator", "other");
00075 }
00076
00077 void
00078 QuartzDocIdListIterator::operator=(const QuartzDocIdListIterator & other)
00079 {
00080 DEBUGCALL(DB, void,
00081 "QuartzDocIdListIterator::operator=", "other");
00082 ranges = other.ranges;
00083 currrange = other.currrange;
00084 currdocid = other.currdocid;
00085 }
00086
00087 QuartzDocIdListIterator &
00088 QuartzDocIdListIterator::operator++()
00089 {
00090 DEBUGCALL(DB, void,
00091 "QuartzDocIdListIterator::operator++", "");
00092 DEBUGLINE(DB, string("Moved from ") <<
00093 (currrange == ranges->end() ? string("end.") : string("docid = ") +
00094 om_tostring(currdocid)));
00095
00096 if (currrange != ranges->end()) {
00097 Assert(currrange->first <= currdocid);
00098 if (currdocid < currrange->second) {
00099 currdocid++;
00100 } else {
00101 currrange++;
00102 if (currrange == ranges->end()) {
00103 currdocid = 0;
00104 } else {
00105 Assert(currrange->first > currdocid);
00106 currdocid = currrange->first;
00107 }
00108 }
00109 }
00110
00111 DEBUGLINE(DB, string("Moved to ") <<
00112 (currrange == ranges->end() ? string("end.") : string("docid = ") +
00113 om_tostring(currdocid)));
00114
00115 return *this;
00116 }
00117
00118
00119 void
00120 QuartzDocIdList::addDocId(Xapian::docid did) {
00121 DEBUGCALL(DB, void, "QuartzDocIdList::addDocId", did);
00122
00123 if (ranges.empty()) {
00124 ranges.insert(pair<Xapian::docid, Xapian::docid>(did, did));
00125 return;
00126 }
00127
00128 if (did < ranges.begin()->first) {
00129 Xapian::docid newend;
00130 if (did == ranges.begin()->first - 1) {
00131 newend = ranges.begin()->second;
00132 ranges.erase(ranges.begin());
00133 } else {
00134 newend = did;
00135 }
00136 ranges[did] = newend;
00137 return;
00138 }
00139
00140 map<Xapian::docid, Xapian::docid>::iterator i;
00141 i = ranges.lower_bound(did);
00142 if (i == ranges.end()) {
00143 i--;
00144 Assert(did > i->first);
00145 } else if (did < i->first) {
00146 i--;
00147 Assert(did > i->first);
00148 }
00149 Assert(did >= i->first);
00150
00151 if (did <= i->second) {
00152
00153 return;
00154 }
00155
00156 if (did == i->second + 1) {
00157
00158 i->second = did;
00159 map<Xapian::docid, Xapian::docid>::iterator j;
00160 j = i;
00161 j++;
00162 if (j != ranges.end()) {
00163 Assert(j->first > i->second);
00164 if (j->first == i->second + 1) {
00165
00166 i->second = j->second;
00167 ranges.erase(j);
00168 }
00169 }
00170 } else {
00171 ranges[did] = did;
00172 }
00173 }
00174
00175
00176 QuartzAllDocsPostList::QuartzAllDocsPostList(Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> this_db_,
00177 const Btree * table,
00178 Xapian::doccount doccount_)
00179 : this_db(this_db_),
00180 docids(),
00181 dociditer(),
00182 doccount(doccount_),
00183 have_started(false)
00184 {
00185 DEBUGCALL(DB, void, "QuartzAllDocsPostList::QuartzAllDocsPostList",
00186 this_db_.get() << ", " << table << ", " << doccount_);
00187
00188
00189 AutoPtr<Bcursor> cursor(table->cursor_get());
00190 cursor->find_entry("");
00191 if (!cursor->after_end())
00192 cursor->next();
00193 while (!cursor->after_end()) {
00194 string key = cursor->current_key;
00195 const char * keystr = key.c_str();
00196 Xapian::docid did;
00197 if (!unpack_uint_last(&keystr, keystr + key.length(), &did)) {
00198 throw Xapian::RangeError("Document number in value table is too large");
00199 }
00200 docids.addDocId(did);
00201 cursor->next();
00202 }
00203 }
00204
00205 QuartzAllDocsPostList::~QuartzAllDocsPostList()
00206 {
00207 DEBUGCALL(DB, void, "QuartzAllDocsPostList::~QuartzAllDocsPostList", "");
00208 }
00209
00210 PostList *
00211 QuartzAllDocsPostList::next(Xapian::weight w_min)
00212 {
00213 DEBUGCALL(DB, PostList *, "QuartzAllDocsPostList::next", w_min);
00214 (void)w_min;
00215
00216 if (have_started) {
00217 ++dociditer;
00218 } else {
00219 dociditer = docids.begin();
00220 have_started = true;
00221 }
00222
00223 DEBUGLINE(DB, string("Moved to ") <<
00224 (dociditer == docids.end() ? string("end.") : string("docid = ") +
00225 om_tostring(*dociditer)));
00226
00227 RETURN(NULL);
00228 }
00229
00230 PostList *
00231 QuartzAllDocsPostList::skip_to(Xapian::docid desired_did, Xapian::weight w_min)
00232 {
00233 DEBUGCALL(DB, PostList *,
00234 "QuartzAllDocsPostList::skip_to", desired_did << ", " << w_min);
00235 (void)w_min;
00236
00237
00238 if (!have_started) {
00239 dociditer = docids.begin();
00240 have_started = true;
00241 }
00242 if (dociditer == docids.end()) RETURN(NULL);
00243 if (desired_did <= *dociditer) RETURN(NULL);
00244
00245 while (dociditer != docids.end() && *dociditer < desired_did) {
00246 ++dociditer;
00247 }
00248
00249 DEBUGLINE(DB, string("Skipped to ") <<
00250 (dociditer == docids.end() ? string("end.") : string("docid = ") +
00251 om_tostring(*dociditer)));
00252
00253 RETURN(NULL);
00254 }
00255
00256 string
00257 QuartzAllDocsPostList::get_description() const
00258 {
00259 return ":" + om_tostring(doccount);
00260 }