line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CHI; |
2
|
|
|
|
|
|
|
$CHI::VERSION = '0.59'; |
3
|
1
|
|
|
1
|
|
15327
|
use 5.006; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
4
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
74
|
|
5
|
1
|
|
|
1
|
|
404
|
use CHI::Stats; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
32
|
|
6
|
1
|
|
|
1
|
|
440
|
use String::RewritePrefix; |
|
1
|
|
|
|
|
10413
|
|
|
1
|
|
|
|
|
6
|
|
7
|
1
|
|
|
1
|
|
133
|
use Module::Runtime qw(require_module); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
7
|
|
8
|
1
|
|
|
1
|
|
519
|
use Moo::Role (); |
|
1
|
|
|
|
|
19510
|
|
|
1
|
|
|
|
|
37
|
|
9
|
1
|
|
|
1
|
|
10
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
42
|
|
10
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
179
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my ( %final_class_seen, %memoized_cache_objects, %stats ); |
13
|
|
|
|
|
|
|
my %valid_config_keys = |
14
|
|
|
|
|
|
|
map { ( $_, 1 ) } qw(defaults memoize_cache_objects namespace storage); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub logger { |
17
|
0
|
|
|
0
|
0
|
0
|
warn |
18
|
|
|
|
|
|
|
"CHI now uses Log::Any for logging - see Log::Any documentation for details"; |
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub config { |
22
|
1
|
|
|
1
|
1
|
2
|
my $class = shift; |
23
|
1
|
50
|
|
|
|
5
|
$class->_set_config(@_) if @_; |
24
|
1
|
|
|
|
|
6
|
return $class->_get_config(); |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub _set_config { |
28
|
1
|
|
|
1
|
|
1
|
my ( $class, $config ) = @_; |
29
|
1
|
50
|
|
|
|
4
|
if ( my @bad_keys = grep { !$valid_config_keys{$_} } keys(%$config) ) { |
|
0
|
|
|
|
|
0
|
|
30
|
0
|
|
|
|
|
0
|
croak "unknown keys in config hash: " . join( ", ", @bad_keys ); |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# set class specific configuration |
34
|
1
|
|
|
1
|
|
31
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
35
|
1
|
|
|
1
|
|
4
|
no warnings 'redefine'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
106
|
|
36
|
1
|
|
|
1
|
|
3
|
*{"$class\::_get_config"} = sub { $config }; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
484
|
|
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
1
|
|
|
1
|
|
4
|
BEGIN { __PACKAGE__->config( {} ) } |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub memoized_cache_objects { |
42
|
0
|
|
|
0
|
0
|
|
my ($class) = @_; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Each CHI root class gets its hash of memoized objects |
45
|
|
|
|
|
|
|
# |
46
|
0
|
|
0
|
|
|
|
$memoized_cache_objects{$class} ||= {}; |
47
|
0
|
|
|
|
|
|
return $memoized_cache_objects{$class}; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub clear_memoized_cache_objects { |
51
|
0
|
|
|
0
|
0
|
|
my ($class) = @_; |
52
|
|
|
|
|
|
|
|
53
|
0
|
|
|
|
|
|
$memoized_cache_objects{$class} = {}; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub stats { |
57
|
0
|
|
|
0
|
0
|
|
my ($class) = @_; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Each CHI root class gets its own stats object |
60
|
|
|
|
|
|
|
# |
61
|
0
|
|
0
|
|
|
|
$stats{$class} ||= CHI::Stats->new( chi_root_class => $class ); |
62
|
0
|
|
|
|
|
|
return $stats{$class}; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub new { |
66
|
0
|
|
|
0
|
1
|
|
my ( $chi_root_class, %params ) = @_; |
67
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
my $config = $chi_root_class->config; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Cache object memoization: See if cache object with these parameters |
71
|
|
|
|
|
|
|
# has already been created, and return it if so. Only for parameters |
72
|
|
|
|
|
|
|
# with 0 or 1 keys. |
73
|
|
|
|
|
|
|
# |
74
|
0
|
|
|
|
|
|
my ( $cache_object_key, $cache_objects ); |
75
|
0
|
0
|
0
|
|
|
|
if ( $config->{memoize_cache_objects} && keys(%params) <= 1 ) { |
76
|
0
|
|
|
|
|
|
$cache_object_key = join chr(28), %params; |
77
|
0
|
|
|
|
|
|
$cache_objects = $chi_root_class->memoized_cache_objects; |
78
|
0
|
0
|
|
|
|
|
if ( my $cache_object = $cache_objects->{$cache_object_key} ) { |
79
|
0
|
|
|
|
|
|
return $cache_object; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Gather defaults |
84
|
|
|
|
|
|
|
# |
85
|
0
|
|
0
|
|
|
|
my $core_defaults = $config->{defaults} || {}; |
86
|
0
|
|
0
|
|
|
|
my $namespace_defaults = |
87
|
|
|
|
|
|
|
$config->{namespace}->{ $params{namespace} || 'Default' } || {}; |
88
|
0
|
|
0
|
|
|
|
my $storage = |
89
|
|
|
|
|
|
|
$params{storage} |
90
|
|
|
|
|
|
|
|| $namespace_defaults->{storage} |
91
|
|
|
|
|
|
|
|| $core_defaults->{storage}; |
92
|
0
|
|
|
|
|
|
my $storage_defaults = {}; |
93
|
0
|
0
|
|
|
|
|
if ( defined($storage) ) { |
94
|
0
|
0
|
|
|
|
|
$storage_defaults = $config->{storage}->{$storage} |
95
|
|
|
|
|
|
|
or croak "no config for storage type '$storage'"; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# Combine passed params with defaults |
99
|
|
|
|
|
|
|
# |
100
|
|
|
|
|
|
|
%params = |
101
|
0
|
|
|
|
|
|
( %$core_defaults, %$storage_defaults, %$namespace_defaults, %params ); |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Get driver class from driver or driver_class parameters |
104
|
|
|
|
|
|
|
# |
105
|
0
|
|
|
|
|
|
my $driver_class; |
106
|
0
|
0
|
|
|
|
|
if ( my $driver = delete( $params{driver} ) ) { |
107
|
0
|
|
|
|
|
|
($driver_class) = |
108
|
|
|
|
|
|
|
String::RewritePrefix->rewrite( { '' => 'CHI::Driver::', '+' => '' }, |
109
|
|
|
|
|
|
|
$driver ); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
else { |
112
|
0
|
|
|
|
|
|
$driver_class = delete( $params{driver_class} ); |
113
|
|
|
|
|
|
|
} |
114
|
0
|
0
|
|
|
|
|
croak "missing required param 'driver' or 'driver_class'" |
115
|
|
|
|
|
|
|
unless defined $driver_class; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Load driver class if it hasn't been loaded or defined in-line already |
118
|
|
|
|
|
|
|
# |
119
|
0
|
0
|
|
|
|
|
unless ( $driver_class->can('fetch') ) { |
120
|
0
|
|
|
|
|
|
require_module($driver_class); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Select roles depending on presence of certain arguments. Everyone gets |
124
|
|
|
|
|
|
|
# the Universal role. Accept both 'roles' and 'traits' for backwards |
125
|
|
|
|
|
|
|
# compatibility. Add CHI::Driver::Role:: unless prefixed with '+'. |
126
|
|
|
|
|
|
|
# |
127
|
0
|
|
|
|
|
|
my @roles = ('Universal'); |
128
|
0
|
|
|
|
|
|
foreach my $param_name (qw(roles traits)) { |
129
|
0
|
0
|
|
|
|
|
if ( exists( $params{$param_name} ) ) { |
130
|
0
|
|
|
|
|
|
push( @roles, @{ delete( $params{$param_name} ) } ); |
|
0
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
0
|
0
|
0
|
|
|
|
if ( exists( $params{max_size} ) || exists( $params{is_size_aware} ) ) { |
134
|
0
|
|
|
|
|
|
push( @roles, 'IsSizeAware' ); |
135
|
|
|
|
|
|
|
} |
136
|
0
|
0
|
0
|
|
|
|
if ( exists( $params{l1_cache} ) || exists( $params{mirror_cache} ) ) { |
137
|
0
|
|
|
|
|
|
push( @roles, 'HasSubcaches' ); |
138
|
|
|
|
|
|
|
} |
139
|
0
|
0
|
|
|
|
|
if ( $params{is_subcache} ) { |
140
|
0
|
|
|
|
|
|
push( @roles, 'IsSubcache' ); |
141
|
|
|
|
|
|
|
} |
142
|
0
|
|
|
|
|
|
@roles = String::RewritePrefix->rewrite( |
143
|
|
|
|
|
|
|
{ '' => 'CHI::Driver::Role::', '+' => '' }, @roles ); |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# Select a final class based on the driver class and roles, creating it |
146
|
|
|
|
|
|
|
# if necessary - adapted from MooseX::Traits |
147
|
|
|
|
|
|
|
# |
148
|
0
|
|
|
|
|
|
my $final_class = |
149
|
|
|
|
|
|
|
Moo::Role->create_class_with_roles( $driver_class, @roles ); |
150
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
|
my $cache_object = $final_class->new( |
152
|
|
|
|
|
|
|
chi_root_class => $chi_root_class, |
153
|
|
|
|
|
|
|
driver_class => $driver_class, |
154
|
|
|
|
|
|
|
%params |
155
|
|
|
|
|
|
|
); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Memoize if appropriate |
158
|
|
|
|
|
|
|
# |
159
|
0
|
0
|
|
|
|
|
if ($cache_object_key) { |
160
|
0
|
|
|
|
|
|
$cache_objects->{$cache_object_key} = $cache_object; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
return $cache_object; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
1; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
__END__ |