File Coverage

blib/lib/Sys/PageCache.pm
Criterion Covered Total %
statement 67 76 88.1
branch 24 38 63.1
condition n/a
subroutine 8 8 100.0
pod 2 2 100.0
total 101 124 81.4


line stmt bran cond sub pod time code
1             package Sys::PageCache;
2              
3 7     7   903322 use strict;
  7         25  
  7         264  
4 7     7   51 use warnings;
  7         19  
  7         243  
5 7     7   192 use 5.008001;
  7         36  
6 7     7   46 use Carp;
  7         161  
  7         502  
7 7     7   80 use base qw(Exporter);
  7         20  
  7         1271  
8             our @EXPORT = qw(page_size fincore fadvise
9             POSIX_FADV_NORMAL
10             POSIX_FADV_SEQUENTIAL
11             POSIX_FADV_RANDOM
12             POSIX_FADV_NOREUSE
13             POSIX_FADV_WILLNEED
14             POSIX_FADV_DONTNEED
15             );
16             our @EXPORT_OK = qw();
17              
18             our $VERSION = '0.05';
19              
20             our $MAX_CHUNK_SIZE = 512*1024*1024;
21              
22 7     7   4301 use POSIX;
  7         48769  
  7         52  
23              
24             require XSLoader;
25             XSLoader::load(__PACKAGE__, $VERSION);
26              
27             sub fincore {
28 13     13 1 35796 my($file, $offset, $length) = @_;
29              
30 13 100       63 if (! $offset) {
    50          
31 11         30 $offset = 0;
32             } elsif ($offset < 0) {
33 0         0 croak "offset must be >= 0";
34             } else {
35 2         19 my $pa_offset = $offset & ~(page_size() - 1);
36 2 50       13 if ($pa_offset != $offset) {
37 0         0 carp(sprintf "[WARN] offset must be a multiple of the page size so change %llu to %llu",
38             $offset,
39             $pa_offset,
40             );
41 0         0 $offset = $pa_offset;
42             }
43             }
44              
45 13         285 my $fsize = (stat $file)[7];
46 13 100       76 if (! $length) {
    100          
47 10         28 $length = $fsize;
48             } elsif ($length > $fsize - $offset) {
49 2         5 my $new_length = $fsize - $offset;
50 2         751 carp(sprintf "[WARN] fincore: length(%llu) is greater than file size(%llu) - offset(%llu). so use file size - offset (=%llu)",
51             $length,
52             $fsize,
53             $offset,
54             $new_length,
55             );
56 2         124 $length = $new_length;
57             }
58              
59 13 50       533 open my $fh, '<', $file or croak $!;
60 13         56 my $fd = fileno $fh;
61              
62 13         41 my($ret, $r, $e);
63 13         58 for (; $offset < $fsize; $offset += $MAX_CHUNK_SIZE, $length -= $MAX_CHUNK_SIZE) {
64 12 50       49 my $chunk_size = $length < $MAX_CHUNK_SIZE ? $length : $MAX_CHUNK_SIZE;
65             # warn "offset=$offset length=$length chunk_size=$chunk_size\n";
66 12         34 local $@;
67 12         46 $r = eval {
68 12         392 _fincore($fd, $offset, $chunk_size);
69             };
70 12 50       88 if ($@) {
71 0         0 chomp($e = $@);
72 0         0 carp $e;
73 0         0 close $fh;
74 0         0 return;
75             } else {
76 12         64 for my $k (keys %$r) {
77 36 100       182 next if $k eq 'page_size';
78 24         115 $ret->{$k} += $r->{$k};
79             }
80             }
81             }
82 13         153 close $fh;
83              
84 13         85 $ret->{page_size} = page_size();
85 13         44 $ret->{file_size} = $fsize;
86 13         145 $ret->{total_pages} = ceil($fsize / $ret->{page_size});
87              
88 13         125 return $ret;
89             }
90              
91             sub fadvise {
92 7     7 1 25039 my($file, $offset, $length, $advice) = @_;
93              
94 7 50       29 croak "missing advice" unless defined $advice;
95 7 50       37 croak "missing length" unless defined $length;
96 7 50       21 croak "missing offset" unless defined $offset;
97 7 50       25 croak "missing file" unless defined $file;
98              
99 7 50       27 croak "offset must be >= 0" if $offset < 0;
100              
101 7         170 my $fsize = (stat $file)[7];
102 7 100       40 if ($length > $fsize - $offset) {
103 3         8 my $new_length = $fsize - $offset;
104 3         621 carp(sprintf "[WARN] fadvise: length(%llu) is greater than file size(%llu) - offset(%llu). so use file size - offset (=%llu)",
105             $length,
106             $fsize,
107             $offset,
108             $new_length,
109             );
110 3         15 $length = $new_length;
111             }
112              
113 7 50       246 open my $fh, '<', $file or croak $!;
114 7         30 my $fd = fileno $fh;
115              
116 7         16 my($r, $e);
117             {
118 7         14 local $@;
  7         42  
119 7         19 $r = eval {
120 7         1166 _fadvise($fd, $offset, $length, $advice);
121             };
122 7 50       43 chomp($e = $@) if $@;
123             }
124 7         67 close $fh;
125              
126 7 50       33 if (defined $e) {
127 0         0 carp $e;
128 0         0 return;
129             }
130              
131 7 50       67 return $r == 0 ? 1 : ();
132             }
133              
134             1;
135             __END__