00001 00004 /* Copyright (C) 2007,2008,2009 Olly Betts 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License as 00008 * published by the Free Software Foundation; either version 2 of the 00009 * License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <config.h> 00022 00023 #include "brass_valuelist.h" 00024 00025 #include "brass_cursor.h" 00026 #include "brass_database.h" 00027 #include "omassert.h" 00028 #include "str.h" 00029 00030 using namespace Brass; 00031 using namespace std; 00032 00033 bool 00034 BrassValueList::update_reader() 00035 { 00036 Xapian::docid first_did = docid_from_key(slot, cursor->current_key); 00037 if (!first_did) return false; 00038 00039 cursor->read_tag(); 00040 const string & tag = cursor->current_tag; 00041 reader.assign(tag.data(), tag.size(), first_did); 00042 return true; 00043 } 00044 00045 BrassValueList::~BrassValueList() 00046 { 00047 delete cursor; 00048 } 00049 00050 Xapian::docid 00051 BrassValueList::get_docid() const 00052 { 00053 Assert(!at_end()); 00054 return reader.get_docid(); 00055 } 00056 00057 Xapian::valueno 00058 BrassValueList::get_valueno() const 00059 { 00060 return slot; 00061 } 00062 00063 std::string 00064 BrassValueList::get_value() const 00065 { 00066 Assert(!at_end()); 00067 return reader.get_value(); 00068 } 00069 00070 bool 00071 BrassValueList::at_end() const 00072 { 00073 return cursor == NULL; 00074 } 00075 00076 void 00077 BrassValueList::next() 00078 { 00079 if (!cursor) { 00080 cursor = db->get_postlist_cursor(); 00081 if (!cursor) return; 00082 cursor->find_entry_ge(make_valuechunk_key(slot, 1)); 00083 } else if (!reader.at_end()) { 00084 reader.next(); 00085 if (!reader.at_end()) return; 00086 cursor->next(); 00087 } 00088 00089 if (!cursor->after_end()) { 00090 if (update_reader()) { 00091 if (!reader.at_end()) return; 00092 } 00093 } 00094 00095 // We've reached the end. 00096 delete cursor; 00097 cursor = NULL; 00098 } 00099 00100 void 00101 BrassValueList::skip_to(Xapian::docid did) 00102 { 00103 if (!cursor) { 00104 cursor = db->get_postlist_cursor(); 00105 if (!cursor) return; 00106 } else if (!reader.at_end()) { 00107 reader.skip_to(did); 00108 if (!reader.at_end()) return; 00109 } 00110 00111 if (!cursor->find_entry(make_valuechunk_key(slot, did))) { 00112 if (update_reader()) { 00113 reader.skip_to(did); 00114 if (!reader.at_end()) return; 00115 } 00116 // The requested docid is between two chunks. 00117 cursor->next(); 00118 } 00119 00120 // Either an exact match, or in a gap before the start of a chunk. 00121 if (!cursor->after_end()) { 00122 if (update_reader()) { 00123 if (!reader.at_end()) return; 00124 } 00125 } 00126 00127 // We've reached the end. 00128 delete cursor; 00129 cursor = NULL; 00130 } 00131 00132 bool 00133 BrassValueList::check(Xapian::docid did) 00134 { 00135 if (!cursor) { 00136 cursor = db->get_postlist_cursor(); 00137 if (!cursor) return true; 00138 } else if (!reader.at_end()) { 00139 // Check for the requested docid in the current block. 00140 reader.skip_to(did); 00141 if (!reader.at_end()) return true; 00142 } 00143 00144 // Try moving to the appropriate chunk. 00145 if (!cursor->find_entry(make_valuechunk_key(slot, did))) { 00146 // We're in a chunk which might contain the docid. 00147 if (update_reader()) { 00148 reader.skip_to(did); 00149 if (!reader.at_end()) return true; 00150 } 00151 return false; 00152 } 00153 00154 // We had an exact match for a chunk starting with specified docid. 00155 Assert(!cursor->after_end()); 00156 if (!update_reader()) { 00157 // We found the exact key we built, so it must match the slot. 00158 // Therefore update_reader() "can't possibly fail". 00159 Assert(false); 00160 } 00161 00162 return true; 00163 } 00164 00165 string 00166 BrassValueList::get_description() const 00167 { 00168 string desc("BrassValueList(slot="); 00169 desc += str(slot); 00170 desc += ')'; 00171 return desc; 00172 }