File Coverage

lib/Archive/BagIt/Fast.pm
Criterion Covered Total %
statement 62 71 87.3
branch 5 10 50.0
condition 1 2 50.0
subroutine 13 13 100.0
pod 2 2 100.0
total 83 98 84.6


line stmt bran cond sub pod time code
1             package Archive::BagIt::Fast;
2 2     2   8123 use strict;
  2         3  
  2         50  
3 2     2   7 use warnings;
  2         4  
  2         59  
4 2     2   8 use Carp qw( carp croak );
  2         4  
  2         102  
5 2     2   905 use Time::HiRes qw( time );
  2         2376  
  2         6  
6 2     2   1274 use Moo;
  2         20883  
  2         14  
7 2     2   3397 use IO::AIO ();
  2         6487  
  2         37  
8 2     2   1011 use Net::SSLeay ();
  2         20641  
  2         184  
9             extends "Archive::BagIt";
10              
11              
12             our $VERSION = '0.090'; # VERSION
13              
14             # ABSTRACT: A module to use L to get better performance
15              
16              
17             sub BEGIN {
18 2     2   1221 Net::SSLeay::OpenSSL_add_all_digests();
19             }
20              
21             sub _XXX_digest {
22 138     138   163 my $digestobj = shift;
23 138         120 my $data_ref = shift;
24 138         123 my $data = ${ $data_ref };
  138         220  
25 138         639 my $md = Net::SSLeay::EVP_get_digestbyname($digestobj->name);
26 138         279 my $internal_digest = Net::SSLeay::EVP_MD_CTX_create();
27 138         383 Net::SSLeay::EVP_DigestInit($internal_digest, $md);
28 138         395 Net::SSLeay::EVP_DigestUpdate($internal_digest, $data);
29 138         533 my $result = Net::SSLeay::EVP_DigestFinal($internal_digest);
30 138         399 Net::SSLeay::EVP_MD_CTX_destroy($internal_digest);
31 138         352 my $digest = unpack('H*', $result);
32 138         1791 return $digest;
33              
34             }
35              
36             sub sysread_based_digest {
37 134     134 1 4990 my $digestobj = shift;
38 134         127 my $fh = shift;
39 134         131 my $filesize = shift;
40 134         126 my $data;
41 134         1159 sysread $fh, $data, $filesize;
42 134         404 return _XXX_digest( $digestobj, \$data);
43             }
44              
45             sub mmap_based_digest {
46 4     4 1 5 my $digestobj = shift;
47 4         5 my $fh = shift;
48 4         4 my $filesize = shift;
49 4         5 my $data='';
50 4 100       10 if ($filesize > 0) {
51 2 50       59 if (! IO::AIO::mmap $data, $filesize, IO::AIO::PROT_READ, IO::AIO::MAP_SHARED, $fh) {
52 0         0 carp "mmap fails, fall back to sysread";
53 0         0 sysread $fh, $data, $filesize;
54             };
55             }
56 4         11 return _XXX_digest($digestobj, \$data);
57             }
58              
59             has 'digest_callback' => (
60             is => 'ro',
61             lazy => 1,
62              
63             builder => sub {
64 11     11   336679 my ($self) = shift;
65             #my $sub = sub {
66             # my ($digestobj, $filename) = @_;
67             # open(my $fh, "<:raw", "$filename") or croak ("Cannot open $filename, $!");
68             # binmode($fh);
69             # my $digest = $digestobj->get_hash_string($fh);
70             # close $fh || croak("could not close file '$filename', $!");
71             # return $digest;
72             #};
73             my $sub = sub {
74 130     130   34389 my $digestobj = shift;
75 130         152 my $filename =shift;
76 130         123 my $opts = shift;
77 130   50     464 my $MMAP_MIN = $opts->{mmap_min} || 8000000;
78 130         1581 my $filesize = -s $filename;
79 130 50       4074 open(my $fh, "<:raw", "$filename") or croak ("Cannot open $filename, $!");
80 130         610 $self->{stats}->{files}->{"$filename"}->{size}= $filesize;
81 130         182 $self->{stats}->{size} += $filesize;
82 130         327 my $start_time = time();
83 130         119 my $digest;
84 130 50       213 if ($filesize < $MMAP_MIN ) {
    0          
85 130         230 return sysread_based_digest($digestobj, $fh, $filesize);
86             }
87             elsif ( $filesize < 1500000000) {
88 0         0 return mmap_based_digest($digestobj, $fh, $filesize);
89             }
90             else {
91 0         0 $digest = $digestobj->get_hash_string($fh);
92             }
93 0         0 my $finish_time = time();
94 0         0 $self->{stats}->{files}->{"$filename"}->{verify_time}= ($finish_time - $start_time);
95 0         0 $self->{stats}->{verify_time} += ($finish_time-$start_time);
96 0         0 close($fh);
97 0         0 return $digest;
98 11         95 };
99 11         48 return $sub;
100             }
101             );
102              
103             1;
104              
105             __END__