00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #endif
00015
00016 #include <fcntl.h>
00017
00018 extern "C" {
00019 #include "db_int.h"
00020 #include "db_page.h"
00021 #include "db_shash.h"
00022 #include "lock.h"
00023 #include "mp.h"
00024 }
00025
00026 #include "WordMeta.h"
00027 #include "WordListOne.h"
00028
00029 #define WORD_META_SERIAL_SIZE (WORD_META_SERIAL_FILE + 1)
00030
00031 class WordLock {
00032 public:
00033 WordLock() { lock.off = LOCK_INVALID; }
00034
00035 DB_LOCK lock;
00036 };
00037
00038
00039
00040
00041 typedef struct _WordMetaInfo {
00042 DBMETA meta;
00043 unsigned int serials[WORD_META_SERIAL_SIZE];
00044 } WordMetaInfo;
00045
00046 class WordMetaImp
00047 {
00048 public:
00049 WordMetaImp() {
00050 mpf = 0;
00051 pgno = PGNO_INVALID;
00052 info = 0;
00053 }
00054
00055 DB_MPOOLFILE *mpf;
00056 db_pgno_t pgno;
00057 WordMetaInfo *info;
00058 };
00059
00060 WordMeta::~WordMeta()
00061 {
00062 delete imp;
00063 delete db;
00064 }
00065
00066 int WordMeta::Initialize(WordList* nwords)
00067 {
00068 words = nwords;
00069 db = new WordDB(nwords->GetContext()->GetDBInfo());
00070 imp = new WordMetaImp();
00071 return OK;
00072 }
00073
00074 int WordMeta::Open()
00075 {
00076 const String& filename = words->Filename();
00077 int flags = words->Flags();
00078
00079 db->set_pagesize(words->Pagesize());
00080
00081 if(db->Open(filename, "meta", DB_BTREE, flags, 0666, WORD_DB_DICT) != 0)
00082 return NOTOK;
00083
00084 imp->mpf = db->db->mpf;
00085
00086 int ret;
00087 String kpgno("pgno");
00088
00089 if((ret = db->Get(0, kpgno, imp->pgno, 0)) != 0 && ret != DB_NOTFOUND)
00090 return NOTOK;
00091
00092
00093
00094
00095 if(ret == DB_NOTFOUND) {
00096 if(CDB_memp_fget(imp->mpf, &imp->pgno, DB_MPOOL_NEW, (void**)&imp->info) != 0)
00097 return NOTOK;
00098 memset((char*)imp->info, '\0', sizeof(WordMetaInfo));
00099 imp->info->meta.type = P_INVALID;
00100 imp->info->meta.pgno = imp->pgno;
00101 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
00102 return NOTOK;
00103
00104 if(db->Put(0, kpgno, imp->pgno, 0) != 0)
00105 return NOTOK;
00106 }
00107
00108 return OK;
00109 }
00110
00111 int WordMeta::Close()
00112 {
00113 return db->Close() == 0 ? OK : NOTOK;
00114 }
00115
00116 int WordMeta::Serial(int what, unsigned int& serial)
00117 {
00118 serial = WORD_META_SERIAL_INVALID;
00119 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
00120 return NOTOK;
00121 serial = ++imp->info->serials[what];
00122 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
00123 return NOTOK;
00124
00125 return OK;
00126 }
00127
00128 int WordMeta::GetSerial(int what, unsigned int& serial)
00129 {
00130 serial = WORD_META_SERIAL_INVALID;
00131 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
00132 return NOTOK;
00133 serial = imp->info->serials[what];
00134 if(CDB_memp_fput(imp->mpf, (void*)imp->info, 0) != 0)
00135 return NOTOK;
00136
00137 return OK;
00138 }
00139
00140 int WordMeta::SetSerial(int what, unsigned int serial)
00141 {
00142 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
00143 return NOTOK;
00144 imp->info->serials[what] = serial;
00145 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
00146 return NOTOK;
00147
00148 return OK;
00149 }
00150
00151 int WordMeta::Lock(const String& resource, WordLock*& lock)
00152 {
00153 lock = new WordLock;
00154 DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
00155 u_int32_t id;
00156 if(CDB_lock_id(dbenv, &id) != 0) {
00157 delete lock;
00158 lock = 0;
00159 return NOTOK;
00160 }
00161 DBT obj;
00162 obj.size = resource.length();
00163 obj.data = (void*)resource.get();
00164 if(CDB_lock_get(dbenv, id, 0, &obj, DB_LOCK_WRITE, &lock->lock) != 0) {
00165 delete lock;
00166 lock = 0;
00167 return NOTOK;
00168 }
00169 return OK;
00170 }
00171
00172 int WordMeta::Unlock(const String& resource, WordLock*& lock)
00173 {
00174 DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
00175
00176 int ret = CDB_lock_put(dbenv, &lock->lock);
00177
00178 delete lock;
00179 lock = 0;
00180
00181 return ret == 0 ? OK : NOTOK;
00182 }