1 //
2 // WordMeta.cc
3 //
4 // Part of the ht://Dig package <http://www.htdig.org/>
5 // Copyright (c) 1999-2004 The ht://Dig Group
6 // For copyright details, see the file COPYING in your distribution
7 // or the GNU Library General Public License (LGPL) version 2 or later
8 // <http://www.gnu.org/copyleft/lgpl.html>
9 //
10 // $Id: WordMeta.cc,v 1.4 2004/05/28 13:15:28 lha Exp $
11 //
12 #ifdef HAVE_CONFIG_H
13 #include "htconfig.h"
14 #endif /* HAVE_CONFIG_H */
15
16 #include <fcntl.h>
17
18 extern "C" {
19 #include "db_int.h"
20 #include "db_page.h"
21 #include "db_shash.h"
22 #include "lock.h"
23 #include "mp.h"
24 }
25
26 #include "WordMeta.h"
27 #include "WordListOne.h"
28
29 #define WORD_META_SERIAL_SIZE (WORD_META_SERIAL_FILE + 1)
30
31 class WordLock {
32 public:
WordLock()33 WordLock() { lock.off = LOCK_INVALID; }
34
35 DB_LOCK lock;
36 };
37
38 //
39 // Total size of structure must *NOT* be over 256 bytes.
40 //
41 typedef struct _WordMetaInfo {
42 DBMETA meta;
43 unsigned int serials[WORD_META_SERIAL_SIZE];
44 } WordMetaInfo;
45
46 class WordMetaImp
47 {
48 public:
WordMetaImp()49 WordMetaImp() {
50 mpf = 0;
51 pgno = PGNO_INVALID;
52 info = 0;
53 }
54
55 DB_MPOOLFILE *mpf;
56 db_pgno_t pgno;
57 WordMetaInfo *info;
58 };
59
~WordMeta()60 WordMeta::~WordMeta()
61 {
62 delete imp;
63 delete db;
64 }
65
Initialize(WordList * nwords)66 int WordMeta::Initialize(WordList* nwords)
67 {
68 words = nwords;
69 db = new WordDB(nwords->GetContext()->GetDBInfo());
70 imp = new WordMetaImp();
71 return OK;
72 }
73
Open()74 int WordMeta::Open()
75 {
76 const String& filename = words->Filename();
77 int flags = words->Flags();
78
79 db->set_pagesize(words->Pagesize());
80
81 if(db->Open(filename, "meta", DB_BTREE, flags, 0666, WORD_DB_DICT) != 0)
82 return NOTOK;
83
84 imp->mpf = db->db->mpf;
85
86 int ret;
87 String kpgno("pgno");
88
89 if((ret = db->Get(0, kpgno, imp->pgno, 0)) != 0 && ret != DB_NOTFOUND)
90 return NOTOK;
91
92 /*
93 * First time thru, create the meta page and initialize it.
94 */
95 if(ret == DB_NOTFOUND) {
96 if(CDB_memp_fget(imp->mpf, &imp->pgno, DB_MPOOL_NEW, (void**)&imp->info) != 0)
97 return NOTOK;
98 memset((char*)imp->info, '\0', sizeof(WordMetaInfo));
99 imp->info->meta.type = P_INVALID;
100 imp->info->meta.pgno = imp->pgno;
101 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
102 return NOTOK;
103
104 if(db->Put(0, kpgno, imp->pgno, 0) != 0)
105 return NOTOK;
106 }
107
108 return OK;
109 }
110
Close()111 int WordMeta::Close()
112 {
113 return db->Close() == 0 ? OK : NOTOK;
114 }
115
Serial(int what,unsigned int & serial)116 int WordMeta::Serial(int what, unsigned int& serial)
117 {
118 serial = WORD_META_SERIAL_INVALID;
119 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
120 return NOTOK;
121 serial = ++imp->info->serials[what];
122 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
123 return NOTOK;
124
125 return OK;
126 }
127
GetSerial(int what,unsigned int & serial)128 int WordMeta::GetSerial(int what, unsigned int& serial)
129 {
130 serial = WORD_META_SERIAL_INVALID;
131 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
132 return NOTOK;
133 serial = imp->info->serials[what];
134 if(CDB_memp_fput(imp->mpf, (void*)imp->info, 0) != 0)
135 return NOTOK;
136
137 return OK;
138 }
139
SetSerial(int what,unsigned int serial)140 int WordMeta::SetSerial(int what, unsigned int serial)
141 {
142 if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
143 return NOTOK;
144 imp->info->serials[what] = serial;
145 if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
146 return NOTOK;
147
148 return OK;
149 }
150
Lock(const String & resource,WordLock * & lock)151 int WordMeta::Lock(const String& resource, WordLock*& lock)
152 {
153 lock = new WordLock;
154 DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
155 u_int32_t id;
156 if(CDB_lock_id(dbenv, &id) != 0) {
157 delete lock;
158 lock = 0;
159 return NOTOK;
160 }
161 DBT obj;
162 obj.size = resource.length();
163 obj.data = (void*)resource.get();
164 if(CDB_lock_get(dbenv, id, 0, &obj, DB_LOCK_WRITE, &lock->lock) != 0) {
165 delete lock;
166 lock = 0;
167 return NOTOK;
168 }
169 return OK;
170 }
171
Unlock(const String & resource,WordLock * & lock)172 int WordMeta::Unlock(const String& resource, WordLock*& lock)
173 {
174 DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
175
176 int ret = CDB_lock_put(dbenv, &lock->lock);
177
178 delete lock;
179 lock = 0;
180
181 return ret == 0 ? OK : NOTOK;
182 }
183