File Coverage

blib/lib/Paranoid/BerkeleyDB.pm
Criterion Covered Total %
statement 28 30 93.3
branch n/a
condition n/a
subroutine 10 10 100.0
pod n/a
total 38 40 95.0


line stmt bran cond sub pod time code
1             # Paranoid::BerkeleyDB -- BerkeleyDB Wrapper
2             #
3             # (c) 2005 - 2015, Arthur Corliss
4             #
5             # $Id: lib/Paranoid/BerkeleyDB.pm, 2.02 2016/06/21 19:51:06 acorliss Exp $
6             #
7             # This software is licensed under the same terms as Perl, itself.
8             # Please see http://dev.perl.org/licenses/ for more information.
9             #
10             #####################################################################
11              
12             #####################################################################
13             #
14             # Dbironment definitions
15             #
16             #####################################################################
17              
18             package Paranoid::BerkeleyDB;
19              
20 1     1   14953 use strict;
  1         2  
  1         21  
21 1     1   3 use warnings;
  1         2  
  1         18  
22 1     1   3 use vars qw($VERSION);
  1         1  
  1         29  
23 1     1   3 use Fcntl qw(:DEFAULT :flock :mode :seek);
  1         1  
  1         383  
24 1     1   4 use Paranoid;
  1         1  
  1         31  
25 1     1   3 use Paranoid::Debug qw(:all);
  1         1  
  1         100  
26 1     1   412 use Paranoid::IO;
  1         9305  
  1         70  
27 1     1   389 use Paranoid::IO::Lockfile;
  1         1111  
  1         51  
28 1     1   568 use Class::EHierarchy qw(:all);
  1         5017  
  1         118  
29 1     1   790 use BerkeleyDB;
  0            
  0            
30             use Paranoid::BerkeleyDB::Env;
31             use Paranoid::BerkeleyDB::Db;
32             use Carp;
33              
34             ($VERSION) = ( q$Revision: 2.02 $ =~ /(\d+(?:\.\d+)+)/sm );
35              
36             use vars qw(@ISA @_properties @_methods);
37              
38             @ISA = qw(Class::EHierarchy);
39              
40             @_properties = (
41             [ CEH_RESTR | CEH_SCALAR, 'filename' ],
42             [ CEH_RESTR | CEH_SCALAR, 'pid' ],
43             [ CEH_RESTR | CEH_REF, 'cursor' ],
44             [ CEH_PRIV | CEH_REF, 'dbh' ],
45             );
46             @_methods = ( [ CEH_PUB, 'dbh' ], );
47              
48             our $db46 = 0;
49              
50             #####################################################################
51             #
52             # module code follows
53             #
54             #####################################################################
55              
56             sub _initialize {
57              
58             # Purpose: Create the database object and env object (if needed)
59             # Returns: Boolean
60             # Usage: $rv = $obj->_initialize(%params);
61              
62             my $obj = shift;
63             my %params = @_;
64             my $rv = 0;
65             my ( $db, $env, $fn );
66              
67             # Make sure minimal parameters are preset
68             pdebug( 'entering w/%s', PDLEVEL1, %params );
69             pIn();
70              
71             # Set db46 flag
72             $db46 = 1
73             if DB_VERSION_MAJOR > 4
74             or ( DB_VERSION_MAJOR == 4 and DB_VERSION_MINOR >= 6 );
75              
76             # Set up the environment
77             if ( exists $params{Home} ) {
78             $env = new Paranoid::BerkeleyDB::Env '-Home' => $params{Home};
79             } elsif ( exists $params{Env}
80             and defined $params{Env}
81             and ref $params{Env} eq 'HASH' ) {
82             $env = new Paranoid::BerkeleyDB::Env %{ $params{Env} };
83             } elsif ( exists $params{Env}
84             and defined $params{Env}
85             and $params{Env}->isa('Paranoid::BerkeleyDB::Env') ) {
86             $env = $params{Env};
87             }
88              
89             Paranoid::ERROR =
90             pdebug( 'failed to acquire a bdb environment', PDLEVEL1 )
91             unless defined $env;
92              
93             # Set up the database
94             if ( defined $env ) {
95             if ( exists $params{Filename} ) {
96             $fn = $params{Filename};
97             $db = new Paranoid::BerkeleyDB::Db
98             '-Filename' => $params{Filename},
99             '-Env' => $env;
100             } elsif ( exists $params{Db}
101             and defined $params{Db}
102             and ref $params{Db} eq 'HASH' ) {
103             $fn = $params{Db}{'-Filename'};
104             $params{Db}{'-Env'} = $env;
105             $db = new Paranoid::BerkeleyDB::Db %{ $params{Db} };
106             }
107              
108             if ( defined $db ) {
109             $obj->adopt($env);
110             $obj->property( 'pid', $$ );
111             $obj->property( 'filename', $fn );
112             $obj->property( 'dbh', $db->db );
113             $rv = 1;
114             } else {
115             Paranoid::ERROR =
116             pdebug( 'failed to open the database', PDLEVEL1 );
117             }
118             }
119              
120             pOut();
121             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
122              
123             return $rv;
124             }
125              
126             sub _deconstruct {
127              
128             # Purpose: Object cleanup
129             # Returns: Boolean
130             # Usage: $rv = $obj->deconstruct;
131              
132             my $obj = shift;
133              
134             pdebug( 'entering', PDLEVEL1 );
135             pIn();
136              
137             $obj->property( 'cursor', undef );
138             $obj->property( 'dbh', undef );
139              
140             pOut();
141             pdebug( 'leaving w/rv: 1', PDLEVEL1 );
142              
143             return 1;
144             }
145              
146             sub dbh {
147              
148             # Purpose: Performs PID check before returning dbh
149             # Returns: Db ref
150             # Usage: $dbh = $obj->dbh;
151              
152             my $obj = shift;
153             my $pid = $obj->property('pid');
154             my $fn = $obj->property('filename');
155             my ( $rv, @children );
156              
157             pdebug( 'entering', PDLEVEL3 );
158             pIn();
159              
160             if ( $$ == $pid ) {
161              
162             # Same process
163             $rv = $obj->property('dbh');
164              
165             } else {
166              
167             # :-) Nothing to see here, can't seem to get it to
168             # work like the old days...
169             croak 'attempted to access an open database in a forked process';
170              
171             # Purge current references
172             $obj->property( 'cursor', undef );
173             $obj->property( 'dbh', undef );
174              
175             # Get a list of children and find the same database
176             @children = ( $obj->children )[0]->children;
177             foreach (@children) {
178             if ( $fn = $_->property('filename') ) {
179             $obj->property( 'pid', $$ );
180             $obj->property( 'dbh', $_->db );
181             $rv = $_->db;
182             last;
183             }
184             }
185             }
186              
187             pOut();
188             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
189              
190             return $rv;
191             }
192              
193             sub cds_lock {
194              
195             # Purpose: Simple wrapper to get a CDS lock
196             # Returns: CDS Lock
197             # Usage: $lock = $dbh->cds_lock;
198              
199             my $obj = shift;
200             my $dbh = $obj->dbh;
201              
202             return $dbh->cds_lock;
203             }
204              
205             sub TIEHASH {
206             my @args = @_;
207              
208             shift @args;
209              
210             return new Paranoid::BerkeleyDB @args;
211             }
212              
213             sub FETCH {
214             my $obj = shift;
215             my $key = shift;
216             my $dbh = $obj->dbh;
217             my ( $val, $rv );
218              
219             pdebug( 'entering w/(%s)', PDLEVEL3, $key );
220             pIn();
221              
222             if ( !$dbh->db_get( $key, $val ) ) {
223             $rv = $val;
224             }
225              
226             pOut();
227             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
228              
229             return $rv;
230             }
231              
232             sub STORE {
233             my $obj = shift;
234             my $key = shift;
235             my $val = shift;
236             my $dbh = $obj->dbh;
237             my $rv;
238              
239             pdebug( 'entering w/(%s)(%s)', PDLEVEL3, $key, $val );
240             pIn();
241              
242             $rv = !$dbh->db_put( $key, $val );
243              
244             pOut();
245             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
246              
247             return $rv;
248             }
249              
250             sub EXISTS {
251             my $obj = shift;
252             my $key = shift;
253             my $dbh = $obj->dbh;
254             my ( $val, $rv );
255              
256             pdebug( 'entering w/(%s)', PDLEVEL3, $key );
257             pIn();
258              
259             $rv =
260             $db46
261             ? $dbh->db_exists($key) != DB_NOTFOUND
262             : $dbh->db_get( $key, $val ) == 0;
263              
264             pOut();
265             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
266              
267             return $rv;
268             }
269              
270             sub DELETE {
271             my $obj = shift;
272             my $key = shift;
273             my $dbh = $obj->dbh;
274             my $rv;
275              
276             pdebug( 'entering w/(%s)', PDLEVEL3, $key );
277             pIn();
278              
279             $rv = !$dbh->db_del($key);
280              
281             pOut();
282             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
283              
284             return $rv;
285             }
286              
287             sub CLEAR {
288             my $obj = shift;
289             my $dbh = $obj->dbh;
290             my $rv = 0;
291             my $lock;
292              
293             pdebug( 'entering', PDLEVEL3 );
294             pIn();
295              
296             $lock = $dbh->cds_lock if $dbh->cds_enabled;
297             $dbh->truncate($rv);
298             $lock->cds_unlock if defined $lock;
299              
300             pOut();
301             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
302              
303             return $rv;
304             }
305              
306             sub FIRSTKEY {
307             my $obj = shift;
308             my $dbh = $obj->dbh;
309             my ( $key, $val ) = ( '', '' );
310             my ( $cursor, %o );
311              
312             pdebug( 'entering', PDLEVEL3 );
313             pIn();
314              
315             $cursor = $dbh->db_cursor;
316              
317             if ( defined $cursor and $cursor->c_get( $key, $val, DB_NEXT ) == 0 ) {
318             %o = ( $key => $val );
319             $obj->property( 'cursor', $cursor );
320             }
321              
322             pOut();
323             pdebug( 'leaving w/rv: %s', PDLEVEL3, %o );
324              
325             return each %o;
326             }
327              
328             sub NEXTKEY {
329             my $obj = shift;
330             my $cursor = $obj->property('cursor');
331             my ( $key, $val ) = ( '', '' );
332             my (%o);
333              
334             pdebug( 'entering', PDLEVEL3 );
335             pIn();
336              
337             if ( defined $cursor ) {
338             if ( $cursor->c_get( $key, $val, DB_NEXT ) == 0 ) {
339             %o = ( $key => $val );
340             } else {
341             $obj->property( 'cursor', undef );
342             }
343             }
344              
345             pOut();
346             pdebug( 'leaving w/rv: %s', PDLEVEL3, %o );
347              
348             return each %o;
349             }
350              
351             sub SCALAR {
352             my $obj = shift;
353             my ( $key, $rv );
354              
355             pdebug( 'entering', PDLEVEL3 );
356             pIn();
357              
358             if ( defined( $key = $obj->FIRSTKEY ) ) {
359             $rv = 1;
360             $obj->property( 'cursor', undef );
361             } else {
362             $rv = 0;
363             }
364              
365             pOut();
366             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
367              
368             return $rv;
369             }
370              
371             sub UNTIE {
372             my $obj = shift;
373             my $rv = 1;
374              
375             pdebug( 'entering', PDLEVEL3 );
376             pIn();
377              
378             $obj->property( 'cursor', undef );
379             $obj->property( 'dbh', undef );
380              
381             pOut();
382             pdebug( 'leaving w/rv: %s', PDLEVEL3, $rv );
383              
384             return $rv;
385             }
386              
387             1;
388              
389             __END__