source: gsdl/trunk/common-src/src/lib/gdbmclass.cpp@ 17065

Last change on this file since 17065 was 17065, checked in by mdewsnip, 16 years ago

Added check that the GDBM .txt.gz file actually exists before trying to unzip it, to prevent confusing messages in the error.txt file.

File size: 7.4 KB
Line 
1/**********************************************************************
2 *
3 * gdbmclass.cpp --
4 * Copyright (C) 1999-2008 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "gdbmclass.h"
27#include "gsdltools.h"
28#include "gsdlunicode.h"
29#include "fileutil.h"
30
31
32
33
34gdbmclass::~gdbmclass()
35{
36 closedatabase();
37}
38
39
40// returns true if opened
41bool gdbmclass::opendatabase (const text_t &filename, int mode, int num_retrys,
42#ifdef __WIN32__
43 bool need_filelock
44#else
45 bool
46#endif
47 )
48{
49
50 text_t data_location;
51 int block_size = 512;
52
53 if (gdbmfile != NULL) {
54 if (openfile == filename) return true;
55 else closedatabase ();
56 }
57
58 openfile = filename;
59
60 // Map the DB mode values into GDBM mode values
61 int gdbm_mode = GDBM_READER;
62 if (mode == DB_WRITER)
63 {
64 gdbm_mode = GDBM_WRITER;
65 }
66 else if (mode == DB_WRITER_CREATE)
67 {
68 gdbm_mode = GDBM_WRCREAT;
69 }
70
71 if (gdbm_mode == GDBM_READER) {
72 // Looking to read in the database
73 // => check to see if .ldb/.bdb file already there
74 // if not (first time) then generate using txt2db
75 if (!file_exists(filename)) {
76
77 // need to generate architecture native GDBM file using txt2db
78
79 // replace sought after gdbm filename ext with ".txt.gz"
80
81 text_t::const_iterator begin = filename.begin();
82 text_t::const_iterator end= filename.end();
83 text_t::const_iterator here = end;
84
85 bool found_ext = false;
86
87 while (here != begin) {
88 if (*here == '.') {
89 found_ext = true;
90 break;
91 }
92 here--;
93 }
94
95 text_t filename_root;
96
97 if (found_ext) {
98 filename_root = substr(begin,here);
99 }
100 else {
101 filename_root = filename;
102 }
103
104 text_t txtgz_filename = filename_root + ".txt.gz";
105 if (file_exists(txtgz_filename))
106 {
107 text_t cmd = "gzip --decompress --to-stdout \"" + txtgz_filename + "\"";
108 cmd += " | txt2db \"" + filename + "\"";
109
110 int rv = gsdl_system(cmd, true, cerr);
111 if (rv != 0) {
112 cerr << "Tried to run command \""<<cmd<<"\", but it failed\n";
113 }
114 }
115 }
116 }
117
118 char *namebuffer = filename.getcstr();
119 do {
120#ifdef __WIN32__
121 gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL, (need_filelock) ? 1 : 0);
122#else
123 gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL);
124#endif
125 --num_retrys;
126 } while (num_retrys>0 && gdbmfile==NULL &&
127 (gdbm_errno==GDBM_CANT_BE_READER || gdbm_errno==GDBM_CANT_BE_WRITER));
128 delete []namebuffer;
129
130 if (gdbmfile == NULL && logout != NULL) {
131 outconvertclass text_t2ascii;
132 (*logout) << text_t2ascii << "database open failed on: " << filename << "\n";
133 }
134
135 return (gdbmfile != NULL);
136}
137
138
139void gdbmclass::closedatabase ()
140{
141 if (gdbmfile == NULL) return;
142
143 gdbm_close (gdbmfile);
144 gdbmfile = NULL;
145 openfile.clear();
146}
147
148
149void gdbmclass::deletekey (const text_t &key)
150{
151 if (gdbmfile == NULL) return;
152
153 // get a utf-8 encoded c string of the unicode key
154 datum key_data;
155 key_data.dptr = (to_utf8(key)).getcstr();
156 if (key_data.dptr == NULL) return;
157 key_data.dsize = strlen (key_data.dptr);
158
159 // delete the key
160 gdbm_delete (gdbmfile, key_data);
161
162 // free up the key memory
163 delete []key_data.dptr;
164}
165
166
167// returns file extension string
168text_t gdbmclass::getfileextension ()
169{
170 if (littleEndian()) return ".ldb";
171 return ".bdb";
172}
173
174
175// returns true on success
176bool gdbmclass::getkeydata (const text_t& key, text_t &data)
177{
178 datum key_data;
179 datum return_data;
180
181 if (gdbmfile == NULL) return false;
182
183 // get a utf-8 encoded c string of the unicode key
184 key_data.dptr = (to_utf8(key)).getcstr();
185 if (key_data.dptr == NULL) {
186 if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
187 return false;
188 }
189 key_data.dsize = strlen (key_data.dptr);
190
191 // fetch the result
192 return_data = gdbm_fetch (gdbmfile, key_data);
193 delete []key_data.dptr;
194
195 if (return_data.dptr == NULL) return false;
196
197 data.setcarr (return_data.dptr, return_data.dsize);
198 free (return_data.dptr);
199 data = to_uni(data); // convert to unicode
200
201 return true;
202}
203
204
205// returns array of keys
206text_tarray gdbmclass::getkeys ()
207{
208 text_tarray keys;
209
210 text_t key = getfirstkey();
211 while (!key.empty())
212 {
213 keys.push_back(key);
214 key = getnextkey(key);
215 }
216
217 return keys;
218}
219
220
221// returns true on success
222bool gdbmclass::setkeydata (const text_t &key, const text_t &data)
223{
224 if (gdbmfile == NULL) return false;
225
226 // store the value
227 datum key_data;
228 datum data_data;
229
230 // get a utf-8 encoded c string of the unicode key
231 key_data.dptr = (to_utf8(key)).getcstr();
232 if (key_data.dptr == NULL) {
233 if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
234 return false;
235 }
236 key_data.dsize = strlen (key_data.dptr);
237
238 data_data.dptr = (to_utf8(data)).getcstr();
239 if (data_data.dptr == NULL) {
240 if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
241 delete []key_data.dptr;
242 return false;
243 }
244 data_data.dsize = strlen (data_data.dptr);
245
246 int ret = gdbm_store (gdbmfile, key_data, data_data, GDBM_REPLACE);
247 delete []key_data.dptr;
248 delete []data_data.dptr;
249
250 return (ret == 0);
251}
252
253
254// ----------------------------------------------------------------------------------------
255// GDBM-ONLY FUNCTIONS
256// ----------------------------------------------------------------------------------------
257
258// getfirstkey and getnextkey are used for traversing the database
259// no insertions or deletions should be carried out while traversing
260// the database. when there are no keys left to visit in the database
261// an empty string is returned.
262text_t gdbmclass::getfirstkey ()
263{
264 if (gdbmfile == NULL) return g_EmptyText;
265
266 // get the first key
267 datum firstkey_data = gdbm_firstkey (gdbmfile);
268 if (firstkey_data.dptr == NULL) return g_EmptyText;
269
270 // convert it to text_t
271 text_t firstkey;
272 firstkey.setcarr (firstkey_data.dptr, firstkey_data.dsize);
273 free (firstkey_data.dptr);
274 return to_uni(firstkey); // convert to unicode
275}
276
277
278text_t gdbmclass::getnextkey (const text_t &key)
279{
280 if (gdbmfile == NULL || key.empty()) return g_EmptyText;
281
282 // get a utf-8 encoded c string of the unicode key
283 datum key_data;
284 key_data.dptr = (to_utf8(key)).getcstr();
285 if (key_data.dptr == NULL) return g_EmptyText;
286 key_data.dsize = strlen (key_data.dptr);
287
288 // get the next key
289 datum nextkey_data = gdbm_nextkey (gdbmfile, key_data);
290 if (nextkey_data.dptr == NULL) {
291 delete []key_data.dptr;
292 return g_EmptyText;
293 }
294
295 // convert it to text_t
296 text_t nextkey;
297 nextkey.setcarr (nextkey_data.dptr, nextkey_data.dsize);
298 free (nextkey_data.dptr);
299 delete []key_data.dptr;
300 return to_uni(nextkey); // convert to unicode
301}
Note: See TracBrowser for help on using the repository browser.