Changeset 30347 for gs2-extensions/tdb/trunk/perllib/DBDrivers/TDB.pm
- Timestamp:
- 2015-12-10T12:19:20+13:00 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
gs2-extensions/tdb/trunk/perllib/DBDrivers/TDB.pm
r30338 r30347 53 53 my $class = shift(@_); 54 54 55 my $self = DBDrivers::GDBM->new( );55 my $self = DBDrivers::GDBM->new(@_); 56 56 57 57 # Default TDB file extension … … 59 59 # Should the TDB used a specific affinity? 60 60 $self->{'forced_affinity'} = -1; # zero upwards indicates the affinity 61 # Keep track of all opened file handles62 $self->{'handle_pool'} = {};63 61 # Ask TDB executables to display debugging information? 64 $self->{'tdb_debug'} = 0; # 1 to enable 62 $self->{'tdb_debug'} = 1; # 1 to enable 63 64 # note: file separator agnostic 65 $self->{'executable_path'} = $ENV{GEXTTDBEDIT_INSTALLED} . '/bin/'; 66 $self->{'read_executable'} = 'tdb2txt'; 67 $self->{'keyread_executable'} = 'tdbkeys'; 68 $self->{'write_executable'} = 'txt2tdb'; 69 70 # Optional Support 71 $self->{'supports_persistentconnection'} = 1; 72 $self->{'supports_set'} = 1; 65 73 66 74 bless($self, $class); … … 96 104 # ----------------------------------------------------------------------------- 97 105 106 # Handled by BaseDBDriver 107 # sub debugPrint(string) => void 108 # sub debugPrintFunctionHeader(*) => void 109 # sub get_infodb_file_path(string, string) => string 98 110 99 ## @function _get_tdb_executable(string) 100 # 101 sub _get_tdb_executable 102 { 103 my $self = shift(@_); 104 my $program = shift(@_); 105 if (!defined $ENV{GEXTTDBEDIT_INSTALLED} || !-d $ENV{GEXTTDBEDIT_INSTALLED}) 106 { 107 die('Fatal Error! Path to TDB binaries not found. Have you sourced setup.bash?'); 108 } 109 my $program_exe = &util::filename_cat($ENV{GEXTTDBEDIT_INSTALLED} . '/bin/' . $program . &util::get_os_exe()); 110 if (!-x $program_exe) 111 { 112 die('Fatal Error! File doesn\'t exist or isn\'t executable: ' . $program_exe); 113 } 114 return $program_exe; 115 } 116 ## _get_tdb_executable(string) => string ## 117 118 119 # Handled by BaseDBDriver 120 # sub get_infodb_file_path(string, string) 121 122 # With infodb_handle already set up, these functions work the same as parent version 123 # sub delete_infodb_entry {} 124 # sub write_infodb_entry {} 125 # sub write_infodb_rawentry {} 111 # Handled by 70HyphenFormat 112 # sub read_infodb_entry(string, string) => hashmap 113 # sub read_infodb_file(string, hashmap) => void 114 # sub read_infodb_keys(string, hashmap) => void 115 # sub read_infodb_rawentry(string, string) => string 116 # sub set_infodb_entry(string, string, hashmap) => integer 117 # sub write_infodb_entry(filehandle, string, hashmap) => void 118 # sub write_infodb_rawentry(filehandle, string, string) => void 126 119 127 120 … … 144 137 sub close_infodb_write_handle { 145 138 my $self = shift(@_); 139 $self->debugPrintFunctionHeader(@_); 146 140 my $infodb_handle = shift(@_); 147 141 my $actually_close = shift(@_); # Undefined most of the time 148 142 if (defined($actually_close)) { 149 $self->_debugPrint('(<infodb_handle>,"' . $actually_close . '")');150 143 # We'll need the file path so we can locate and remove the entry in the 151 144 # handle pool … … 156 149 # we can search for the appropriate file extension that should be there 157 150 # for valid paths. 158 my $pattern = '\.' . $self->{'default_file_extension'} . ' $';151 my $pattern = '\.' . $self->{'default_file_extension'} . '(\s\[APPEND\])?$'; 159 152 if ($actually_close =~ /$pattern/) { 160 153 $infodb_file_path = $actually_close; … … 173 166 } 174 167 if (defined($infodb_file_path)) { 168 $self->debugPrint('Closing connection: ' . $infodb_file_path); 175 169 delete($self->{'handle_pool'}->{$infodb_file_path}); 176 170 } … … 181 175 $self->SUPER::close_infodb_write_handle($infodb_handle); 182 176 } 177 else { 178 $self->debugPrint('Connection persists for later use.'); 179 } 183 180 } 184 181 ## close_infodb_write_handle(filehandle) => void ## 182 183 # sub delete_infodb_entry {} 185 184 186 185 … … 190 189 { 191 190 my $self = shift(@_); 192 my $infodb_file_path = shift(@_); 193 my $opt_append = shift(@_); 194 195 my $txt2tdb_exe = $self->_get_tdb_executable('txt2tdb'); 196 197 my $cmd = '"' . $txt2tdb_exe . '"'; 198 if ((defined $opt_append) && ($opt_append eq "append")) { 199 $cmd .= ' -append'; 191 if ($self->{'tdb_debug'}) { 192 push(@_, '-debug'); 200 193 } 201 $cmd .= ' "' . $infodb_file_path . '"'; 202 # Optional flags 203 if ($self->{'forced_affinity'} >= 0) { 204 $cmd = 'taskset -c 5 ' . $cmd; 205 } 206 if ($self->{'debug'}) { 207 $cmd .= ' -debug'; 208 } 209 210 # we're going to pipe the key value pairs, in the appropriate format, from 211 # within the buildproc, so we create a piped handle here 212 my $infodb_file_handle = undef; 213 # if the connection is already open, simply return it. 214 if (defined $self->{'handle_pool'}->{$infodb_file_path}) { 215 $infodb_file_handle = $self->{'handle_pool'}->{$infodb_file_path}; 216 } 217 else { 218 $self->_debugPrint('(' . $infodb_file_path . ')'); 219 if(!open($infodb_file_handle, "| $cmd")) { 220 print STDERR "Error: Failed to open pipe to $cmd\n"; 221 print STDERR " $!\n"; 222 return undef; 223 } 224 binmode($infodb_file_handle,":utf8"); 225 # Remember to store the newly created connection in the pool so we can 226 # re-use for subsequent calls. 227 $self->{'handle_pool'}->{$infodb_file_path} = $infodb_file_handle; 228 } 229 return $infodb_file_handle; 194 my $handle = $self->SUPER::open_infodb_write_handle(@_); 195 return $handle; 230 196 } 231 197 ## open_infodb_write_handle(string, string) => filehandle ## 232 198 233 234 ## @function read_infodb_file235 #236 sub read_infodb_file237 {238 my $self = shift(@_);239 my $infodb_file_path = shift(@_);240 my $infodb_map = shift(@_);241 242 $self->_debugPrint('(' . $infodb_file_path . ', <hashmap>)');243 244 my $tdb2txt_exe = $self->_get_tdb_executable('tdb2txt');245 246 if (!open (PIPEIN, '"' . $tdb2txt_exe . '" "' . $infodb_file_path . '" |')) {247 print STDERR 'Error: Failed to open pipe to ' . $tdb2txt_exe . "\n";248 print STDERR " $!\n";249 return undef;250 }251 252 binmode(PIPEIN,":utf8");253 254 my $infodb_line = "";255 my $infodb_key = "";256 my $infodb_value = "";257 while (defined ($infodb_line = <PIPEIN>)) {258 if ($infodb_line =~ /^\[([^\]]+)\]$/) {259 $infodb_key = $1;260 }261 elsif ($infodb_line =~ /^-{70}$/) {262 $infodb_map->{$infodb_key} = $infodb_value;263 $infodb_key = "";264 $infodb_value = "";265 }266 else {267 $infodb_value .= $infodb_line;268 }269 }270 close (PIPEIN);271 }272 ## read_infodb_file(string, hashmap) => void ##273 274 275 ## @function read_infodb_keys(string, hashmap)276 #277 sub read_infodb_keys278 {279 my $self = shift(@_);280 my $infodb_file_path = shift(@_);281 my $infodb_map = shift(@_);282 283 $self->_debugPrint('(' . $infodb_file_path . ', <hashmap>)');284 285 my $tdbkeys_exe = $self->_get_tdb_executable('tdbkeys');286 287 if (!open (PIPEIN, '"' . $tdbkeys_exe . '" "' . $infodb_file_path . '" |')) {288 die("Error! Couldn't open pipe from read_infodb_keys: $infodb_file_path\n$!\n");289 }290 291 binmode(PIPEIN,":utf8");292 293 my $infodb_line = "";294 my $infodb_key = "";295 my $infodb_value = "";296 while (defined ($infodb_line = <PIPEIN>)) {297 # remove end of line298 chomp $infodb_line;299 $infodb_map->{$infodb_line} = 1;300 }301 302 close (PIPEIN);303 }304 ## read_infodb_keys(string, hashmap) => void ##305 306 307 ## @function set_infodb_entry(string, string, hashmap)308 #309 sub set_infodb_entry310 {311 my $self = shift(@_);312 my $infodb_file_path = shift(@_);313 my $infodb_key = shift(@_);314 my $infodb_map = shift(@_);315 316 $self->_debugPrint('(' . $infodb_file_path . ', ' . $infodb_key . ', <hashmap>)');317 318 # Protect metadata values that go inside quotes for tdbset319 foreach my $k (keys %$infodb_map) {320 my @escaped_v = ();321 foreach my $v (@{$infodb_map->{$k}}) {322 if ($k eq "contains") {323 # protect quotes in ".2;".3 etc324 $v =~ s/\"/\\\"/g;325 push(@escaped_v, $v);326 }327 else {328 my $ev = &ghtml::unescape_html($v);329 $ev =~ s/\"/\\\"/g;330 push(@escaped_v, $ev);331 }332 }333 $infodb_map->{$k} = \@escaped_v;334 }335 336 # Generate the record string337 my $serialized_infodb_map = $self->_convert_infodb_hash_to_string($infodb_map);338 339 # Store it into GDBM340 my $tdbset_exe = $self->_get_tdb_executable('tdbset');341 my $cmd = '"' . $tdbset_exe . '" "' . $infodb_file_path . '" "' . $infodb_key . '" "' . $serialized_infodb_map . '"';342 my $status = system($cmd);343 344 return $status;345 }346 ## set_infodb_entry(string, string, hashmap) => integer ##347 348 199 1;
Note:
See TracChangeset
for help on using the changeset viewer.