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   678983 use strict;
  7         65  
  7         237  
4 7     7   39 use warnings;
  7         14  
  7         174  
5 7     7   130 use 5.008001;
  7         26  
6 7     7   32 use Carp;
  7         13  
  7         396  
7 7     7   42 use base qw(Exporter);
  7         12  
  7         1341  
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.06';
19              
20             our $MAX_CHUNK_SIZE = 512*1024*1024;
21              
22 7     7   3964 use POSIX qw(ceil);
  7         44509  
  7         37  
23              
24             require XSLoader;
25             XSLoader::load(__PACKAGE__, $VERSION);
26              
27             sub fincore {
28 13     13 1 25299 my($file, $offset, $length) = @_;
29              
30 13 100       49 if (! $offset) {
    50          
31 11         26 $offset = 0;
32             } elsif ($offset < 0) {
33 0         0 croak "offset must be >= 0";
34             } else {
35 2         18 my $pa_offset = $offset & ~(page_size() - 1);
36 2 50       9 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         236 my $fsize = (stat $file)[7];
46 13 100       74 if (! $length) {
    100          
47 10         19 $length = $fsize;
48             } elsif ($length > $fsize - $offset) {
49 2         4 my $new_length = $fsize - $offset;
50 2         342 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         13 $length = $new_length;
57             }
58              
59 13 50       849 open my $fh, '<', $file or croak $!;
60 13         50 my $fd = fileno $fh;
61              
62 13         25 my($ret, $r, $e);
63 13         81 for (; $offset < $fsize; $offset += $MAX_CHUNK_SIZE, $length -= $MAX_CHUNK_SIZE) {
64 13 50       43 my $chunk_size = $length < $MAX_CHUNK_SIZE ? $length : $MAX_CHUNK_SIZE;
65             # warn "offset=$offset length=$length chunk_size=$chunk_size\n";
66 13         48 local $@;
67 13         42 $r = eval {
68 13         408 _fincore($fd, $offset, $chunk_size);
69             };
70 13 50       52 if ($@) {
71 0         0 chomp($e = $@);
72 0         0 carp $e;
73 0         0 close $fh;
74 0         0 return;
75             } else {
76 13         65 for my $k (keys %$r) {
77 39 100       106 next if $k eq 'page_size';
78 26         89 $ret->{$k} += $r->{$k};
79             }
80             }
81             }
82 13         131 close $fh;
83              
84 13         73 $ret->{page_size} = page_size();
85 13         29 $ret->{file_size} = $fsize;
86 13         114 $ret->{total_pages} = ceil($fsize / $ret->{page_size});
87              
88 13         105 return $ret;
89             }
90              
91             sub fadvise {
92 7     7 1 18848 my($file, $offset, $length, $advice) = @_;
93              
94 7 50       27 croak "missing advice" unless defined $advice;
95 7 50       18 croak "missing length" unless defined $length;
96 7 50       17 croak "missing offset" unless defined $offset;
97 7 50       30 croak "missing file" unless defined $file;
98              
99 7 50       21 croak "offset must be >= 0" if $offset < 0;
100              
101 7         111 my $fsize = (stat $file)[7];
102 7 100       41 if ($length > $fsize - $offset) {
103 3         8 my $new_length = $fsize - $offset;
104 3         600 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         34 $length = $new_length;
111             }
112              
113 7 50       281 open my $fh, '<', $file or croak $!;
114 7         35 my $fd = fileno $fh;
115              
116 7         13 my($r, $e);
117             {
118 7         41 local $@;
  7         19  
119 7         17 $r = eval {
120 7         31554 _fadvise($fd, $offset, $length, $advice);
121             };
122 7 50       70 chomp($e = $@) if $@;
123             }
124 7         89 close $fh;
125              
126 7 50       33 if (defined $e) {
127 0         0 carp $e;
128 0         0 return;
129             }
130              
131 7 50       84 return $r == 0 ? 1 : ();
132             }
133              
134             1;
135             __END__