File Coverage

blib/lib/Tie/MAB2/Id.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::Id;
2              
3 1     1   2128 use strict;
  1         2  
  1         46  
4              
5             BEGIN {
6 1     1   798 use Tie::Hash;
  1         978  
  1         36  
7 1     1   37 our @ISA = qw(Tie::StdHash);
8             }
9              
10 1     1   399 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.5 $ =~ /(\d+)\.(\d+)/;
19              
20              
21             sub TIEHASH {
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             open my $fh, "<", $args{file} or Carp::confess("Could not open $args{file}: $!");
27             $self->{FH} = $fh;
28             # warn sprintf "Filesize: %d\n", -s $fh;
29             my %offset;
30             # ("BerkeleyDB::Recno", -Filename => "$args{file}.bdbrecno", -Flags => DB_RDONLY, -Mode => 0600);
31              
32             my $db = tie(%offset, "BerkeleyDB::Hash", -Filename => "$args{file}.bdbhash", -Flags => DB_RDONLY, -Mode => 0644);
33              
34             #############################################^^^^^^^ did simply not work with RDONLY
35             unless ($db) {
36             $db = tie(%offset, "BerkeleyDB::Hash", -Filename => "$args{file}.bdbhash", -Flags => DB_CREATE, -Mode => 0644) or die "Could not tie $args{file}.bdbhash: $!";
37             warn "Creating ID index";
38             local($/) = "\n";
39             my $Loffset = 0;
40             local($|) = 1;
41             while (<$fh>) {
42             chomp;
43             my $obj = MAB2::Record::Base->new($_);
44             $offset{$obj->id} = $Loffset;
45             my $offset = tell $fh;
46             printf "." unless int $offset/1000000 == int $Loffset/1000000;
47             $Loffset = $offset;
48             }
49             }
50             my $stat = $db->db_stat(DB_FAST_STAT);
51             # use Data::Dumper;
52             # print Data::Dumper::Dumper($stat);
53             $self->{OFFSET} = \%offset;
54             bless $self, ref $class || $class;
55             }
56              
57             sub UNTIE {
58             my $self = shift;
59             close $self->{FH};
60             untie %{$self->{OFFSET}};
61             }
62              
63             sub FETCH {
64             my($self, $key) = @_;
65             my $fh = $self->{FH};
66             my $offset = $self->{OFFSET}{$key};
67             return undef unless defined $offset;
68             seek $fh, $offset, SEEK_SET;
69             local($/) = "\n";
70             my $rec = <$fh>;
71             chomp $rec;
72             my $obj = MAB2::Record::Base->new($rec,$key);
73             $obj;
74             }
75              
76             for my $method (qw(STORE DELETE CLEAR)) {
77             no strict "refs";
78             *$method = sub {
79             warn "$method not supported on ".ref shift;
80             return;
81             };
82             }
83              
84             sub EXISTS {
85             my($self, $key) = @_;
86             exists $self->{OFFSET}{$key};
87             }
88              
89             sub NEXTKEY {
90             my $self = shift;
91             return each %{ $self->{OFFSET} };
92             }
93              
94             sub FIRSTKEY {
95             my $self = shift;
96             my $a = keys %{$self->{OFFSET}};
97             return each %{ $self->{OFFSET} };
98             }
99              
100             1;
101              
102             __END__