File Coverage

blib/lib/File/SmartTail/DB.pm
Criterion Covered Total %
statement 38 59 64.4
branch 6 26 23.0
condition 7 22 31.8
subroutine 8 10 80.0
pod 0 4 0.0
total 59 121 48.7


line stmt bran cond sub pod time code
1             #
2             # $Id: DB.pm,v 1.9 2008/07/09 20:40:20 mprewitt Exp $
3             # $Source: /usr/local/src/perllib/Tail/0.1/lib/File/SmartTail/RCS/DB.pm,v $
4             #
5             # DMJA, Inc
6             #
7             # Copyright (C) 2003-2008 DMJA, Inc, File::SmartTail comes with
8             # ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to
9             # redistribute it and/or modify it under the same terms as Perl itself.
10             # See the "The Artistic License" L for more details.
11             package File::SmartTail::DB;
12              
13 5     5   24 use strict;
  5         9  
  5         118  
14 5     5   25 use warnings;
  5         8  
  5         202  
15              
16 5     5   24 use Fcntl qw(:DEFAULT :flock);
  5         9  
  5         2476  
17              
18 5     5   27 use constant MAX_RETRIES => 6;
  5         8  
  5         4146  
19              
20             if ( ! -d "/var/tmp/filestatus" ) {
21             mkdir( "/var/tmp/filestatus", 01777 ) ||
22             die "Unable to make status directory /var/tmp/filestatus [$!].\n";
23              
24             chmod( 01777, "/var/tmp/filestatus" );
25             }
26              
27             {
28             my %cache;
29             sub new {
30 1     1 0 4 my $type = shift;
31 1         7 my %h = @_;
32              
33             my $statuskey = $h{statuskey} or
34 1 50       7 LOG()->logdie( "required param: statuskey" );
35 1   50     6 my $tietype = $h{tietype} || 'DB_File';
36 1         6 my $cachekey = join "\0", $statuskey, $tietype;
37 1 50       6 $cache{$cachekey} and return $cache{$cachekey};
38              
39 1         5 my $filename = "/var/tmp/filestatus/$statuskey";
40 1         4 my $saverr = "";
41 1 50       7 my $fullname = $filename . (($tietype eq 'NDBM_File') ? ".pag" : "");
42 1 50 33     67 if (-f $fullname && open(FH, ">> $fullname ")) {
43 0         0 my $count = 0;
44 0         0 while (++$count < MAX_RETRIES) {
45 0 0       0 last if flock(FH, LOCK_EX | LOCK_NB);
46 0         0 $saverr = $!;
47 0         0 sleep (2 ** $count);
48             }
49 0 0       0 LOG()->logdie( "Could not lock $filename in @{[MAX_RETRIES()]} attemps [$saverr].\n" )
  0         0  
50             if ($count >= MAX_RETRIES);
51 0         0 flock(FH, LOCK_UN | LOCK_NB);
52 0         0 close FH;
53             }
54              
55 1         4 my %STATUS;
56 1     1   160 eval "use $tietype";
  1         54  
  1         9  
  1         57  
57 1 50       8 die "Unable to use $tietype [$@]" if $@;
58 1   33     244 my $STATFILE = tie( %STATUS, $tietype, $filename,
59             O_RDWR | O_CREAT, 0600 ) ||
60             LOG()->logdie( "Tie of status for $statuskey failed [$!].\n" );
61              
62 1   33     21 my $self = bless {
63             STATUS => \%STATUS,
64             STATFILE => $STATFILE,
65             STATUSKEY => $statuskey,
66             TIETYPE => $tietype,
67             }, ref $type || $type;
68              
69             #
70             # keep our own reference, so the logging object is
71             # destroyed AFTER $self.
72             #
73 1         6 $self->{LOG} = LOG();
74              
75 1         7 $self->sync;
76              
77 1         15 return $cache{$cachekey} = $self;
78             }
79             }
80              
81             sub sync {
82 1     1 0 3 my $self = shift;
83              
84 1 50 33     19 if ($self->{STATFILE} && $self->can('sync')) {
85 1         5 eval {
86             $self->{STATFILE}->sync
87 1         24 };
88             }
89             }
90              
91             sub DESTROY {
92 0 0   0   0 my $self = shift or return;
93              
94 0         0 $self->sync;
95             # LOG()->debug( sub {
96             # my $tt = $self->{TIETYPE} || '';
97             # my $sf = $self->{STATFILE} || '';
98             # my $ds = $self->DumpStatus || '';
99             # "sub DESTROY: TIETYPE: $tt; STATFILE: $sf; $ds";
100             # } );
101             # delete $self->{STATFILE}; # undef necessary?
102             # untie %{ $self->{STATUS} }; # will this do the right thing?
103             }
104              
105             sub DumpStatus {
106 0 0   0 0 0 my $self = shift or return;
107 0         0 my %h = @_;
108              
109 0         0 my $indent = $h{indent};
110 0 0       0 defined $indent or $indent = 1;
111              
112 0         0 my $tab = "\t" x $indent;
113              
114 0   0     0 my $sk = $self->{STATUSKEY} || '';
115 0 0       0 my @k = $self->{STATUS} ? sort keys %{ $self->{STATUS} } : ();
  0         0  
116 0 0       0 my @m = @k ? map "$_ =>\t$self->{STATUS}->{$_}", @k : ();
117 0         0 return join "\n$tab", "STATUSKEY file: $sk:", @m;
118             }
119              
120             {
121             my $v;
122             sub LOG {
123 1   33 1 0 28 $v ||= require File::SmartTail::Logger && File::SmartTail::Logger::LOG();
      33        
124             }
125             }
126              
127             1;