00001 // 00002 // WordDB.h 00003 // 00004 // WordDB: Interface to Berkeley DB 00005 // uses String and WordReference instead of Dbt, add some convenience 00006 // methods and implements string translation of Berkeley DB error codes. 00007 // It does not include the 'join' feature. 00008 // Beside this, the interface it identical to the Db class. 00009 // The next evolution for this set of class is to have a single object per 00010 // application so that they all share the same environment (transactions, 00011 // shared pool, database directory). This implies a static common object 00012 // that is refered by each actual instance of WordDB. The static object 00013 // holds the DbEnv and DbInfo, the instances of WordDB only have an open 00014 // descriptor using the same DbEnv and DbInfo. 00015 // 00016 // Part of the ht://Dig package <http://www.htdig.org/> 00017 // Copyright (c) 1999, 2000, 2001 The ht://Dig Group 00018 // For copyright details, see the file COPYING in your distribution 00019 // or the GNU General Public License version 2 or later 00020 // <http://www.gnu.org/copyleft/gpl.html> 00021 // 00022 // $Id: WordDB_8h-source.html,v 1.1 2008年06月08日 10:13:07 sebdiaz Exp $ 00023 // 00024 00025 #ifndef _WordDB_h_ 00026 #define _WordDB_h_ 00027 00028 #include <stdio.h> 00029 #include <errno.h> 00030 00031 #include "db.h" 00032 #include "WordReference.h" 00033 #include "WordDBInfo.h" 00034 #include "htString.h" 00035 00036 class WordDBCache; 00037 class WordDBCacheEntry; 00038 00039 #define WORD_DBT_DCL(v) \ 00040 DBT v; \ 00041 memset((char*)&(v), '0円', sizeof(DBT)); \ 00042 v.app_private = user_data 00043 00044 #define WORD_DBT_SET(v,d,s) \ 00045 v.data = (d); \ 00046 v.size = (s) 00047 00048 #define WORD_DBT_INIT(v,d,s) \ 00049 WORD_DBT_DCL(v); \ 00050 WORD_DBT_SET(v,d,s) 00051 00052 class WordDBCursor; 00053 class WordDBCache; 00054 00055 #define WORD_DB_DICT (1 << 4) 00056 #define WORD_DB_INDEX (2 << 4) 00057 #define WORD_DB_DEAD (3 << 4) 00058 #define WORD_DB_FILES (4 << 4) 00059 #define WORD_DB_EXCLUDE (5 << 4) 00060 00061 // 00062 // Encapsulate the DB type 00063 // 00064 // Implements the same methods with String instead of Dbt. 00065 // 00066 // Add convenience methods taking WordReference instead of String 00067 // 00068 // The error model is *not* to use exceptions. 00069 // 00070 // To get a cursor use the Open method of WordDBCursor. I find this 00071 // more convinient than getting a cursor from WordDB. 00072 // 00073 // The WordDB has DbInfo and DbEnv members that can be set before 00074 // calling Open to configure it. 00075 // 00076 class WordDB { 00077 public: 00078 inline WordDB(WordDBInfo& ndb_info) : 00079 db_info(ndb_info) 00080 { 00081 db = 0; 00082 is_open = 0; 00083 cache = 0; 00084 } 00085 inline ~WordDB() { 00086 if(CacheP()) CacheOff(); 00087 Close(); 00088 } 00089 00090 int Alloc(); 00091 00092 int Open(const String& filename, const String& subname, DBTYPE type, int flags, int mode, int tags); 00093 int Remove(const String& filename, const String& subname); 00094 int Close(); 00095 00096 int Fd(int *fdp); 00097 int Stat(void *sp, void *(*db_malloc)(size_t), int flags); 00098 int Sync(int flags); 00099 int get_byteswapped() const; 00100 DBTYPE get_type() const; 00101 unsigned int Size() const; 00102 void Tags(int tags) { db->tags = tags; } 00103 int Tags() const { return db->tags; } 00104 00105 // 00106 // String arguments 00107 // 00108 int Put(DB_TXN *txn, const String& key, const String& data, int flags); 00109 int Put(DB_TXN *txn, const String& key, const unsigned int& data, int flags); 00110 int Get(DB_TXN *txn, String& key, String& data, int flags) const; 00111 int Get(DB_TXN *txn, String& key, unsigned int& data, int flags) const; 00112 int Del(DB_TXN *txn, const String& key); 00113 00114 // 00115 // WordReference argument 00116 // 00117 int Put(const WordReference& wordRef, int flags); 00118 int Del(const WordReference& wordRef); 00119 00120 // 00121 // Search entry matching wkey exactly, return key and data 00122 // in wordRef. 00123 // 00124 int Get(WordReference& wordRef) const; 00125 00126 // 00127 // Returns 0 of the key of wordRef matches an entry in the database. 00128 // Could be implemented with Get but is not because we don't 00129 // need to build a wordRef with the entry found in the base. 00130 // 00131 int Exists(const WordReference& wordRef) const; 00132 00133 // 00134 // Accessors 00135 // 00136 int set_bt_compare(int (*compare)(const DBT *, const DBT *), void *user_data); 00137 int set_pagesize(u_int32_t pagesize); 00138 00139 // 00140 // Cursor 00141 // 00142 WordDBCursor* Cursor(); 00143 00144 // 00145 // Cache management 00146 // 00147 int CacheOn(WordContext* context, int size_hint); 00148 int CacheOff(); 00149 int CacheFlush(); 00150 int CacheCompare(int (*compare)(WordContext *, const WordDBCacheEntry *, const WordDBCacheEntry *)); 00151 int CacheP() const { return cache ? 1 : 0; } 00152 00153 void* user_data; 00154 int is_open; 00155 DB* db; 00156 WordDBInfo& db_info; 00157 WordDBCache* cache; 00158 }; 00159 00160 // 00161 // Interface to DBC that uses String instead of DBT 00162 // 00163 class WordDBCursor { 00164 public: 00165 inline WordDBCursor(WordDB* ndb) { 00166 db = ndb; 00167 user_data = db->user_data; 00168 cursor = 0; 00169 Open(); 00170 } 00171 inline ~WordDBCursor() { 00172 Close(); 00173 } 00174 00175 inline int Open() { 00176 Close(); 00177 return db->db->cursor(db->db, 0, &cursor, 0); 00178 } 00179 00180 inline int Close() { 00181 if(cursor) cursor->c_close(cursor); 00182 cursor = 0; 00183 return 0; 00184 } 00185 00186 inline int Get(String& key, unsigned int& data, int flags) { 00187 db->CacheFlush(); 00188 00189 WORD_DBT_DCL(rkey); 00190 WORD_DBT_DCL(rdata); 00191 switch(flags & DB_OPFLAGS_MASK) { 00192 case DB_SET_RANGE: 00193 case DB_SET: 00194 case DB_GET_BOTH: 00195 WORD_DBT_SET(rkey, (void*)key.get(), key.length()); 00196 break; 00197 } 00198 int error; 00199 data = 0; 00200 if((error = cursor->c_get(cursor, &rkey, &rdata, (u_int32_t)flags)) != 0) { 00201 if(error != DB_NOTFOUND) 00202 fprintf(stderr, "WordDBCursor::Get(%d) failed %s\n", flags, CDB_db_strerror(error)); 00203 } else { 00204 key.set((const char*)rkey.data, (int)rkey.size); 00205 memcpy((char*)&data, (char*)rdata.data, sizeof(unsigned int)); 00206 } 00207 return error; 00208 } 00209 00210 // 00211 // String arguments 00212 // 00213 inline int Get(String& key, String& data, int flags) { 00214 db->CacheFlush(); 00215 00216 WORD_DBT_DCL(rkey); 00217 WORD_DBT_DCL(rdata); 00218 switch(flags & DB_OPFLAGS_MASK) { 00219 case DB_SET_RANGE: 00220 case DB_SET: 00221 case DB_GET_BOTH: 00222 WORD_DBT_SET(rkey, (void*)key.get(), key.length()); 00223 break; 00224 } 00225 int error; 00226 if((error = cursor->c_get(cursor, &rkey, &rdata, (u_int32_t)flags)) != 0) { 00227 if(error != DB_NOTFOUND) 00228 fprintf(stderr, "WordDBCursor::Get(%d) failed %s\n", flags, CDB_db_strerror(error)); 00229 } else { 00230 key.set((const char*)rkey.data, (int)rkey.size); 00231 data.set((const char*)rdata.data, (int)rdata.size); 00232 } 00233 return error; 00234 } 00235 00236 inline int Put(const String& key, const String& data, int flags) { 00237 WORD_DBT_INIT(rkey, (void*)key.get(), (size_t)key.length()); 00238 WORD_DBT_INIT(rdata, (void*)data.get(), (size_t)data.length()); 00239 return cursor->c_put(cursor, &rkey, &rdata, (u_int32_t)flags); 00240 } 00241 00242 inline int Del() { 00243 return cursor->c_del(cursor, (u_int32_t)0); 00244 } 00245 00246 void* user_data; 00247 WordDB* db; 00248 DBC* cursor; 00249 }; 00250 00251 #endif /* _WordDB_h */