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

Last change on this file since 31230 was 31230, checked in by ak19, 7 years ago

Commit for GS3 server side part of OAI deletion police implementation. Still to implement the GS2 server side part. The earlier commits implemented the PERL side, the oai-inf db implementation. I think I've now got the GS3 server side working, but have yet to try validating against the OAI validator. (I need to test that on a machine that is publicly accessible).

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