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   4769 use Class::Std;
  3         8  
  3         26  
3              
4 3     3   392 use warnings;
  3         5  
  3         99  
5 3     3   15 use strict;
  3         5  
  3         123  
6              
7 3     3   17 use Fcntl;
  3         6  
  3         1303  
8 3     3   2861 use AnyDBM_File;
  3         14798  
  3         176  
9 3     3   38 use Carp qw(carp);
  3         6  
  3         143  
10 3     3   17 use File::Basename;
  3         8  
  3         205  
11 3     3   3281 use LockFile::Simple;
  3         25718  
  3         2257  
12              
13             =head1 NAME
14              
15             Email::Fingerprint::Cache::AnyDBM - AnyDBM backend for Email::Fingerprint::Cache
16              
17             =head1 VERSION
18              
19             Version 0.01
20              
21             =cut
22              
23             our $VERSION = '0.01';
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 684 my ( $self, $ident, $args ) = @_;
64              
65 11         153 $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 18 my $self = shift;
84              
85 9   100     50 my $file = $file{ ident $self } || '';
86 9 100       35 return unless $file;
87              
88 8         40 my $hash = $self->get_hash;
89              
90 8         1044 tie %$hash, 'AnyDBM_File', $file, O_CREAT|O_RDWR, oct(600);
91              
92 8 50       32 if ( not $self->is_open ) {
93 0         0 carp "Couldn't open $file";
94 0         0 return;
95             }
96              
97 8         49 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 18 my $self = shift;
109              
110 9 100       29 return unless $self->is_open;
111              
112 8         14 untie %{ $self->get_hash };
  8         28  
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 61 my $self = shift;
123 34         134 my $hash = $self->get_hash;
124              
125 34 50 33     216 return 0 unless defined $hash and ref $hash eq 'HASH';
126 34 100       46 return 0 unless tied %{ $hash };
  34         172  
127 20         73 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 14 my $self = shift;
138 7 100       68 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 19 my $self = shift;
152 7         16 my %opts = @_;
153              
154 7 100       45 return 1 if exists $lock{ ident $self }; # Success if already locked
155              
156 6 100       50 return unless defined $file{ ident $self }; # Can't lock nothing!
157 5         24 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       585 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 5 100       54 my $lock
169             = $opts{block}
170             ? $mgr->lock($file)
171             : $mgr->trylock($file);
172 5 50       2853 return unless $lock;
173              
174             # Remember the lock
175 5         27 $lock{ ident $self } = $lock;
176              
177 5         31 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 27 my $self = shift;
190 15 100       111 my $lock = delete $lock{ ident $self } or return 1; # Success if no lock
191              
192 5         80 $lock->release();
193              
194 5         2070 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         572 my $self = shift;
207 50         570 return $hash{ ident $self };
208 3     3   31 }
  3         5  
  3         35  
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;