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

Last change on this file since 17719 was 17719, checked in by ak19, 15 years ago

A few more endl instead of slash newline character inserted, may make this more platform independent

File size: 8.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#include "stdlib.h"
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 // Test to make sure Perl is on the path
111 text_t cmd_test = "perl -v";
112 int rv_test = gsdl_system(cmd_test, true, cerr);
113 if (rv_test != 0) {
114 cerr << "Tried to find Perl. Return exit value of running "
115 << cmd_test <<": "<< rv_test << ", (expected this to be 0)" << endl;
116 cerr << "Check that Perl is set in your environment variable PATH." << endl;
117 cerr << "At present, PATH=" << getenv("PATH") << endl;
118 }
119
120 text_t cmd = "perl -S txtgz-to-gdbm.pl \"" + txtgz_filename + "\" \"" + filename + "\"";
121 int rv = gsdl_system(cmd, true, cerr);
122 // For some reason, launching this command with gsdl_system() still returns 1
123 // even when it returns 0 when run from the command-line. We can check whether
124 // we succeeded by looking at whether the output database file was created.
125 if (rv != 0) {
126 cerr << "Warning, non-zero return value on running command \""
127 << cmd << "\": " << rv << endl;
128 if (!file_exists(filename)) {
129 cerr << "Tried to run command \""<<cmd<<"\", but it failed" << endl;
130 }
131 }
132 }
133 }
134 }
135
136 char *namebuffer = filename.getcstr();
137 do {
138#ifdef __WIN32__
139 gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL, (need_filelock) ? 1 : 0);
140#else
141 gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL);
142#endif
143 --num_retrys;
144 } while (num_retrys>0 && gdbmfile==NULL &&
145 (gdbm_errno==GDBM_CANT_BE_READER || gdbm_errno==GDBM_CANT_BE_WRITER));
146 delete []namebuffer;
147
148 if (gdbmfile == NULL && logout != NULL) {
149 outconvertclass text_t2ascii;
150 (*logout) << text_t2ascii << "database open failed on: " << filename << "\n";
151 }
152
153 return (gdbmfile != NULL);
154}
155
156
157void gdbmclass::closedatabase ()
158{
159 if (gdbmfile == NULL) return;
160
161 gdbm_close (gdbmfile);
162 gdbmfile = NULL;
163 openfile.clear();
164}
165
166
167void gdbmclass::deletekey (const text_t &key)
168{
169 if (gdbmfile == NULL) return;
170
171 // get a utf-8 encoded c string of the unicode key
172 datum key_data;
173 key_data.dptr = (to_utf8(key)).getcstr();
174 if (key_data.dptr == NULL) return;
175 key_data.dsize = strlen (key_data.dptr);
176
177 // delete the key
178 gdbm_delete (gdbmfile, key_data);
179
180 // free up the key memory
181 delete []key_data.dptr;
182}
183
184
185// returns file extension string
186text_t gdbmclass::getfileextension ()
187{
188 if (littleEndian()) return ".ldb";
189 return ".bdb";
190}
191
192
193// returns true on success
194bool gdbmclass::getkeydata (const text_t& key, text_t &data)
195{
196 datum key_data;
197 datum return_data;
198
199 if (gdbmfile == NULL) return false;
200
201 // get a utf-8 encoded c string of the unicode key
202 key_data.dptr = (to_utf8(key)).getcstr();
203 if (key_data.dptr == NULL) {
204 if (logout != NULL) (*logout) << "gdbmclass: out of memory" << endl;
205 return false;
206 }
207 key_data.dsize = strlen (key_data.dptr);
208
209 // fetch the result
210 return_data = gdbm_fetch (gdbmfile, key_data);
211 delete []key_data.dptr;
212
213 if (return_data.dptr == NULL) return false;
214
215 data.setcarr (return_data.dptr, return_data.dsize);
216 free (return_data.dptr);
217 data = to_uni(data); // convert to unicode
218
219 return true;
220}
221
222
223// returns array of keys
224text_tarray gdbmclass::getkeys ()
225{
226 text_tarray keys;
227
228 text_t key = getfirstkey();
229 while (!key.empty())
230 {
231 keys.push_back(key);
232 key = getnextkey(key);
233 }
234
235 return keys;
236}
237
238
239// returns true on success
240bool gdbmclass::setkeydata (const text_t &key, const text_t &data)
241{
242 if (gdbmfile == NULL) return false;
243
244 // store the value
245 datum key_data;
246 datum data_data;
247
248 // get a utf-8 encoded c string of the unicode key
249 key_data.dptr = (to_utf8(key)).getcstr();
250 if (key_data.dptr == NULL) {
251 if (logout != NULL) (*logout) << "gdbmclass: out of memory" << endl;
252 return false;
253 }
254 key_data.dsize = strlen (key_data.dptr);
255
256 data_data.dptr = (to_utf8(data)).getcstr();
257 if (data_data.dptr == NULL) {
258 if (logout != NULL) (*logout) << "gdbmclass: out of memory" << endl;
259 delete []key_data.dptr;
260 return false;
261 }
262 data_data.dsize = strlen (data_data.dptr);
263
264 int ret = gdbm_store (gdbmfile, key_data, data_data, GDBM_REPLACE);
265 delete []key_data.dptr;
266 delete []data_data.dptr;
267
268 return (ret == 0);
269}
270
271
272// ----------------------------------------------------------------------------------------
273// GDBM-ONLY FUNCTIONS
274// ----------------------------------------------------------------------------------------
275
276// getfirstkey and getnextkey are used for traversing the database
277// no insertions or deletions should be carried out while traversing
278// the database. when there are no keys left to visit in the database
279// an empty string is returned.
280text_t gdbmclass::getfirstkey ()
281{
282 if (gdbmfile == NULL) return g_EmptyText;
283
284 // get the first key
285 datum firstkey_data = gdbm_firstkey (gdbmfile);
286 if (firstkey_data.dptr == NULL) return g_EmptyText;
287
288 // convert it to text_t
289 text_t firstkey;
290 firstkey.setcarr (firstkey_data.dptr, firstkey_data.dsize);
291 free (firstkey_data.dptr);
292 return to_uni(firstkey); // convert to unicode
293}
294
295
296text_t gdbmclass::getnextkey (const text_t &key)
297{
298 if (gdbmfile == NULL || key.empty()) return g_EmptyText;
299
300 // get a utf-8 encoded c string of the unicode key
301 datum key_data;
302 key_data.dptr = (to_utf8(key)).getcstr();
303 if (key_data.dptr == NULL) return g_EmptyText;
304 key_data.dsize = strlen (key_data.dptr);
305
306 // get the next key
307 datum nextkey_data = gdbm_nextkey (gdbmfile, key_data);
308 if (nextkey_data.dptr == NULL) {
309 delete []key_data.dptr;
310 return g_EmptyText;
311 }
312
313 // convert it to text_t
314 text_t nextkey;
315 nextkey.setcarr (nextkey_data.dptr, nextkey_data.dsize);
316 free (nextkey_data.dptr);
317 delete []key_data.dptr;
318 return to_uni(nextkey); // convert to unicode
319}
Note: See TracBrowser for help on using the repository browser.