backends/quartz/quartz_alldocspostlist.cc

Go to the documentation of this file.
00001 /* quartz_alldocspostlist.cc: All-document postlists in quartz databases
00002  *
00003  * Copyright 1999,2000,2001 BrightStation PLC
00004  * Copyright 2002,2003,2004,2005,2007 Olly Betts
00005  * Copyright 2006 Richard Boulton
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of the
00010  * License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
00020  * USA
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         // Do nothing - already in range
00153         return;
00154     }
00155 
00156     if (did == i->second + 1) {
00157         // Extend range
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                 // Merge ranges
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     // Move to initial NULL entry.
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; // no warning
00236 
00237     // Don't skip back, and don't need to do anything if already there.
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 }

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.