source: main/trunk/greenstone2/perllib/dbutil/gdbm.pm@ 23758

Last change on this file since 23758 was 23758, checked in by davidb, 13 years ago

Changed to using 'txt2db' to set a single entry so it is not effected by length of data that needs to be pushed through the command line of 'gdbmset' or is effected by the issue of quotes in the data that need to be escaped

File size: 6.2 KB
Line 
1###########################################################################
2#
3# dbutil::gdbm -- utility functions for writing to gdbm databases
4#
5# A component of the Greenstone digital library software
6# from the New Zealand Digital Library Project at the
7# University of Waikato, New Zealand.
8#
9# Copyright (C) 2009
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::gdbm;
28
29use strict;
30
31use dbutil::gdbmtxtgz;
32
33# -----------------------------------------------------------------------------
34# GDBM IMPLEMENTATION
35# -----------------------------------------------------------------------------
36
37sub open_infodb_write_handle
38{
39 my $infodb_file_path = shift(@_);
40 my $opt_append = shift(@_);
41
42 my $txt2db_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",$ENV{'GSDLOS'}, "txt2db" . &util::get_os_exe());
43 my $infodb_file_handle = undef;
44 my $cmd = "\"$txt2db_exe\"";
45 if ((defined $opt_append) && ($opt_append eq "append")) {
46 $cmd .= " -append";
47 }
48 $cmd .= " \"$infodb_file_path\"";
49
50 if (!-e "$txt2db_exe")
51 {
52 print STDERR "Error: Unable to find $txt2db_exe\n";
53 return undef;
54 }
55
56 if(!open($infodb_file_handle, "| $cmd"))
57 {
58
59 print STDERR "Error: Failed to open pipe to $cmd\n";
60 print STDERR " $!\n";
61 return undef;
62 }
63
64 binmode($infodb_file_handle,":utf8");
65
66 return $infodb_file_handle;
67}
68
69
70
71sub close_infodb_write_handle
72{
73 my $infodb_handle = shift(@_);
74
75 close($infodb_handle);
76}
77
78
79sub get_infodb_file_path
80{
81 my $collection_name = shift(@_);
82 my $infodb_directory_path = shift(@_);
83
84 my $infodb_file_extension = ".gdb";
85 my $infodb_file_name = &util::get_dirsep_tail($collection_name) . $infodb_file_extension;
86 return &util::filename_cat($infodb_directory_path, $infodb_file_name);
87}
88
89
90sub read_infodb_file
91{
92 my $infodb_file_path = shift(@_);
93 my $infodb_map = shift(@_);
94
95 open (PIPEIN, "db2txt \"$infodb_file_path\" |")
96 || die "couldn't open pipe from db2txt \$infodb_file_path\"\n";
97
98 binmode(PIPEIN,":utf8");
99
100 my $infodb_line = "";
101 my $infodb_key = "";
102 my $infodb_value = "";
103 while (defined ($infodb_line = <PIPEIN>))
104 {
105 if ($infodb_line =~ /^\[([^\]]+)\]$/)
106 {
107 $infodb_key = $1;
108 }
109 elsif ($infodb_line =~ /^-{70}$/)
110 {
111 $infodb_map->{$infodb_key} = $infodb_value;
112 $infodb_key = "";
113 $infodb_value = "";
114 }
115 else
116 {
117 $infodb_value .= $infodb_line;
118 }
119 }
120
121 close (PIPEIN);
122}
123
124sub read_infodb_keys
125{
126 my $infodb_file_path = shift(@_);
127 my $infodb_map = shift(@_);
128
129 open (PIPEIN, "gdbmkeys \"$infodb_file_path\" |")
130 || die "couldn't open pipe from gdbmkeys \$infodb_file_path\"\n";
131
132 binmode(PIPEIN,":utf8");
133
134 my $infodb_line = "";
135 my $infodb_key = "";
136 my $infodb_value = "";
137 while (defined ($infodb_line = <PIPEIN>))
138 {
139 chomp $infodb_line; # remove end of line
140
141 $infodb_map->{$infodb_line} = 1;
142 }
143
144 close (PIPEIN);
145}
146
147sub write_infodb_entry
148{
149 # With infodb_handle already set up, works the same as _gdbm_txtgz version
150 &dbutil::gdbmtxtgz::write_infodb_entry(@_);
151}
152
153sub write_infodb_rawentry
154{
155 # With infodb_handle already set up, works the same as _gdbm_txtgz version
156 &dbutil::gdbmtxtgz::write_infodb_rawentry(@_);
157}
158
159
160sub set_infodb_entry_OLD
161{
162 my $infodb_file_path = shift(@_);
163 my $infodb_key = shift(@_);
164 my $infodb_map = shift(@_);
165
166 # Protect metadata values that go inside quotes for gdbmset
167 foreach my $k (keys %$infodb_map) {
168 my @escaped_v = ();
169 foreach my $v (@{$infodb_map->{$k}}) {
170 if ($k eq "contains") {
171 # protect quotes in ".2;".3 etc
172 $v =~ s/\"/\\\"/g;
173 push(@escaped_v, $v);
174 }
175 else {
176 my $ev = &ghtml::unescape_html($v);
177 $ev =~ s/\"/\\\"/g;
178 push(@escaped_v, $ev);
179 }
180 }
181 $infodb_map->{$k} = \@escaped_v;
182 }
183
184 # Generate the record string
185 my $serialized_infodb_map = &dbutil::convert_infodb_hash_to_string($infodb_map);
186## print STDERR "**** ser dr\n$serialized_infodb_map\n\n\n";
187
188 # Store it into GDBM
189 my $cmd = "gdbmset \"$infodb_file_path\" \"$infodb_key\" \"$serialized_infodb_map\"";
190 my $status = system($cmd);
191
192 return $status;
193
194}
195
196
197
198sub set_infodb_entry
199{
200 my $infodb_file_path = shift(@_);
201 my $infodb_key = shift(@_);
202 my $infodb_map = shift(@_);
203
204 # HTML escape anything that is not part of the "contains" metadata value
205 foreach my $k (keys %$infodb_map) {
206 my @escaped_v = ();
207 foreach my $v (@{$infodb_map->{$k}}) {
208 if ($k eq "contains") {
209 push(@escaped_v, $v);
210 }
211 else {
212 my $ev = &ghtml::unescape_html($v);
213 push(@escaped_v, $ev);
214 }
215 }
216 $infodb_map->{$k} = \@escaped_v;
217 }
218
219 # Generate the record string
220 my $serialized_infodb_map = &dbutil::convert_infodb_hash_to_string($infodb_map);
221### print STDERR "**** ser dr\n$serialized_infodb_map\n\n\n";
222
223 # Store it into GDBM using 'txt2db -append' which despite its name
224 # actually replaces the record if it already exists
225
226 my $cmd = "txt2db -append \"$infodb_file_path\"";
227
228 my $status = undef;
229 if(!open(GOUT, "| $cmd"))
230 {
231 print STDERR "Error: gdbm::set_infodb_entry() failed to open pipe to: $cmd\n";
232 print STDERR " $!\n";
233 $status = -1;
234 }
235 else {
236 binmode(GOUT,":utf8");
237
238 print GOUT "[$infodb_key]\n";
239 print GOUT "$serialized_infodb_map\n";
240
241 close(GOUT);
242 $status = 0; # as in exit status of cmd OK
243 }
244
245 return $status;
246}
247
248
249sub delete_infodb_entry
250{
251 # With infodb_handle already set up, works the same as _gdbm_txtgz version
252 &dbutil::gdbmtxtgz::delete_infodb_entry(@_);
253}
254
255
256
2571;
Note: See TracBrowser for help on using the repository browser.