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