backends/quartz/quartz_alltermslist.cc

Go to the documentation of this file.
00001 /* quartzalltermslist.cc
00002  *
00003  * Copyright 1999,2000,2001 BrightStation PLC
00004  * Copyright 2002 Ananova Ltd
00005  * Copyright 2002,2003,2004,2005,2007 Olly Betts
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 #include "quartz_alltermslist.h"
00025 #include "quartz_utils.h"
00026 #include "quartz_postlist.h"
00027 
00028 #include "stringutils.h"
00029 
00030 QuartzAllTermsList::QuartzAllTermsList(Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> database_,
00031                                        AutoPtr<Bcursor> pl_cursor_,
00032                                        quartz_tablesize_t size_,
00033                                        const string & prefix_)
00034         : database(database_), pl_cursor(pl_cursor_), size(size_), 
00035           started(false), prefix(prefix_)
00036 {
00037     DEBUGCALL(DB, void, "QuartzAllTermsList", "[database_], [pl_cursor_]");
00038     if (prefix.empty()) {
00039         /* Seek to the first term */
00040         pl_cursor->find_entry(string());
00041 
00042         if (pl_cursor->current_key.empty()) {
00043             pl_cursor->next();
00044         }
00045     } else {
00046         // Seek to the first key which is at or after the desired prefix.
00047         if (!pl_cursor->find_entry(pack_string_preserving_sort(prefix))) {
00048             // Found the last key which is before the prefix - advance to the
00049             // first one following the prefix.
00050             pl_cursor->next();
00051         }
00052     }
00053 
00054     is_at_end = pl_cursor->after_end();
00055     if (!is_at_end) {
00056         const char *start = pl_cursor->current_key.data();
00057         const char *end = start + pl_cursor->current_key.length();
00058         if (!unpack_string_preserving_sort(&start, end, current_term)) {
00059             throw Xapian::DatabaseCorruptError("Failed to read the key field from a Bcursor's key");
00060         }
00061     }
00062 
00063     if (!startswith(current_term, prefix))
00064         is_at_end = true;
00065 
00066     have_stats = false;
00067 }
00068 
00069 QuartzAllTermsList::~QuartzAllTermsList()
00070 {
00071     DEBUGCALL(DB, void, "~QuartzAllTermsList", "");
00072 }
00073 
00074 string
00075 QuartzAllTermsList::get_termname() const
00076 {
00077     DEBUGCALL(DB, string, "QuartzAllTermsList::get_termname", "");
00078     Assert(started);
00079     RETURN(current_term);
00080 }
00081 
00082 void QuartzAllTermsList::get_stats() const
00083 {
00084     pl_cursor->read_tag();
00085     const char *start = pl_cursor->current_tag.data();
00086     const char *end = start + pl_cursor->current_tag.length();
00087     QuartzPostList::read_number_of_entries(&start, end,
00088                                            &termfreq, &collection_freq);
00089 
00090     have_stats = true;
00091 }
00092 
00093 Xapian::doccount
00094 QuartzAllTermsList::get_termfreq() const
00095 {
00096     DEBUGCALL(DB, Xapian::doccount, "QuartzAllTermsList::get_termfreq", "");
00097     Assert(started);
00098     if (have_stats) {
00099         RETURN(termfreq);
00100     } else if (!is_at_end) {
00101         get_stats();
00102         RETURN(termfreq);
00103     }
00104     throw Xapian::InvalidArgumentError("Attempt to get termfreq after end");
00105 }
00106 
00107 Xapian::termcount
00108 QuartzAllTermsList::get_collection_freq() const
00109 {
00110     DEBUGCALL(DB, Xapian::termcount, "QuartzAllTermsList::get_collection_freq", "");
00111     Assert(started);
00112     if (have_stats) {
00113         RETURN(collection_freq);
00114     } else if (!is_at_end) {
00115         get_stats();
00116         RETURN(collection_freq);
00117     }
00118     throw Xapian::InvalidArgumentError("Attempt to get collection_freq after end");
00119 }
00120 
00121 TermList *
00122 QuartzAllTermsList::skip_to(const string &tname)
00123 {
00124     DEBUGCALL(DB, TermList *, "QuartzAllTermsList::skip_to", tname);
00125     DEBUGLINE(DB, "QuartzAllTermList::skip_to(" << tname << ")");
00126     started = true;
00127     string key;
00128     key = pack_string_preserving_sort(tname);
00129 
00130     have_stats = false;
00131 
00132     if (!pl_cursor->find_entry(key)) {
00133         if (pl_cursor->after_end()) {
00134             is_at_end = true;
00135         } else {
00136             next();
00137             // next() checks the prefix, so we don't need to do that here.
00138         }
00139     } else {
00140         // This assertion isn't true if key contains zero bytes.
00141         // Assert(key == pl_cursor->current_key);
00142         current_term = tname;
00143 
00144         // Check that we haven't gone past the prefix.
00145         if (!startswith(current_term, prefix))
00146             is_at_end = true;
00147     }
00148     RETURN(NULL);
00149 }
00150 
00151 TermList *
00152 QuartzAllTermsList::next()
00153 {
00154     DEBUGCALL(DB, TermList *, "QuartzAllTermsList::next", "");
00155     if (!started) {
00156         started = true;
00157     } else {
00158         while (true) {
00159             pl_cursor->next();
00160 
00161             is_at_end = pl_cursor->after_end();
00162 
00163             if (is_at_end) break;
00164 
00165             const char *start = pl_cursor->current_key.data();
00166             const char *end = start + pl_cursor->current_key.length();
00167             if (!unpack_string_preserving_sort(&start, end, current_term)) {
00168                 throw Xapian::DatabaseCorruptError("Failed to read the key field from a Bcursor's key");
00169             }
00170             if (!startswith(current_term, prefix)) {
00171                 is_at_end = true;
00172                 break;
00173             }
00174             // Check if this is the first chunk of a postlist, skip otherwise
00175             if (start == end) break;
00176         }
00177 
00178         have_stats = false;
00179     }
00180     RETURN(NULL);
00181 }
00182 
00183 bool
00184 QuartzAllTermsList::at_end() const
00185 {
00186     DEBUGCALL(DB, bool, "QuartzAllTermsList::at_end", "");
00187     RETURN(is_at_end);
00188 }

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