File Coverage

blib/lib/Paranoid/BerkeleyDB/Env.pm
Criterion Covered Total %
statement 34 36 94.4
branch n/a
condition n/a
subroutine 12 12 100.0
pod n/a
total 46 48 95.8


line stmt bran cond sub pod time code
1             # Paranoid::BerkeleyDB::Env -- BerkeleyDB CDS Env
2             #
3             # (c) 2005 - 2015, Arthur Corliss
4             #
5             # $Id: lib/Paranoid/BerkeleyDB/Env.pm, 2.03 2017/02/06 02:49:24 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             # Environment definitions
15             #
16             #####################################################################
17              
18             package Paranoid::BerkeleyDB::Env;
19              
20 1     1   15076 use strict;
  1         1  
  1         21  
21 1     1   2 use warnings;
  1         1  
  1         20  
22 1     1   2 use vars qw($VERSION);
  1         1  
  1         29  
23 1     1   3 use Fcntl qw(:DEFAULT :flock :mode :seek);
  1         1  
  1         369  
24 1     1   5 use Paranoid;
  1         1  
  1         34  
25 1     1   4 use Paranoid::Debug qw(:all);
  1         1  
  1         102  
26 1     1   370 use Paranoid::Input qw(detaint);
  1         1842  
  1         47  
27 1     1   497 use Paranoid::Filesystem;
  1         24504  
  1         83  
28 1     1   6 use Paranoid::IO;
  1         1  
  1         54  
29 1     1   381 use Paranoid::IO::Lockfile;
  1         807  
  1         49  
30 1     1   513 use Class::EHierarchy qw(:all);
  1         5838  
  1         112  
31 1     1   771 use BerkeleyDB;
  0            
  0            
32             use Cwd qw(realpath);
33             use Carp;
34              
35             ($VERSION) = ( q$Revision: 2.03 $ =~ /(\d+(?:\.\d+)+)/sm );
36              
37             use vars qw(@ISA @_properties);
38              
39             @_properties = ( [ CEH_PRIV | CEH_SCALAR, 'home' ] );
40              
41             @ISA = qw(Class::EHierarchy);
42              
43             #####################################################################
44             #
45             # module code follows
46             #
47             #####################################################################
48              
49             {
50              
51             my %dbe; # Object handles
52             my %dbp; # Parameters used for handles
53             my %dbc; # Reference count
54             my %pid; # Object handle create PID
55              
56             sub _openDbe {
57              
58             # Purpose: Opens a new environment or returns a cached reference
59             # Returns: Reference to BerkeleyDB::Env object
60             # Usage: $env = _openDbe(%params);
61              
62             my $obj = shift;
63             my %params = @_;
64             my ( $env, $home, $rv, $fh );
65              
66             pdebug( 'entering w/%s', PDLEVEL2, %params );
67             pIn();
68              
69             # Validate home
70             $rv = defined $params{'-Home'};
71             if ( $rv and $rv = detaint( $params{'-Home'}, 'filename', $home ) ) {
72              
73             # Create the path
74             if ( pmkdir($home) ) {
75              
76             # Make canonical and save
77             $params{'-Home'} = $home = realpath($home);
78             pdebug( 'canonical home path: %s', PDLEVEL3, $home );
79              
80             } else {
81             carp pdebug(
82             'failed to create/access the requisite directory',
83             PDLEVEL1 );
84             $rv = 0;
85             }
86              
87             } else {
88             carp pdebug( 'invalid home specified: %s',
89             PDLEVEL1, $params{'-Home'} );
90             $rv = 0;
91             }
92              
93             if ($rv) {
94             if ( exists $dbe{$home} ) {
95             pdebug( 'environment already exists', PDLEVEL3 );
96              
97             if ( $pid{$home} == $$ ) {
98             pdebug( 'using cached reference', PDLEVEL3 );
99              
100             # Increment reference count
101             $dbc{$home}++;
102             $env = $dbe{$home};
103              
104             } else {
105              
106             # Expect bad things from here, particularly since
107             # BerkeleyDB will close the shared file handles for
108             # the parent process as well...
109             croak pdebug(
110             'cached ref created under different pid (%s)',
111             PDLEVEL1, $pid{$home} );
112             }
113              
114             } else {
115              
116             pdebug( 'opening a new environment', PDLEVEL3 );
117              
118             # Create an error log
119             $params{'-ErrFile'} = "$home/db_err.log"
120             unless exists $params{'-ErrFile'};
121             $fh =
122             popen( $params{'-ErrFile'},
123             O_WRONLY | O_CREAT | O_APPEND );
124             $params{'-ErrFile'} = $fh if defined $fh;
125              
126             # Add default flags if they're omitted
127             $params{'-Mode'} = 0666 & ~umask;
128             $params{'-Flags'} = DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL
129             unless exists $params{'-Flags'};
130             $params{'-Verbose'} = 1;
131             pdebug( 'final parameters: %s', PDLEVEL4, %params );
132              
133             # Create the environment
134             if ( pexclock( "$home/env.lock", $params{'-Mode'} ) ) {
135             $env = BerkeleyDB::Env->new(%params);
136             punlock("$home/env.lock");
137             }
138              
139             if ( defined $env ) {
140             $dbe{$home} = $env;
141             $dbp{$home} = {%params};
142             $pid{$home} = $$;
143             $dbc{$home} = 1;
144             } else {
145             Paranoid::ERROR =
146             pdebug( 'failed to open environment: %s',
147             PDLEVEL1, $BerkeleyDB::Error );
148             }
149             }
150             }
151              
152             $obj->set( 'home', $home ) if defined $env;
153              
154             pOut();
155             pdebug( 'leaving w/rv: %s', PDLEVEL2, $env );
156              
157             return $env;
158             }
159              
160             sub _closeDbe {
161              
162             # Purpose: Closes env or decrements counter
163             # Returns: Boolean
164             # Usage: $rv = _closeDbe($home);
165              
166             my $home = shift;
167              
168             pdebug( 'entering w/%s', PDLEVEL2, $home );
169             pIn();
170              
171             if ( defined $home and exists $dbe{$home} ) {
172             if ( $dbc{$home} == 1 ) {
173             pdebug( 'closing out environment', PDLEVEL4 );
174             delete $dbe{$home};
175             delete $dbp{$home};
176             delete $dbc{$home};
177             delete $pid{$home};
178             } else {
179             pdebug( 'decrementing ref count', PDLEVEL4 );
180             $dbc{$home}--;
181             }
182             }
183              
184             pOut();
185             pdebug( 'leaving w/rv: 1', PDLEVEL2 );
186              
187             return 1;
188             }
189              
190             sub home {
191              
192             # Purpose: Returns canonical home path
193             # Returns: String
194             # Usage: $home = $obj->home;
195              
196             my $obj = shift;
197             my $rv;
198              
199             pdebug( 'entering', PDLEVEL1 );
200             pIn();
201              
202             if ( !$obj->isStale ) {
203              
204             $rv = $obj->get('home');
205              
206             croak pdebug( 'object opened under a different pid (%s)',
207             PDLEVEL1, $pid{$rv} )
208             if defined $rv and $pid{$rv} != $$;
209              
210             } else {
211             carp pdebug( 'home method called on stale object', PDLEVEL1 );
212             }
213              
214             pOut();
215             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
216              
217             return $rv;
218             }
219              
220             sub params {
221              
222             # Purpose: Returns parameter hash
223             # Returns: Hash
224             # Usage: %params = $obj->params;
225              
226             my $obj = shift;
227             my ( $home, %rv );
228              
229             pdebug( 'entering', PDLEVEL1 );
230             pIn();
231              
232             if ( !$obj->isStale ) {
233             $home = $obj->home;
234             %rv = %{ $dbp{$home} };
235              
236             croak pdebug( 'object opened under a different pid (%s)',
237             PDLEVEL1, $pid{$home} )
238             if $pid{$home} != $$;
239              
240             } else {
241             carp pdebug( 'params method called on stale object', PDLEVEL1 );
242             }
243              
244             pOut();
245             pdebug( 'leaving w/rv: %s', PDLEVEL1, %rv );
246              
247             return %rv;
248             }
249              
250             sub refc {
251              
252             # Purpose: Returns reference count for underlying environment
253             # Returns: Integer
254             # Usage: $count = $obj->refc;
255              
256             my $obj = shift;
257             my ( $home, $rv );
258              
259             pdebug( 'entering', PDLEVEL1 );
260             pIn();
261              
262             if ( !$obj->isStale ) {
263             $home = $obj->home;
264             $rv = $dbc{$home};
265              
266             croak pdebug( 'object opened under a different pid (%s)',
267             PDLEVEL1, $pid{$home} )
268             if $pid{$home} != $$;
269              
270             } else {
271             carp pdebug( 'refc method called on stale object', PDLEVEL1 );
272             }
273              
274             pOut();
275             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
276              
277             return $rv;
278             }
279              
280             sub env {
281              
282             # Purpose: Returns a reference to the env
283             # Returns: Ref
284             # Usage: $env = $obj->env;
285              
286             my $obj = shift;
287             my ( $home, $rv );
288              
289             pdebug( 'entering', PDLEVEL1 );
290             pIn();
291              
292             if ( !$obj->isStale ) {
293             $home = $obj->home;
294             $rv = $dbe{$home};
295              
296             croak pdebug( 'object opened under a different pid (%s)',
297             PDLEVEL1, $pid{$home} )
298             if $pid{$home} != $$;
299             } else {
300             pdebug( 'env method called on a stale object', PDLEVEL1 );
301             }
302              
303             pOut();
304             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
305              
306             return $rv;
307             }
308             }
309              
310             sub _initialize {
311             my $obj = shift;
312             my %params = @_;
313             my $rv;
314              
315             # Make sure minimal parameters are preset
316             pdebug( 'entering', PDLEVEL1 );
317             pIn();
318              
319             if ( exists $params{'-Home'} ) {
320             $rv = 1 if defined _openDbe( $obj, %params );
321             } else {
322             Paranoid::ERROR = pdebug( 'caller didn\'t specify -Home', PDLEVEL1 );
323             }
324              
325             pOut();
326             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
327              
328             return $rv;
329             }
330              
331             sub _deconstruct {
332             my $obj = shift;
333             my $rv;
334              
335             pdebug( 'entering', PDLEVEL1 );
336             pIn();
337              
338             # Close the environment
339             $rv = _closeDbe( $obj->home ) if !$obj->isStale;
340              
341             pOut();
342             pdebug( 'leaving w/rv: %s', PDLEVEL1, $rv );
343              
344             return $rv;
345             }
346              
347             1;
348              
349             __END__