File Coverage

blib/lib/IO/LockedFile.pm
Criterion Covered Total %
statement 83 103 80.5
branch 25 48 52.0
condition 9 18 50.0
subroutine 21 23 91.3
pod 12 12 100.0
total 150 204 73.5


line stmt bran cond sub pod time code
1             package IO::LockedFile;
2              
3 7     7   15722 use strict;
  7         14  
  7         329  
4 7     7   35 use vars qw($VERSION @ISA);
  7         14  
  7         539  
5              
6             $VERSION = 0.23;
7              
8 7     7   6916 use IO::File;
  7         89180  
  7         1267  
9             @ISA = ("IO::File"); # subclass of IO::File
10              
11 7     7   77 use strict;
  7         14  
  7         224  
12 7     7   42 use Carp;
  7         14  
  7         10640  
13              
14             # Set default options
15             my %Options;
16             _set_option( __PACKAGE__, ( block => 1,
17             lock => 1,
18             scheme => 'Flock',
19             _locked => 0,
20             _writable => 0 ) );
21              
22             ###########################
23             # new
24             ###########################
25             # the constructor
26             sub new {
27 39     39 1 105111 my $proto = shift; # get the class name
28 39   33     1203 my $class = ref($proto) || $proto;
29 39         1206 my $self = $class->SUPER::new(); # the object is also file handle
30              
31             # Grab our options (if they're there);
32 39         5292 my $options = {};
33 39 100       425 $options = shift if ref($_[0]) eq 'HASH';
34              
35 39 50       504 if ( exists $options->{ scheme } ) {
    50          
36             # User-specified scheme (may have to load it)
37 0         0 $class = join( '::', __PACKAGE__, $options->{ scheme } );
38 0         0 eval "require $class";
39 0 0       0 croak "Unable to load $class: $@" if $@;
40             }
41             elsif ( $class eq __PACKAGE__ ) {
42             # User didn't specify anything (or subclass), so do it for her
43 39         399 $class .= '::' . get_scheme( $class );
44             }
45              
46 39         324 bless ($self, $class);
47              
48             # Store our options
49 39         134 $self->_set_option( %{ $options } );
  39         513  
50              
51             # if receives any parameters, call our open with those parameters
52 39 50       302 if (@_) {
53 39 100       548 $self->open(@_) or return undef;
54             }
55              
56 30         150 return $self;
57             } # of new
58              
59             ############################
60             # open
61             ############################
62             sub open {
63 39     39 1 115 my $self = shift;
64              
65 39         62 my $writable = 0;
66 39 100       637 if ( scalar(@_) == 1 ) {
    100          
67             # Perl mode. Look at first character
68              
69             # Quick sanity check. We can't lock a pipe
70 23 50 33     706 if (( substr( $_[0], 0, 1 ) eq '|' ) ||
71             ( substr( $_[0], -1, 1 ) eq '|' ) ) {
72 0         0 croak "Cannot lock a pipe"
73             }
74              
75             # OK, now look at first character
76 23         260 $writable = substr( $_[0], 0, 1 ) eq '>';
77             }
78             elsif ( $_[1] =~ /^\d+$/ ) {
79             # Numeric mode
80 7         562 require Fcntl;
81 7   33     215 $writable = ( ( $_[1] & O_APPEND ) ||
82             ( $_[1] & O_CREAT ) ||
83             ( $_[1] & O_TRUNC ) );
84             }
85             else {
86             # POSIX mode (we know there were enough parameters since our
87             # SUPER succeeded).
88 9         91 $writable = ( $_[1] ne 'r' );
89             }
90              
91 39         428 $self->_set_writable( $writable );
92             # call open of the super class (IO::File) with the rest of the parameters
93 39 50       736 $self->SUPER::open(@_) or return undef;
94              
95 39 50       6668 if ( $self->should_lock() ) {
96 39 100       411 $self->lock() or return undef;
97             }
98              
99 30         112 return 1;
100             } # of open
101              
102             ########################
103             # lock
104             ########################
105             sub lock {
106 30     30 1 76 my $self = shift;
107              
108 30         158 $self->_set_locked( 1 );
109 30         72 return 1;
110             } # of lock
111              
112             ########################
113             # unlock
114             ########################
115             sub unlock {
116 30     30 1 80 my $self = shift;
117 30         133 $self->_set_locked( 0 );
118 30         71 return 1;
119             } # of unlock
120              
121             ########################
122             # close
123             ########################
124             sub close {
125 39     39 1 268 my $self = shift;
126             # if the file was opened - unlock it
127 39 100 66     745 $self->unlock() if ($self->opened() and $self->have_lock());
128 39         358 $self->SUPER::close();
129             } # of close
130              
131             #######################
132             # have_lock
133             #######################
134             sub have_lock {
135 39     39 1 1442 my $self = shift;
136 39         248 return $self->_get_option( '_locked' );
137             } # of have_lock
138              
139             #######################
140             # _set_locked
141             #######################
142             sub _set_locked {
143 60     60   218 my ( $self, $value ) = @_;
144 60         253 return $self->_set_option( '_locked', $value );
145             } # of _set_locked
146              
147             #######################
148             # is_writable
149             #######################
150             sub is_writable {
151 39     39 1 115 my $self = shift;
152 39         118 return $self->_get_option( '_writable' );
153             } # of is_writable
154              
155             #######################
156             # _set_writable
157             #######################
158             sub _set_writable {
159 39     39   219 my ( $self, $value ) = @_;
160 39         446 return $self->_set_option( '_writable', $value );
161             } # of _set_writable
162              
163             #######################
164             # should_block
165             #######################
166             sub should_block {
167 39     39 1 81 my $self = shift;
168 39         196 return $self->_get_option( 'block' );
169             } # of should_block
170              
171             #######################
172             # should_lock
173             #######################
174             sub should_lock {
175 39     39 1 89 my $self = shift;
176 39         1189 return $self->_get_option( 'lock' );
177             } # of should_lock
178              
179             #######################
180             # print
181             #######################
182             sub print {
183 0     0 1 0 my ( $self, @args ) = @_;
184              
185 0         0 my $was_locked = $self->have_lock();
186              
187 0 0       0 if ( ! $was_locked ) {
188 0 0       0 return 0 unless $self->lock();
189             }
190 0         0 my $rc = $self->SUPER::print( @args );
191 0 0       0 $self->unlock unless $was_locked;
192              
193 0         0 return $rc;
194             } # of print
195              
196             #######################
197             # truncate
198             #######################
199             sub truncate {
200 0     0 1 0 my ( $self, @args ) = @_;
201              
202 0         0 my $was_locked = $self->have_lock();
203              
204 0 0       0 if ( ! $was_locked ) {
205 0 0       0 return 0 unless $self->lock();
206             }
207 0         0 my $rc = $self->SUPER::truncate( @args );
208 0 0       0 $self->unlock() unless $was_locked;
209              
210 0         0 return $rc;
211             } # of truncate
212              
213             #######################
214             # get_scheme
215             #######################
216             sub get_scheme {
217 46     46 1 164 my $self = shift;
218              
219 46         277 return _get_option( $self, 'scheme' );
220             } # of get_scheme
221            
222             #######################
223             # DESTROY
224             #######################
225             sub DESTROY {
226 39     39   10408494 my $self = shift;
227             # if the file was opened, close (and unlock) it
228 39         729 $self->close;
229             } # of DESTROY
230              
231             ######################
232             # _get_option
233             ######################
234             sub _get_option {
235 352     352   1385 my( $self, $key ) = @_;
236              
237             # Is the option set here?
238 352 100 100     2760 if ( exists $Options{ $self } && exists $Options{ $self }->{ $key } ) {
    100          
    50          
239 202         2480 return $Options{ $self }->{ $key }
240             }
241             # If we're an object, check out class
242             elsif ( ref( $self ) ) {
243 75         622 return _get_option( ref( $self ), $key );
244             }
245             # If we're a class other than this one, check defaults
246             elsif ( $self ne __PACKAGE__ ) {
247 75         340 return _get_option( __PACKAGE__, $key );
248             }
249             # It's nowhere. Probably a typo
250             else {
251 0         0 croak "Bad option fetch: $key\n";
252             }
253             } # of _get_option
254              
255             ######################
256             # _set_option
257             ######################
258             sub _set_option {
259 152     152   901 my( $self, %hash ) = @_;
260              
261 152         1134 while ( my( $key, $value ) = each %hash ) {
262 146         1838 $Options{ $self }->{ $key } = $value;
263             }
264             } # of _set_option
265              
266             ######################
267             # import
268             ######################
269             sub import {
270 7     7   49 my $pkg = shift;
271 7         14 my( %config );
272 7 50       28 if ( @_ == 1 ) {
273 0         0 $config{ scheme } = shift;
274             }
275             else {
276 7         14 %config = @_;
277             }
278              
279 7   33     42 my $scheme = $config{ scheme } || $pkg->get_scheme;
280              
281 7         35 my $class = __PACKAGE__ . "::$scheme";
282 7         448 eval "require $class";
283 7 50       63 croak "Unable to load $class: $@" if $@;
284              
285 7         77 $class->_set_option( %config );
286             } # of import
287              
288             1;
289             __END__