source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java@ 30264

Last change on this file since 30264 was 30264, checked in by jmt12, 9 years ago

Added static block to ensure database wrapper registers its name and extension with the DBHelper.

  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
1/*
2 * GDBMWrapper.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import au.com.pharos.gdbm.GdbmFile;
22import au.com.pharos.packing.*;
23import au.com.pharos.gdbm.GdbmException;
24
25import org.apache.log4j.Logger;
26
27import java.io.UnsupportedEncodingException;
28import java.io.File;
29
30/**
31 * java wrapper class for gdbm - uses Java-GDBM written by Martin Pool replaces
32 * gdbmclass in the old version
33 */
34
35public class GDBMWrapper implements FlatDatabaseWrapper
36{
37
38 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
39
40 static
41 {
42 /** Register this Wrapper with the DBHelper */
43 DBHelper.registerDBTypeExt("gdbm",".gdb");
44 }
45
46 /*
47 * GdbmFile modes: READER - read access, many readers may share the database
48 * WRITER - read/write access, exclusive access WRCREAT - read/write access,
49 * create db if doesn't exist NEWDB - read/write access, db should be
50 * replaced if exists
51 */
52
53 protected GdbmFile db_ = null;
54
55 /**
56 * open the database filename, with mode mode - uses the constants above, eg
57 * GdbmFile.WRITER
58 */
59 public boolean openDatabase(String filename, int mode)
60 {
61 // need to convert mode to GdbmFile mode
62 if (mode == READ)
63 {
64 mode = GdbmFile.READER;
65 }
66 else if (mode == WRITE)
67 {
68 mode = GdbmFile.WRITER;
69 }
70 else
71 {
72 logger.error("invalid mode, " + mode + ", opening db for reading only");
73 mode = GdbmFile.READER;
74 }
75 try
76 {
77 if (db_ != null)
78 {
79 db_.close();
80 }
81
82 // The java version of the C++ code in common-src/src/lib/gdbmclass.cpp
83 if (mode == GdbmFile.READER)
84 {
85 // Looking to read in the database
86 // we now use gdb extension. Check for ldb/bdb in case of legacy collection
87 // if not (first time) then generate using txt2db
88 if (!new File(filename).exists())
89 {
90 logger.warn("Database file " + filename + " does not exist. Looking for ldb/bdb version");
91 int extension = filename.lastIndexOf('.');
92 String filename_head = filename.substring(0, extension);
93 filename = filename_head + ".ldb";
94 if (!new File(filename).exists())
95 {
96 filename = filename_head + ".bdb";
97
98 if (!new File(filename).exists())
99 {
100 logger.warn("ldb/bdb version of database file " + filename + " does not exist. Looking for txtgz version of db file.");
101 // put the filename back to gdb
102 filename = filename_head + ".gdb";
103 // need to generate architecture native GDBM file using txt2db
104
105 // replace sought after gdbm filename ext with ".txt.gz"
106
107 String txtgzFilename = filename_head + ".txt.gz";
108 if (new File(txtgzFilename).exists())
109 {
110 // Test to make sure Perl is on the path
111 // On Linux, the output of the test goes to STDOUT so redirect it to STDERR
112 String cmdTest = "perl -v 2>&1";
113 //String cmdTest = "echo %PATH%";
114 int returnValue = Processing.runProcess(cmdTest);
115 if (returnValue != 0)
116 {
117 logger.error("Tried to find Perl. Return exit value of running " + cmdTest + ": " + returnValue + ", (expected this to be 0)");
118 logger.error("Check that Perl is set in your PATH environment variable.");
119 //log.error("At present, PATH=" + System.getenv("PATH"));
120 }
121
122 String cmd = "perl -S txtgz-to-gdbm.pl \"" + txtgzFilename + "\" \"" + filename + "\"";
123 returnValue = Processing.runProcess(cmd);
124 // For some reason, launching this command with gsdl_system() still returns 1
125 // even when it returns 0 when run from the command-line. We can check whether
126 // we succeeded by looking at whether the output database file was created.
127 if (returnValue != 0)
128 {
129 logger.warn("Warning, non-zero return value on running command \"" + cmd + "\": " + returnValue);
130 if (!new File(filename).exists())
131 {
132 logger.error("Tried to run command \"" + cmd + "\", but it failed");
133 }
134 }
135 }
136 }
137 }
138
139 }
140 }
141
142 db_ = new GdbmFile(filename, mode);
143 }
144 catch (GdbmException e)
145 { // the database wasn't opened or created
146 logger.error("couldn't open database " + filename);
147 return false;
148 }
149 db_.setKeyPacking(new StringPacking());
150 db_.setValuePacking(new StringPacking());
151 return true;
152 }
153
154 /** close the database associated with this wrapper */
155 public void closeDatabase()
156 {
157 try
158 {
159 if (db_ != null)
160 {
161 db_.close();
162 db_ = null;
163 if (System.getProperty("os.name").startsWith("Windows"))
164 {
165 //Hack: force Windows to let go of the gdb file
166 System.gc();
167 }
168 }
169 }
170 catch (GdbmException e)
171 {
172 // should never get here - close never actually throws an exception
173 logger.error("error on close()");
174 }
175 }
176
177 public String getValue(String key)
178 {
179 if (db_ == null)
180 {
181 return null;
182 }
183 String s_info = null;
184 try
185 {
186 try
187 {
188 // The key is UTF8: do db lookup using the UTF8 version of key
189 if (db_.exists(key.getBytes("UTF-8")))
190 {
191 s_info = (String) db_.fetch(key.getBytes("UTF-8"));
192 }
193 }
194 catch (UnsupportedEncodingException e)
195 {
196 logger.warn("utf8 key for " + key + " unrecognised. Retrying with default encoding.");
197 // retry db lookup using default encoding of key instead of UTF8
198 s_info = (String) db_.fetch(key);
199 }
200 }
201 catch (GdbmException e)
202 {
203 logger.error("couldn't get record");
204 return null;
205 }
206 if (s_info == null)
207 {
208 // record not present
209 logger.error("key " + key + " not present in db");
210 return null;
211 }
212 return s_info;
213 }
214
215 /**
216 * sets the given key to the given value in the database
217 */
218 public boolean setValue(String key, String value)
219 {
220 if (db_ == null || !db_.isWritable())
221 {
222 logger.error("GDBM database is either null or not writable");
223 return false;
224 }
225
226 try
227 {
228 db_.store(key, value);
229 }
230 catch (GdbmException ex)
231 {
232 logger.error("Error storing " + key + " = " + value + " in GDBM database");
233 logger.error("Error message is: " + ex.getMessage());
234 return false;
235 }
236 return true;
237 }
238
239 /**
240 * deletes the entry for given key
241 */
242 public boolean deleteKey(String key)
243 {
244 if (db_ == null)
245 {
246 logger.error("GDBM database is null");
247 return false;
248 }
249
250 try
251 {
252 db_.delete(key);
253 }
254 catch (GdbmException ex)
255 {
256 logger.error("Error deleting key " + key + " from the database");
257 logger.error("Error message is: " + ex.getMessage());
258 return false;
259 }
260
261 return true;
262 }
263
264 /**
265 * returns a string of key-value entries that can be printed for debugging
266 * purposes.
267 */
268 public String displayAllEntries()
269 {
270 StringBuffer output = new StringBuffer();
271 try
272 {
273 java.util.Enumeration e = db_.keys();
274 while (e.hasMoreElements())
275 {
276 Object key = e.nextElement();
277 Object value = db_.fetch(key);
278
279 output.append("key href: ");
280 output.append((String) key);
281 output.append("\tvalue ID: ");
282 output.append((String) value);
283 output.append("\n");
284 //logger.warn("key: " + key + "\tvalue: " + value);
285
286 String urlkey = java.net.URLEncoder.encode((String) key, "UTF8");
287 output.append("URL encoded key: " + urlkey);
288 //logger.warn("URL encoded key: " + urlkey);
289 }
290 }
291 catch (UnsupportedEncodingException e)
292 {
293 logger.warn("Trouble converting key to UTF-8.");
294 }
295 catch (Exception e)
296 {
297 logger.warn("Exception encountered when trying to displayAllEntries():" + e);
298 }
299 return output.toString();
300 }
301}
Note: See TracBrowser for help on using the repository browser.