line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package File::DataClass::Cache; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
68
|
use 5.01; |
|
3
|
|
|
|
|
8
|
|
4
|
3
|
|
|
3
|
|
11
|
use namespace::autoclean; |
|
3
|
|
|
|
|
1
|
|
|
3
|
|
|
|
|
21
|
|
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
140
|
use File::DataClass::Constants qw( FALSE NUL SPC TRUE ); |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
183
|
|
7
|
3
|
|
|
3
|
|
12
|
use File::DataClass::Functions qw( merge_attributes throw ); |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
140
|
|
8
|
3
|
|
|
|
|
32
|
use File::DataClass::Types qw( Bool Cache ClassName HashRef |
9
|
3
|
|
|
3
|
|
999
|
LoadableClass Object Str ); |
|
3
|
|
|
|
|
8
|
|
10
|
3
|
|
|
3
|
|
5534
|
use Storable qw( freeze ); |
|
3
|
|
|
|
|
7480
|
|
|
3
|
|
|
|
|
183
|
|
11
|
3
|
|
|
3
|
|
18
|
use Try::Tiny; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
135
|
|
12
|
3
|
|
|
3
|
|
11
|
use Moo; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
24
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Public attributes |
15
|
|
|
|
|
|
|
has 'cache' => is => 'lazy', isa => Object, builder => sub { |
16
|
3
|
|
|
3
|
|
74
|
$_[ 0 ]->cache_class->new( %{ $_[ 0 ]->cache_attributes } ) }; |
|
3
|
|
|
|
|
8762
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
has 'cache_attributes' => is => 'ro', isa => HashRef, required => TRUE; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
has 'cache_class' => is => 'lazy', isa => LoadableClass, |
21
|
|
|
|
|
|
|
default => 'Cache::FastMmap'; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has 'log' => is => 'ro', isa => Object, required => TRUE; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Private attributes |
26
|
|
|
|
|
|
|
has '_mtimes_key' => is => 'ro', isa => Str, default => '_mtimes'; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Construction |
29
|
|
|
|
|
|
|
around 'BUILDARGS' => sub { |
30
|
|
|
|
|
|
|
my ($orig, $class, @args) = @_; my $attr = $orig->( $class, @args ); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$attr->{cache_attributes} //= {}; my $cache_class; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
$cache_class = delete $attr->{cache_attributes}->{cache_class} |
35
|
|
|
|
|
|
|
and $attr->{cache_class} = $cache_class; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
my $builder = delete $attr->{builder} or return $attr; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
merge_attributes $attr, $builder, [ 'log' ]; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
return $attr; |
42
|
|
|
|
|
|
|
}; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Private methods |
45
|
|
|
|
|
|
|
my $_get_key_and_newest = sub { |
46
|
|
|
|
|
|
|
my ($self, $paths) = @_; my $newest = 0; my $is_valid = TRUE; my $key; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
for my $path (grep { defined && length "${_}" } @{ $paths }) { |
49
|
|
|
|
|
|
|
my $mtime = $self->get_mtime( "${path}" ) or $is_valid = FALSE; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
($mtime and $path->exists and $mtime == $path->stat->{mtime}) |
52
|
|
|
|
|
|
|
or $is_valid = FALSE; |
53
|
|
|
|
|
|
|
$mtime and $mtime > $newest and $newest = $mtime; |
54
|
|
|
|
|
|
|
$key .= $key ? "~${path}" : "${path}"; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
return ($key, $is_valid ? $newest : undef); |
58
|
|
|
|
|
|
|
}; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Public methods |
61
|
|
|
|
|
|
|
sub get { |
62
|
75
|
|
|
75
|
1
|
2159
|
my ($self, $key) = @_; $key .= NUL; |
|
75
|
|
|
|
|
221
|
|
63
|
|
|
|
|
|
|
|
64
|
75
|
100
|
|
|
|
2236
|
my $cached = $key ? $self->cache->get( $key ) : FALSE; |
65
|
|
|
|
|
|
|
|
66
|
75
|
100
|
|
|
|
56327
|
$cached and return ($cached->{data}, $cached->{meta}); |
67
|
|
|
|
|
|
|
|
68
|
29
|
|
|
|
|
725
|
return (undef, { mtime => undef }); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub get_by_paths { |
72
|
2
|
|
|
2
|
1
|
80
|
my ($self, $paths) = @_; |
73
|
2
|
|
|
|
|
8
|
my ($key, $newest) = $self->$_get_key_and_newest( $paths ); |
74
|
|
|
|
|
|
|
|
75
|
2
|
|
|
|
|
8
|
return ($self->get( $key ), $newest); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub get_mtime { |
79
|
10
|
100
|
|
10
|
1
|
1229
|
my ($self, $k) = @_; $k or return; |
|
10
|
|
|
|
|
24
|
|
80
|
|
|
|
|
|
|
|
81
|
9
|
100
|
|
|
|
113
|
my $mtimes = $self->cache->get( $self->_mtimes_key ) or return; |
82
|
|
|
|
|
|
|
|
83
|
8
|
|
|
|
|
444
|
return $mtimes->{ $k }; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub remove { |
87
|
24
|
100
|
|
24
|
1
|
716
|
my ($self, $key) = @_; defined $key or return; |
|
24
|
|
|
|
|
67
|
|
88
|
|
|
|
|
|
|
|
89
|
23
|
|
|
|
|
292
|
$self->cache->remove( $key ); $self->set_mtime( $key, undef ); |
|
23
|
|
|
|
|
829
|
|
90
|
|
|
|
|
|
|
|
91
|
23
|
|
|
|
|
2090
|
return; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub set { |
95
|
28
|
|
100
|
28
|
1
|
1172
|
my ($self, $key, $data, $meta) = @_; $meta //= { mtime => undef }; |
|
28
|
|
|
|
|
74
|
|
96
|
|
|
|
|
|
|
|
97
|
28
|
|
|
|
|
63
|
my $val = { data => $data, meta => $meta }; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
try { |
100
|
28
|
100
|
|
28
|
|
876
|
$key eq $self->_mtimes_key and throw 'key not allowed'; |
101
|
27
|
50
|
|
|
|
861
|
$self->cache->set( $key, $val ) or throw 'set operation returned false'; |
102
|
27
|
|
|
|
|
1286
|
$self->set_mtime( $key, $meta->{mtime} ); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
catch { |
105
|
1
|
|
|
1
|
|
1364
|
my $len = length( $key ) + length( freeze $val ); |
106
|
|
|
|
|
|
|
|
107
|
1
|
|
|
|
|
36
|
$self->log->error( "Cache key ${key}(${len}) set failed: ${_}" ); |
108
|
28
|
|
|
|
|
246
|
}; |
109
|
|
|
|
|
|
|
|
110
|
28
|
|
|
|
|
2070
|
return ($data, $meta); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub set_by_paths { |
114
|
2
|
|
|
2
|
1
|
6
|
my ($self, $paths, $data, $meta) = @_; |
115
|
|
|
|
|
|
|
|
116
|
2
|
|
|
|
|
5
|
my ($key, $newest) = $self->$_get_key_and_newest( $paths ); |
117
|
|
|
|
|
|
|
|
118
|
2
|
|
|
|
|
4
|
$meta->{mtime} = $newest; |
119
|
|
|
|
|
|
|
|
120
|
2
|
|
|
|
|
7
|
return $self->set( $key, $data, $meta ); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub set_mtime { |
124
|
50
|
|
|
50
|
1
|
77
|
my ($self, $k, $v) = @_; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
return $self->cache->get_and_set( $self->_mtimes_key, sub { |
127
|
50
|
|
|
50
|
|
2677
|
my (undef, $mtimes) = @_; |
128
|
|
|
|
|
|
|
|
129
|
50
|
100
|
|
|
|
91
|
if (defined $v) { $mtimes->{ $k } = $v } else { delete $mtimes->{ $k } } |
|
25
|
|
|
|
|
68
|
|
|
25
|
|
|
|
|
71
|
|
130
|
|
|
|
|
|
|
|
131
|
50
|
|
|
|
|
910
|
return $mtimes; |
132
|
50
|
|
|
|
|
694
|
} ); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
1; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
__END__ |