mifluz

WordDB.cc

Go to the documentation of this file.
00001 //
00002 // WordDB.cc
00003 //
00004 // Part of the ht://Dig package <http://www.htdig.org/>
00005 // Copyright (c) 1999, 2000, 2001 The ht://Dig Group
00006 // For copyright details, see the file COPYING in your distribution
00007 // or the GNU General Public License version 2 or later
00008 // <http://www.gnu.org/copyleft/gpl.html>
00009 //
00010 // $Id: WordDB_8cc-source.html,v 1.1 2008年06月08日 10:13:06 sebdiaz Exp $
00011 //
00012 
00013 #ifdef HAVE_CONFIG_H
00014 #include "config.h"
00015 #endif /* HAVE_CONFIG_H */
00016 
00017 #include <fcntl.h>
00018 #include <stdlib.h>
00019 
00020 extern "C" {
00021 #include "db_int.h"
00022 #include "db_page.h"
00023 #include "db_shash.h"
00024 #include "lock.h"
00025 #include "mp.h"
00026 }
00027 
00028 #include "myqsort.h"
00029 #include "WordDB.h"
00030 #include "WordDBCache.h"
00031 
00032 class WordContext;
00033 
00034 const char* dberror(int errval) {
00035 #define DB_MAX_ERROR (-DB_TXN_CKP + 1)
00036 static const char* dbstr[DB_MAX_ERROR] = {
00037 "",
00038 "DB_INCOMPLETE",
00039 "DB_KEYEMPTY",
00040 "DB_KEYEXISTS",
00041 "DB_LOCK_DEADLOCK",
00042 "DB_LOCK_NOTGRANTED",
00043 "DB_LOCK_NOTHELD",
00044 "DB_NOTFOUND",
00045 "DB_RUNRECOVERY",
00046 "DB_DELETED",
00047 "DB_NEEDSPLIT",
00048 "DB_SWAPBYTES",
00049 "DB_TXN_CKP",
00050 };
00051 if(errval < 0 && -errval < DB_MAX_ERROR)
00052 return dbstr[-errval];
00053 else
00054 return strerror(errval);
00055 }
00056 
00057 int WordDB::Alloc() {
00058 if(db == 0) {
00059 db = 0;
00060 is_open = 0;
00061 return CDB_db_create(&db, db_info.dbenv, 0);
00062 } else {
00063 return 0;
00064 }
00065 }
00066 
00067 int WordDB::Open(const String& filename, const String& subname, DBTYPE type, int flags, int mode, int tags) {
00068 int error;
00069 if(is_open) {
00070 if((error = Close()) != 0)
00071 return error;
00072 }
00073 
00074 if((error = Alloc()) != 0) return error;
00075 
00076 if(!db_info.dbenv) {
00077 const char* progname = "WordDB";
00078 
00079 //
00080 // Environment initialization
00081 //
00082 // Output errors to the application's log.
00083 //
00084 db->set_errfile(db, stderr);
00085 db->set_errpfx(db, progname);
00086 }
00087 
00088 Tags(tags);
00089 
00090 error = db->open(db,
00091 (const char*)filename,
00092 (subname.empty() ? (const char*)0 : (const char*)subname),
00093 type, (u_int32_t)flags, mode);
00094 
00095 //
00096 // When sharing files among processes, it may not be possible to flush
00097 // all the buffers because another process is locking them. This is not
00098 // fatal since the other process will take care of it.
00099 //
00100 if(error == DB_INCOMPLETE)
00101 error = 0;
00102 
00103 if(error == 0)
00104 is_open = 1;
00105 else
00106 fprintf(stderr, "WordDB::Open(%s,%s,%d,%d,%d) failed %s\n", (const char*)filename, (const char*)subname, type, flags, mode, CDB_db_strerror(error));
00107 
00108 
00109 return error;
00110 }
00111 
00112 int WordDB::Remove(const String& filename, const String& subname) {
00113 int error = 0;
00114 if((error = Close()) != 0) return error;
00115 if((error = Alloc()) != 0) return error;
00116 
00117 DB* tmp = db;
00118 db = 0;
00119 
00120 return tmp->remove(tmp, (const char*)filename, (const char*)subname, 0);
00121 }
00122 
00123 int WordDB::Close() {
00124 int error = 0;
00125 if((error = CacheOff()) != 0) return error;
00126 is_open = 0;
00127 if(db) error = db->close(db, 0);
00128 db = 0;
00129 return error;
00130 }
00131 
00132 int WordDB::Fd(int *fdp) {
00133 if(!is_open) return DB_UNKNOWN;
00134 return db->fd(db, fdp);
00135 }
00136 
00137 int WordDB::Stat(void *sp, void *(*db_malloc)(size_t), int flags) {
00138 if(!is_open) return DB_UNKNOWN;
00139 return db->stat(db, sp, db_malloc, (u_int32_t) flags);
00140 }
00141 
00142 int WordDB::Sync(int flags) {
00143 if(!is_open) return DB_UNKNOWN;
00144 return db->sync(db, (u_int32_t) flags);
00145 }
00146 
00147 int WordDB::get_byteswapped() const {
00148 if(!is_open) return DB_UNKNOWN;
00149 return db->get_byteswapped(db);
00150 }
00151 
00152 DBTYPE WordDB::get_type() const {
00153 if(!is_open) return DB_UNKNOWN;
00154 return db->get_type(db);
00155 }
00156 
00157 unsigned int WordDB::Size() const
00158 {
00159 return (unsigned int)db->mpf->mfp->last_pgno;
00160 }
00161 
00162 //
00163 // String arguments
00164 //
00165 int WordDB::Put(DB_TXN *txn, const String& key, const String& data, int flags) {
00166 if(!is_open) return DB_UNKNOWN;
00167 WORD_DBT_INIT(rkey, (void*)key.get(), key.length());
00168 WORD_DBT_INIT(rdata, (void*)data.get(), data.length());
00169 
00170 if(CacheP()) {
00171 int ret;
00172 //
00173 // If Put is not default (is NOOVERWRITE, for instance),
00174 // flush cache. 
00175 //
00176 if(flags != 0) {
00177 if((ret = CacheFlush()) != 0)
00178 return ret;
00179 return db->put(db, txn, &rkey, &rdata, flags);
00180 } else {
00181 if((ret = cache->Allocate(rkey.size + rdata.size)) == ENOMEM) {
00182 // fprintf(stderr, "No mem ! No mem !\n");
00183 if((ret = CacheFlush()) != 0) return ret;
00184 if((ret = cache->Allocate(rkey.size + rdata.size))) return ret;
00185 }
00186 return cache->Add((char*)rkey.data, rkey.size, (char*)rdata.data, rdata.size);
00187 }
00188 } else {
00189 return db->put(db, txn, &rkey, &rdata, flags);
00190 }
00191 
00192 //
00193 // Should never reach this point
00194 // 
00195 return DB_RUNRECOVERY;
00196 }
00197 
00198 int WordDB::Put(DB_TXN *txn, const String& key, const unsigned int& data, int flags) {
00199 if(!is_open) return DB_UNKNOWN;
00200 WORD_DBT_INIT(rkey, (void*)key.get(), key.length());
00201 WORD_DBT_DCL(rdata);
00202 rdata.data = (void*)&data;
00203 rdata.size = sizeof(unsigned int);
00204 
00205 return db->put(db, txn, &rkey, &rdata, flags);
00206 }
00207 
00208 int WordDB::Get(DB_TXN *txn, String& key, String& data, int flags) const {
00209 if(!is_open) return DB_UNKNOWN;
00210 WORD_DBT_INIT(rkey, (void*)key.get(), (u_int32_t)key.length());
00211 WORD_DBT_INIT(rdata, (void*)data.get(), (u_int32_t)data.length());
00212 
00213 int error;
00214 
00215 if((error = ((WordDB*)this)->CacheFlush()) != 0) return error;
00216 
00217 if((error = db->get(db, txn, &rkey, &rdata, 0)) != 0) {
00218 if(error != DB_NOTFOUND)
00219 fprintf(stderr, "WordDB::Get(%s,%s) using %d failed %s\n", (char*)key, (char*)data, flags, CDB_db_strerror(error));
00220 } else {
00221 //
00222 // Only set arguments if found something.
00223 //
00224 key.set((const char*)rkey.data, (int)rkey.size);
00225 data.set((const char*)rdata.data, (int)rdata.size);
00226 }
00227 
00228 return error;
00229 }
00230 
00231 int WordDB::Get(DB_TXN *txn, String& key, unsigned int& data, int flags) const {
00232 if(!is_open) return DB_UNKNOWN;
00233 WORD_DBT_INIT(rkey, (void*)key.get(), (u_int32_t)key.length());
00234 WORD_DBT_DCL(rdata);
00235 
00236 int error;
00237 
00238 if((error = ((WordDB*)this)->CacheFlush()) != 0) return error;
00239 
00240 if((error = db->get(db, txn, &rkey, &rdata, 0)) != 0) {
00241 if(error != DB_NOTFOUND)
00242 fprintf(stderr, "WordDB::Get(%s,%s) using %d failed %s\n", (char*)key, (char*)data, flags, CDB_db_strerror(error));
00243 } else {
00244 //
00245 // Only set arguments if found something.
00246 //
00247 key.set((const char*)rkey.data, (int)rkey.size);
00248 if(rdata.size == sizeof(unsigned int)) 
00249 memcpy((char*)&data, (char*)rdata.data, sizeof(unsigned int));
00250 else
00251 data = 0;
00252 }
00253 
00254 return error;
00255 }
00256 
00257 int WordDB::Del(DB_TXN *txn, const String& key) {
00258 if(!is_open) return DB_UNKNOWN;
00259 WORD_DBT_INIT(rkey, (void*)key.get(), (u_int32_t)key.length());
00260 
00261 int error;
00262 
00263 if((error = CacheFlush()) != 0) return error;
00264 
00265 return db->del(db, txn, &rkey, 0);
00266 }
00267 
00268 //
00269 // WordReference argument
00270 //
00271 int WordDB::Put(const WordReference& wordRef, int flags) {
00272 if(!is_open) return DB_UNKNOWN;
00273 
00274 int ret;
00275 
00276 String key;
00277 String record;
00278 
00279 if((ret = wordRef.Pack(key, record)) != OK) return DB_RUNRECOVERY;
00280 
00281 return Put(0, key, record, flags);
00282 }
00283 
00284 int WordDB::Del(const WordReference& wordRef) {
00285 if(!is_open) return DB_UNKNOWN;
00286 
00287 String key;
00288 
00289 wordRef.Key().Pack(key);
00290 
00291 return Del(0, key);
00292 }
00293 
00294 //
00295 // Search entry matching wkey exactly, return key and data
00296 // in wordRef.
00297 //
00298 int WordDB::Get(WordReference& wordRef) const {
00299 if(!is_open) return DB_UNKNOWN;
00300 
00301 String data;
00302 String key;
00303 
00304 if(wordRef.Key().Pack(key) != OK) return DB_RUNRECOVERY;
00305 
00306 int ret;
00307 if((ret = Get(0, key, data, 0)) != 0)
00308 return ret;
00309 
00310 return wordRef.Unpack(key, data) == OK ? 0 : DB_RUNRECOVERY;
00311 }
00312 
00313 //
00314 // Returns 0 of the key of wordRef matches an entry in the database.
00315 // Could be implemented with Get but is not because we don't
00316 // need to build a wordRef with the entry found in the base. 
00317 //
00318 int WordDB::Exists(const WordReference& wordRef) const {
00319 if(!is_open) return DB_UNKNOWN;
00320 
00321 String key;
00322 String data;
00323 
00324 if(wordRef.Key().Pack(key) != OK) return DB_RUNRECOVERY;
00325 
00326 return Get(0, key, data, 0);
00327 }
00328 
00329 //
00330 // Accessors
00331 //
00332 int WordDB::set_bt_compare(int (*compare)(const DBT *, const DBT *), void *nuser_data) {
00333 int ret;
00334 if((ret = Alloc()) != 0) return ret;
00335 user_data = nuser_data;
00336 return db->set_bt_compare(db, compare);
00337 }
00338 
00339 int WordDB::set_pagesize(u_int32_t pagesize) {
00340 if(pagesize <= 0) return 0;
00341 int ret;
00342 if((ret = Alloc()) != 0) return ret;
00343 return db->set_pagesize(db, pagesize);
00344 }
00345 
00346 //
00347 // Cursor
00348 //
00349 WordDBCursor* WordDB::Cursor() {
00350 if(!is_open) return 0;
00351 
00352 WordDBCursor *cursor = new WordDBCursor(this);
00353 return cursor->cursor ? cursor : 0;
00354 }
00355 
00356 //
00357 // Cache management
00358 //
00359 int WordDB::CacheOn(WordContext* context, int size_hint)
00360 {
00361 if(!CacheP()) {
00362 cache = new WordDBCache(context);
00363 cache->SetMax(size_hint);
00364 }
00365 
00366 return 0;
00367 }
00368 
00369 int WordDB::CacheOff()
00370 {
00371 if(CacheP()) {
00372 int ret;
00373 if((ret = CacheFlush()) != 0) return ret;
00374 
00375 delete cache;
00376 cache = 0;
00377 }
00378 
00379 return 0;
00380 }
00381 
00382 int WordDB::CacheFlush()
00383 {
00384 if(CacheP() && !cache->Empty()) {
00385 // fprintf(stderr, "Flush ! Flush !\n");
00386 cache->Sort();
00387 WordDBCacheEntry* entries;
00388 int entries_length;
00389 int ret;
00390 if((ret = cache->Entries(entries, entries_length)) != 0)
00391 return ret;
00392 int i;
00393 WORD_DBT_DCL(key);
00394 WORD_DBT_DCL(record);
00395 for(i = 0; i < entries_length; i++) {
00396 WORD_DBT_SET(key, entries[i].key, entries[i].key_size);
00397 WORD_DBT_SET(record, entries[i].data, entries[i].data_size);
00398 if((ret = db->put(db, 0, &key, &record, 0)) != 0)
00399 return ret;
00400 }
00401 cache->Flush();
00402 // fprintf(stderr, "Flushed ! Flushed !\n");
00403 } 
00404 
00405 return 0;
00406 }
00407 
00408 int WordDB::CacheCompare(int (*compare)(WordContext *, const WordDBCacheEntry *, const WordDBCacheEntry *)) {
00409 if(!CacheP()) {
00410 fprintf(stderr, "WordDB::CacheCompare: cannot set comparison function for cache on because the cache is not active\n");
00411 return DB_RUNRECOVERY;
00412 }
00413 return cache->SetCompare(compare);
00414 }

Generated on Sun Jun 8 10:56:40 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /