File Coverage

blib/lib/Tie/MAB2/Recno.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


line stmt bran cond sub pod time code
1             package Tie::MAB2::Recno;
2              
3 2     2   28353 use strict;
  2         6  
  2         141  
4              
5             BEGIN {
6 2     2   2362 use Tie::Array;
  2         4129  
  2         83  
7 2     2   75 our @ISA = qw(Tie::StdArray);
8             }
9              
10 2     2   2577 use BerkeleyDB qw( DB_RDONLY DB_CREATE DB_FAST_STAT );
  0            
  0            
11              
12             warn sprintf "WARNING: Recommended Berkeley DB version is 4.0 or higher. Yours is %s.
13             Be prepared for trouble!", $BerkeleyDB::db_version if $BerkeleyDB::db_version<4;
14              
15             use Fcntl qw( SEEK_SET );
16             use MAB2::Record::Base;
17              
18             our $VERSION = sprintf "%d.%03d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/;
19              
20              
21             sub TIEARRAY {
22             my($class,%args) = @_;
23             my $self = {};
24             $self->{ARGS} = \%args;
25             die "Could not tie: required argument file missing" unless exists $args{file};
26             my $fh;
27             unless (open $fh, "<", $args{file}) {
28             require Carp;
29             Carp::confess("Could not open $args{file}: $!");
30             }
31             $self->{FH} = $fh;
32              
33             my $buf;
34             read $fh, $buf, 3;
35             seek $fh, 0, SEEK_SET;
36              
37             if ($buf eq "###") {
38             $self->{RS} = "";
39             } else {
40             $self->{RS} = "\n";
41             }
42              
43             # warn sprintf "Filesize: %d\n", -s $fh;
44             my @offset;
45             # ("BerkeleyDB::Recno", -Filename => "$args{file}.bdbrecno", -Flags => DB_RDONLY, -Mode => 0600);
46              
47             my $db = tie(@offset, "BerkeleyDB::Recno", -Filename => "$args{file}.bdbrecno", -Flags => DB_RDONLY, -Mode => 0644);
48              
49             #############################################^^^^^^^ did simply not work with RDONLY
50             unless ($db) {
51             $db = tie(@offset, "BerkeleyDB::Recno", -Filename => "$args{file}.bdbrecno", -Flags => DB_CREATE, -Mode => 0644) or die "Could not tie: $!";
52             warn "Creating offset index";
53             local($/) = $self->{RS};
54             my $Loffset = 0;
55             local($|) = 1;
56             while (<$fh>) {
57             $offset[$. - 1] = $Loffset;
58             my $offset = tell $fh;
59             printf "." unless int $offset/1000000 == int $Loffset/1000000;
60             $Loffset = $offset;
61             }
62             }
63             my $stat = $db->db_stat(DB_FAST_STAT);
64             # use Data::Dumper;
65             # print Data::Dumper::Dumper($stat);
66             $self->{NKEYS} = $stat->{bt_nkeys}; # doesn't seem to improve much, but...
67              
68             $self->{OFFSET} = \@offset;
69             bless $self, ref $class || $class;
70             }
71              
72             sub UNTIE {
73             my $self = shift;
74             close $self->{FH};
75             untie @{$self->{OFFSET}};
76             }
77              
78             sub FETCH {
79             my($self, $key) = @_;
80             my $fh = $self->{FH};
81             seek $fh, $self->{OFFSET}[$key], SEEK_SET;
82             local($/) = $self->{RS};
83             my $rec = <$fh>;
84             if ($self->{RS}){ # Band
85             chomp $rec;
86             } else { # convert Diskette to Band
87             $rec =~ s/^### //;
88             $rec =~ s/\015?\012//; # the first
89             $rec =~ s/\s*\z/\c^\c]/;
90             $rec =~ s/\015?\012/\c^/g ;
91             }
92             my $obj = MAB2::Record::Base->new($rec,$key);
93             $obj;
94             }
95              
96             sub FETCHSIZE {
97             my($self) = @_;
98             $self->{NKEYS};
99             }
100              
101             sub EXISTS {
102             my($self,$key) = @_;
103             $key >= 0 && $key <= $self->{NKEYS};
104             }
105              
106             for my $method (qw(STORE DELETE CLEAR)) {
107             no strict "refs";
108             *$method = sub {
109             warn "$method not supported on ".ref shift;
110             return;
111             };
112             }
113              
114             #sub EXISTS {
115             # my($self, $key) = @_;
116             # exists $self->{OFFSET}[$key];
117             #}
118              
119             1;
120              
121             __END__