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