root/gsdl/trunk/lib/gdbmclass.cpp @ 15655

Revision 15655, 6.2 KB (checked in by mdewsnip, 11 years ago)

(Adding new DB support) Created default implementations of getinfo() and setinfo() in dbclass so they don't necessarily be re-implemented for every subclass.

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 "unitool.h"
28#include "gsdlunicode.h"
29#include "OIDtools.h"
30
31
32gdbmclass::~gdbmclass()
33{
34  closedatabase();
35}
36
37
38// returns true if opened
39bool gdbmclass::opendatabase (const text_t &filename, int mode, int num_retrys,
40#ifdef __WIN32__
41                  bool need_filelock
42#else
43                              bool
44#endif
45                  )
46{
47  text_t data_location;
48  int block_size = 512;
49 
50  if (gdbmfile != NULL) {
51    if (openfile == filename) return true;
52    else closedatabase ();
53  }
54
55  openfile = filename;
56
57  // Map the DB mode values into GDBM mode values
58  int gdbm_mode = GDBM_READER;
59  if (mode == DB_WRITER)
60  {
61    gdbm_mode = GDBM_WRITER;
62  }
63  else if (mode == DB_WRITER_CREATE)
64  {
65    gdbm_mode = GDBM_WRCREAT;
66  }
67
68  char *namebuffer = filename.getcstr();
69  do {
70#ifdef __WIN32__
71    gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL, (need_filelock) ? 1 : 0);
72#else
73    gdbmfile = gdbm_open (namebuffer, block_size, gdbm_mode, 00664, NULL);
74#endif
75    --num_retrys;
76  } while (num_retrys>0 && gdbmfile==NULL &&
77       (gdbm_errno==GDBM_CANT_BE_READER || gdbm_errno==GDBM_CANT_BE_WRITER));
78  delete []namebuffer;
79 
80  if (gdbmfile == NULL && logout != NULL) {
81    outconvertclass text_t2ascii;
82    (*logout) << text_t2ascii << "database open failed on: " << filename << "\n";
83  }
84
85  return (gdbmfile != NULL);
86}
87
88
89void gdbmclass::closedatabase ()
90{
91  if (gdbmfile == NULL) return;
92 
93  gdbm_close (gdbmfile);
94  gdbmfile = NULL;
95  openfile.clear();
96}
97
98
99void gdbmclass::deletekey (const text_t &key)
100{
101  if (gdbmfile == NULL) return;
102
103  // get a utf-8 encoded c string of the unicode key
104  datum key_data;
105  key_data.dptr = (to_utf8(key)).getcstr();
106  if (key_data.dptr == NULL) return;
107  key_data.dsize = strlen (key_data.dptr);
108
109  // delete the key
110  gdbm_delete (gdbmfile, key_data);
111
112  // free up the key memory
113  delete []key_data.dptr;
114}
115
116
117// returns true on success
118bool gdbmclass::getkeydata (const text_t& key, text_t &data)
119{
120  datum key_data;
121  datum return_data;
122
123  if (gdbmfile == NULL) return false;
124 
125  // get a utf-8 encoded c string of the unicode key
126  key_data.dptr = (to_utf8(key)).getcstr();
127  if (key_data.dptr == NULL) {
128    if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
129    return false;
130  }
131  key_data.dsize = strlen (key_data.dptr);
132 
133  // fetch the result
134  return_data = gdbm_fetch (gdbmfile, key_data);
135  delete []key_data.dptr;
136 
137  if (return_data.dptr == NULL) return false;
138
139  data.setcarr (return_data.dptr, return_data.dsize);
140  free (return_data.dptr);
141  data = to_uni(data);  // convert to unicode
142
143  return true;
144}
145
146
147// returns array of keys
148text_tarray gdbmclass::getkeys ()
149{
150  text_tarray keys;
151
152  text_t key = getfirstkey();
153  while (!key.empty())
154  {
155    keys.push_back(key);
156    key = getnextkey(key);
157  }
158
159  return keys;
160}
161
162
163// returns true on success
164bool gdbmclass::setkeydata (const text_t &key, const text_t &data)
165{
166  if (gdbmfile == NULL) return false;
167 
168  // store the value
169  datum key_data;
170  datum data_data;
171
172  // get a utf-8 encoded c string of the unicode key
173  key_data.dptr = (to_utf8(key)).getcstr();
174  if (key_data.dptr == NULL) {
175    if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
176    return false;
177  }
178  key_data.dsize = strlen (key_data.dptr);
179
180  data_data.dptr = (to_utf8(data)).getcstr();
181  if (data_data.dptr == NULL) {
182    if (logout != NULL) (*logout) << "gdbmclass: out of memory\n";
183    delete []key_data.dptr;
184    return false;
185  }
186  data_data.dsize = strlen (data_data.dptr);
187
188  int ret = gdbm_store (gdbmfile, key_data, data_data, GDBM_REPLACE);
189  delete []key_data.dptr;
190  delete []data_data.dptr;
191
192  return (ret == 0);
193}
194
195
196// ----------------------------------------------------------------------------------------
197//   GDBM-ONLY FUNCTIONS
198// ----------------------------------------------------------------------------------------
199
200// getfirstkey and getnextkey are used for traversing the database
201// no insertions or deletions should be carried out while traversing
202// the database. when there are no keys left to visit in the database
203// an empty string is returned.
204text_t gdbmclass::getfirstkey ()
205{
206  if (gdbmfile == NULL) return g_EmptyText;
207
208  // get the first key
209  datum firstkey_data = gdbm_firstkey (gdbmfile);
210  if (firstkey_data.dptr == NULL) return g_EmptyText;
211
212  // convert it to text_t
213  text_t firstkey;
214  firstkey.setcarr (firstkey_data.dptr, firstkey_data.dsize);
215  free (firstkey_data.dptr);
216  return to_uni(firstkey);  // convert to unicode
217}
218
219
220text_t gdbmclass::getnextkey (const text_t &key)
221{
222  if (gdbmfile == NULL || key.empty()) return g_EmptyText;
223
224  // get a utf-8 encoded c string of the unicode key
225  datum key_data;
226  key_data.dptr = (to_utf8(key)).getcstr();
227  if (key_data.dptr == NULL) return g_EmptyText;
228  key_data.dsize = strlen (key_data.dptr);
229 
230  // get the next key
231  datum nextkey_data = gdbm_nextkey (gdbmfile, key_data);
232  if (nextkey_data.dptr == NULL) {
233    delete []key_data.dptr;
234    return g_EmptyText;
235  }
236
237  // convert it to text_t
238  text_t nextkey;
239  nextkey.setcarr (nextkey_data.dptr, nextkey_data.dsize);
240  free (nextkey_data.dptr);
241  delete []key_data.dptr;
242  return to_uni(nextkey);  // convert to unicode
243}
Note: See TracBrowser for help on using the browser.