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