source: gs2-extensions/tdb-edit/trunk/src/perllib/dbutil.pm@ 28000

Last change on this file since 28000 was 28000, checked in by jmt12, 11 years ago

Functions for determining if the plugout supports writing Datestamp and RSS information internally (or if Greenstone should handle writing them itself)

File size: 11.1 KB
RevLine 
[24068]1###########################################################################
2#
3# dbutil.pm -- gateway to utilities for reading/writing to different databases
4#
[27400]5# Copyright (C) 2008 DL Consulting Ltd
[24068]6#
7# A component of the Greenstone digital library software
8# from the New Zealand Digital Library Project at the
9# University of Waikato, New Zealand.
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24#
25###########################################################################
26
27package dbutil;
28
29use strict;
30
31use Symbol qw<qualify>;
32use util;
33
34# /** Dynamic class loading - for use in DBUtils to load various database
35# * drivers, configured in the collect.cfg, at runtime.
36# * @param $class - The class name (including any path) to load
37# * @param rest - any function aliases you want exported
38# */
39sub load_db_driver
40{
41 my $class = shift(@_);
42 (my $file = "$class.pm") =~ s|::|/|g;
43 # - ensure we haven't already loaded this class
44 unless( $INC{$file} )
45 {
46 # - require is fine being assigned at runtime - no need for evil eval
[27400]47 #eval
48 #{
49 require $file;
50 #};
[24068]51 }
52 # - this is the magic that actually instantiates the class (rubberstamp?)
53 # - we pass @_ to action any function aliases exports requested
54 eval
55 {
56 $class->import(@_);
57 };
58 # - by now the driver file should have been loaded
59 return (defined $INC{$file});
60}
61# /** load_db_driver() **/
62
63# /** Make a function call to a dynamically loaded database driver.
64# * @param $function_name
65# * @param $driver_name
66# * @param <rest> The parameters to be passed to the function called
67# */
68sub call_dynamic_driver_function
69{
70 my $function_name = shift(@_);
71 my $driver_name = shift(@_);
72 my $package_name = 'dbutil::' . $driver_name;
73 # - try to load the requested infodb type
74 if (!&load_db_driver($package_name))
75 {
76 # - try loading the default GDBM driver
77 print STDERR 'Warning! Using default database driver (GDBM) as failed to load configured database driver: ' . $driver_name . "\n";
78 $package_name = 'dbutil::gdbm';
79 if (!&load_db_driver($package_name))
80 {
81 die("Fatal Error! Failed to load default database driver: dbutil::gdbm\n");
82 }
83 }
84 # - make call to the newly created package
85 no strict;
86 # - lets check that the function we are about to call
87 my $symbol = qualify($function_name, $package_name);
88 unless ( defined &{$symbol} )
89 {
90 die ('Error! Function not found: ' . $package_name . '::' . $function_name . "()\n");
91 }
92 return &{$symbol}(@_);
93}
94# /** call_dynamic_driver_function() **/
95
96
[28000]97## @function test_dynamic_driver_function()
98#
99# Checks to see if a function in a dynamically loaded driver exists
100#
101sub test_dynamic_driver_function
102{
103 my $function_name = shift(@_);
104 my $driver_name = shift(@_);
105 my $package_name = 'dbutil::' . $driver_name;
106 # - try to load the requested infodb type
107 if (!&load_db_driver($package_name))
108 {
109 # - try loading the default GDBM driver
110 print STDERR 'Warning! Using default database driver (GDBM) as failed to load configured database driver: ' . $driver_name . "\n";
111 $package_name = 'dbutil::gdbm';
112 if (!&load_db_driver($package_name))
113 {
114 die("Fatal Error! Failed to load default database driver: dbutil::gdbm\n");
115 }
116 }
117 # - make call to the newly created package
118 no strict;
119 # - lets check that the function we are about to call
120 my $symbol = qualify($function_name, $package_name);
121 return defined &{$symbol};
122}
123## test_dynamic_driver_function() ##
124
125
126## @function
127#
[24068]128sub open_infodb_write_handle
129{
130 my $infodb_type = shift(@_);
131 my $infodb_file_path = shift(@_);
132 # Make a call to the dynamically loaded driver to open the connection.
133 return &dbutil::call_dynamic_driver_function('open_infodb_write_handle', $infodb_type, $infodb_file_path, @_);
134}
135
136
137sub close_infodb_write_handle
138{
139 my $infodb_type = shift(@_);
140 my $infodb_handle = shift(@_);
141 # Dynamic database driver call
142 return &dbutil::call_dynamic_driver_function('close_infodb_write_handle', $infodb_type, $infodb_handle, @_);
143}
144
145
146sub get_default_infodb_type
147{
148 # The default is GDBM so everything works the same for existing collections
149 # To use something else, specify the "infodbtype" in the collection's collect.cfg file
150 return "gdbm";
151}
152
[27400]153# /** @function get_infodb_file_path()
154# * Warning! Black magic follows. The first time get_infodb_file_path is
155# * called (presumably from inexport::process_files()) for databases of type
156# * server will actually the Server to be run complete with an initial dummy
157# * listener. This is done so that, in parallel importing, the server will
158# * persist until the top level import.pl (which will be the first that calls
159# * this function) completes and removes the dummy listener. [jmt12]
[24068]160sub get_infodb_file_path
161{
162 my $infodb_type = shift(@_);
163 my $collection_name = shift(@_);
164 my $infodb_directory_path = shift(@_);
165
166 #=======================================MSSQL SUPPORT==============================================#
167 # Updated by Jeffrey (2008/08/25 Monday)
168 # After look into the run-time code, it seems we should still create a database file.
169 # Since the run-time code is always try to read a database file, the easiest way here is not
170 # to change the whole structure, but to give whatever the system is looking for.
171 #==================================================================================================#
172 # Added by Jeffrey (2008/08/15 Friday)
173 # No file path required for MS SQL, it is a server-client connection.
174 # At the moment the information is hard coded in dbutil::mssql::open_infodb_write_handle
175 # the this might need some tidy up sometime.
176 #==================================================================================================#
177
178 return &dbutil::call_dynamic_driver_function('get_infodb_file_path', $infodb_type, $collection_name, $infodb_directory_path, @_);
179}
180
181# This function, conceptually, would be better structured if it didn't
182# use return statements, as the database methods it calls do not
183# themselves return anything.
184# Note: if doing this, then the GDBM lines of code should be moved into
185# an 'else' clause
186sub read_infodb_file
187{
188 my $infodb_type = shift(@_);
189 my $infodb_file_path = shift(@_);
190 my $infodb_map = shift(@_);
191
192 return &dbutil::call_dynamic_driver_function('read_infodb_file', $infodb_type, $infodb_file_path, $infodb_map, @_);
193}
194
195sub read_infodb_keys
196{
197 my $infodb_type = shift(@_);
198 my $infodb_file_path = shift(@_);
199 my $infodb_map = shift(@_);
200
201 return &dbutil::call_dynamic_driver_function('read_infodb_keys', $infodb_type, $infodb_file_path, $infodb_map, @_);
202}
203
[28000]204
205## @function supportDatestamp
206#
207sub supportsDatestamp
208{
209 my $infodb_type = shift(@_);
210 return &dbutil::test_dynamic_driver_function('supportsDatestamp', $infodb_type);
211}
212## supportsDatestamp() ##
213
214
215## @function supportRSS
216#
217sub supportsRSS
218{
219 my $infodb_type = shift(@_);
220 return &dbutil::test_dynamic_driver_function('supportsRSS', $infodb_type);
221}
222## supportsRSS() ##
223
224
[24068]225sub write_infodb_entry
226{
227 my $infodb_type = shift(@_);
228 my $infodb_handle = shift(@_);
229 my $infodb_key = shift(@_);
230 my $infodb_map = shift(@_);
231
232 return &dbutil::call_dynamic_driver_function('write_infodb_entry', $infodb_type, $infodb_handle, $infodb_key, $infodb_map, @_);
233}
234
235
236sub write_infodb_rawentry
237{
238 my $infodb_type = shift(@_);
239 my $infodb_handle = shift(@_);
240 my $infodb_key = shift(@_);
241 my $infodb_val = shift(@_);
242
243 return &dbutil::call_dynamic_driver_function('write_infodb_rawentry', $infodb_type, $infodb_handle, $infodb_key, $infodb_val, @_);
244}
245
246
247sub set_infodb_entry
248{
249 my $infodb_type = shift(@_);
250 my $infodb_file_path = shift(@_);
251 my $infodb_key = shift(@_);
252 my $infodb_map = shift(@_);
253
254 return &dbutil::call_dynamic_driver_function('set_infodb_entry', $infodb_type, $infodb_file_path, $infodb_key, $infodb_map, @_);
255}
256
257
258
259sub delete_infodb_entry
260{
261 my $infodb_type = shift(@_);
262 my $infodb_handle = shift(@_);
263 my $infodb_key = shift(@_);
264
265 return &dbutil::call_dynamic_driver_function('delete_infodb_entry', $infodb_type, $infodb_handle, $infodb_key, @_);
266}
267
268sub read_infodb_rawentry
269{
270 my $infodb_type = shift(@_);
271 my $infodb_file_path = shift(@_);
272 my $infodb_key = shift(@_);
273
274 # !! TEMPORARY: Slow and naive implementation that just reads the entire file and picks out the one value
275 # !! This will one day be replaced with database-specific versions that will use dbget etc.
276 my $infodb_map = {};
277 &read_infodb_file($infodb_type, $infodb_file_path, $infodb_map);
278
279 return $infodb_map->{$infodb_key};
280}
281
282
283sub read_infodb_entry
284{
285 my $infodb_type = shift(@_);
286 my $infodb_file_path = shift(@_);
287 my $infodb_key = shift(@_);
288
289 if ($infodb_type eq "sqlite")
290 {
291 require dbutil::sqlite;
292 return &dbutil::sqlite::read_infodb_entry($infodb_file_path, $infodb_key, @_);
293 }
294# elsif ($infodb_type eq "gdbm-txtgz")
295# {
296# require dbutil::gdbmtxtgz;
297# return &dbutil::gdbmtxtgz::read_infodb_entry($infodb_file_path, $infodb_key, @_);
298# }
299# elsif ($infodb_type eq "jdbm")
300# {
301# require dbutil::jdbm;
302# return &dbutil::jdbm::read_infodb_entry($infodb_file_path, $infodb_key, @_);
303# }
304# elsif ($infodb_type eq "mssql")
305# {
306# require dbutil::mssql;
307# return &dbutil::mssql::read_infodb_entry($infodb_file_path, $infodb_key, @_);
308# }
309
310# # Use GDBM if the infodb type is empty or not one of the values above
311# require dbutil::gdbm;
312# return &dbutil::gdbm::read_infodb_entry($infodb_file_path, $infodb_key, @_);
313
314
315 # rawentry above is currently naive implementation
316 my $raw_string = read_infodb_rawentry($infodb_type, $infodb_file_path, $infodb_key);
317 my $infodb_rec = &dbutil::convert_infodb_string_to_hash($raw_string);
318
319 return $infodb_rec;
320}
321
322
323# ---- GENERAL FUNCTIONS --------
324
325sub convert_infodb_hash_to_string
326{
327 my $infodb_map = shift(@_);
328
329 my $infodb_entry_value = "";
330 foreach my $infodb_value_key (keys(%$infodb_map))
331 {
332 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
333 {
334 $infodb_entry_value .= "<$infodb_value_key>" . $infodb_value . "\n";
335 }
336 }
337
338 return $infodb_entry_value;
339}
340
341
342sub convert_infodb_string_to_hash
343{
344 my $infodb_entry_value = shift(@_);
345 my $infodb_map = ();
346
347 if (!defined $infodb_entry_value) {
348 print STDERR "Warning: No value to convert into a infodb hashtable\n";
349 }
350 else {
351 while ($infodb_entry_value =~ /^<(.*?)>(.*)$/mg)
352 {
353 my $infodb_value_key = $1;
354 my $infodb_value = $2;
355
356 if (!defined($infodb_map->{$infodb_value_key}))
357 {
358 $infodb_map->{$infodb_value_key} = [ $infodb_value ];
359 }
360 else
361 {
362 push(@{$infodb_map->{$infodb_value_key}}, $infodb_value);
363 }
364 }
365 }
366
367 return $infodb_map;
368}
369
370
3711;
Note: See TracBrowser for help on using the repository browser.