File Coverage

blib/lib/Email/Fingerprint/Cache/AnyDBM.pm
Criterion Covered Total %
statement 65 69 94.2
branch 20 24 83.3
condition 3 5 60.0
subroutine 16 16 100.0
pod 7 7 100.0
total 111 121 91.7


line stmt bran cond sub pod time code
1             package Email::Fingerprint::Cache::AnyDBM;
2 3     3   2491 use Class::Std;
  3         6  
  3         15  
3              
4 3     3   300 use warnings;
  3         7  
  3         72  
5 3     3   15 use strict;
  3         7  
  3         61  
6              
7 3     3   19 use Fcntl;
  3         9  
  3         688  
8 3     3   1139 use AnyDBM_File;
  3         7185  
  3         123  
9 3     3   23 use Carp qw(carp);
  3         7  
  3         112  
10 3     3   20 use File::Basename;
  3         8  
  3         158  
11 3     3   1268 use LockFile::Simple;
  3         13802  
  3         1486  
12              
13             =head1 NAME
14              
15             Email::Fingerprint::Cache::AnyDBM - AnyDBM backend for Email::Fingerprint::Cache
16              
17             =head1 VERSION
18              
19             Version 0.49
20              
21             =cut
22              
23             our $VERSION = '0.49';
24              
25             =head1 SYNOPSIS
26              
27             use Email::Fingerprint::Cache;
28              
29             my $foo = Email::Fingerprint::Cache->new({
30             backend => 'AnyDBM',
31             });
32             ...
33              
34             You never want to use this class directly; you always want to access it
35             through Email::Fingerpint::Cache.
36              
37             =head1 ATTRIBUTES
38              
39             =cut
40              
41             my %file :ATTR( :init_arg, :set ) = ();
42             my %hash :ATTR( :init_arg ) = ();
43             my %lock :ATTR = ();
44             my %mgr :ATTR = ();
45              
46             =head1 FUNCTIONS
47              
48             =head2 new
49              
50             $cache = new Email::Fingerprint::Cache::AnyDBM({
51             file => $filename, # Mandatory
52             });
53              
54             Method created automatically by C.
55              
56             =head2 BUILD
57              
58             Internal helper method; never called directly by users.
59              
60             =cut
61              
62             sub BUILD {
63 11     11 1 818 my ( $self, $ident, $args ) = @_;
64              
65 11         114 $mgr{$ident} = LockFile::Simple->make(
66             -nfs => 1,
67             -warn => 0,
68             -efunc => undef,
69             -autoclean => 1,
70             );
71             }
72              
73             =head2 open
74              
75             $cache->open or die;
76              
77             Open the associated file, and tie it to our hash. This method does not
78             lock the file, nor unlock it on failure. See C and C.
79              
80             =cut
81              
82             sub open {
83 9     9 1 21 my $self = shift;
84              
85 9   100     42 my $file = $file{ ident $self } || '';
86 9 100       34 return unless $file;
87              
88 8         28 my $hash = $self->get_hash;
89              
90 8         622 tie %$hash, 'AnyDBM_File', $file, O_CREAT|O_RDWR, oct(600);
91              
92 8 50       37 if ( not $self->is_open ) {
93 0         0 carp "Couldn't open $file";
94 0         0 return;
95             }
96              
97 8         38 1;
98             }
99              
100             =head2 close
101              
102             Unties the hash, which causes the underlying DB file to be written and
103             closed.
104              
105             =cut
106              
107             sub close {
108 9     9 1 21 my $self = shift;
109              
110 9 100       31 return unless $self->is_open;
111              
112 8         19 untie %{ $self->get_hash };
  8         31  
113             }
114              
115             =head2 is_open
116              
117             Returns true if the cache is open; false otherwise.
118              
119             =cut
120              
121             sub is_open {
122 34     34 1 71 my $self = shift;
123 34         111 my $hash = $self->get_hash;
124              
125 34 50 33     199 return 0 unless defined $hash and ref $hash eq 'HASH';
126 34 100       56 return 0 unless tied %{ $hash };
  34         137  
127 20         70 return 1;
128             }
129              
130             =head2 is_locked
131              
132             Returns true if the cache is locked; false otherwise.
133              
134             =cut
135              
136             sub is_locked {
137 7     7 1 19 my $self = shift;
138 7 100       57 return defined $lock{ ident $self } ? 1 : 0;
139             }
140              
141             =head2 lock
142              
143             $cache->lock or die; # returns immediately
144             $cache->lock( block => 1 ) or die; # Waits for a lock
145              
146             Lock the DB file. Returns false on failure, true on success.
147              
148             =cut
149              
150             sub lock {
151 7     7 1 18 my $self = shift;
152 7         83 my %opts = @_;
153              
154 7 100       52 return 1 if exists $lock{ ident $self }; # Success if already locked
155              
156 6 100       36 return unless defined $file{ ident $self }; # Can't lock nothing!
157 5         18 my $file = $file{ ident $self };
158              
159 5         15 my $mgr = $mgr{ ident $self };
160              
161             # Minor validation that LockFile::Simple doesn't perform
162 5 50       386 if (not -w dirname($file)) {
163 0         0 warn "Directory " . dirname($file) . " is not writable\n";
164 0         0 return;
165             }
166              
167             # Perform the lock
168             my $lock
169             = $opts{block}
170 5 100       48 ? $mgr->lock($file)
171             : $mgr->trylock($file);
172 5 50       2051 return unless $lock;
173              
174             # Remember the lock
175 5         26 $lock{ ident $self } = $lock;
176              
177 5         27 1;
178             }
179              
180             =head2 unlock
181              
182             $cache->unlock or cluck "Unlock failed";
183              
184             Unlocks the DB file. Returns false on failure, true on success.
185              
186             =cut
187              
188             sub unlock {
189 15     15 1 28 my $self = shift;
190 15 100       85 my $lock = delete $lock{ ident $self } or return 1; # Success if no lock
191              
192 5         51 $lock->release();
193              
194 5         1141 1;
195             }
196              
197             =head1 PRIVATE METHODS
198              
199             =head2 get_hash
200              
201             Returns a reference to the hash which is tied to the backend storage.
202              
203             =cut
204              
205             sub get_hash : PRIVATE {
206 50         557 my $self = shift;
207 50         306 return $hash{ ident $self };
208 3     3   23 }
  3         7  
  3         24  
209              
210             =head1 AUTHOR
211              
212             Len Budney, C<< >>
213              
214             =head1 BUGS
215              
216             Please report any bugs or feature requests to
217             C, or through the web interface at
218             L.
219             I will be notified, and then you'll automatically be notified of progress on
220             your bug as I make changes.
221              
222             =head1 SUPPORT
223              
224             You can find documentation for this module with the perldoc command.
225              
226             perldoc Email::Fingerprint::Cache::AnyDBM
227              
228             You can also look for information at:
229              
230             =over 4
231              
232             =item * AnnoCPAN: Annotated CPAN documentation
233              
234             L
235              
236             =item * CPAN Ratings
237              
238             L
239              
240             =item * RT: CPAN's request tracker
241              
242             L
243              
244             =item * Search CPAN
245              
246             L
247              
248             =back
249              
250             =head1 ACKNOWLEDGEMENTS
251              
252             Email::Fingerprint::Cache is based on caching code in the
253             C script by Peter Samuel and available at
254             L.
255              
256             =head1 COPYRIGHT & LICENSE
257              
258             Copyright 2006-2011 Len Budney, all rights reserved.
259              
260             This program is free software; you can redistribute it and/or modify it
261             under the same terms as Perl itself.
262              
263             =cut
264              
265             1;