File Coverage

blib/lib/File/SmartTail/DB.pm
Criterion Covered Total %
statement 12 53 22.6
branch 0 26 0.0
condition 0 22 0.0
subroutine 4 9 44.4
pod 0 4 0.0
total 16 114 14.0


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 1     1   802 use strict;
  1         2  
  1         27  
14 1     1   5 use warnings;
  1         1  
  1         30  
15              
16 1     1   4 use Fcntl qw(:DEFAULT :flock);
  1         2  
  1         580  
17              
18             my @TIETYPES = qw( DB_File NDBM_File );
19             my %TIETYPES;
20             @TIETYPES{ @TIETYPES } = ();
21              
22 1     1   5 use constant MAX_RETRIES => 6;
  1         2  
  1         876  
23              
24             if ( ! -d "/var/tmp/filestatus" ) {
25             mkdir( "/var/tmp/filestatus", 01777 ) ||
26             die "Unable to make status directory /var/tmp/filestatus [$!].\n";
27              
28             chmod( 01777, "/var/tmp/filestatus" );
29             }
30              
31             {
32             my %cache;
33             sub new {
34 0     0 0   my $type = shift;
35 0           my %h = @_;
36              
37 0 0         my $statuskey = $h{statuskey} or
38             LOG()->logdie( "required param: statuskey" );
39 0   0       my $tietype = $h{tietype} || 'DB_File';
40 0 0         exists $TIETYPES{$tietype} or
41             LOG()->logdie( "unrecognized: tietype: $tietype. Must be one of @TIETYPES" );
42 0           my $cachekey = join "\0", $statuskey, $tietype;
43 0 0         $cache{$cachekey} and return $cache{$cachekey};
44              
45 0           my $filename = "/var/tmp/filestatus/$statuskey";
46 0           my $saverr = "";
47 0 0         my $fullname = $filename . (($tietype eq 'NDBM_File') ? ".pag" : "");
48 0 0 0       if (-f $fullname && open(FH, ">> $fullname ")) {
49 0           my $count = 0;
50 0           while (++$count < MAX_RETRIES) {
51 0 0         last if flock(FH, LOCK_EX | LOCK_NB);
52 0           $saverr = $!;
53 0           sleep (2 ** $count);
54             }
55 0 0         LOG()->logdie( "Could not lock $filename in @{[MAX_RETRIES()]} attemps [$saverr].\n" )
  0            
56             if ($count >= MAX_RETRIES);
57 0           flock(FH, LOCK_UN | LOCK_NB);
58 0           close FH;
59             }
60              
61 0           my %STATUS;
62 0   0       my $STATFILE = tie( %STATUS, $tietype, $filename,
63             O_RDWR | O_CREAT, 0600 ) ||
64             LOG()->logdie( "Tie of status for $statuskey failed [$!].\n" );
65              
66 0   0       my $self = bless {
67             STATUS => \%STATUS,
68             STATFILE => $STATFILE,
69             STATUSKEY => $statuskey,
70             TIETYPE => $tietype,
71             }, ref $type || $type;
72              
73             #
74             # keep our own reference, so the logging object is
75             # destroyed AFTER $self.
76             #
77 0           $self->{LOG} = LOG();
78              
79 0           $self->sync;
80              
81 0           return $cache{$cachekey} = $self;
82             }
83             }
84              
85             sub sync {
86 0     0 0   my $self = shift;
87              
88 0 0 0       $self->{STATFILE}->sync if $self->{STATFILE} && $self->{TIETYPE} eq 'DB_File';
89             }
90              
91             sub DESTROY {
92 0 0   0     my $self = shift or return;
93              
94 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   my $self = shift or return;
107 0           my %h = @_;
108              
109 0           my $indent = $h{indent};
110 0 0         defined $indent or $indent = 1;
111              
112 0           my $tab = "\t" x $indent;
113              
114 0   0       my $sk = $self->{STATUSKEY} || '';
115 0 0         my @k = $self->{STATUS} ? sort keys %{ $self->{STATUS} } : ();
  0            
116 0 0         my @m = @k ? map "$_ =>\t$self->{STATUS}->{$_}", @k : ();
117 0           return join "\n$tab", "STATUSKEY file: $sk:", @m;
118             }
119              
120             {
121             my $v;
122             sub LOG {
123 0   0 0 0   $v ||= require File::SmartTail::Logger && File::SmartTail::Logger::LOG();
      0        
124             }
125             }
126              
127             1;