Lines 30-41
Koha::Cache - Handling caching of html and Objects for Koha
Link Here
|
30 |
=head1 DESCRIPTION |
30 |
=head1 DESCRIPTION |
31 |
|
31 |
|
32 |
Koha caching routines. This class provides two interfaces for cache access. |
32 |
Koha caching routines. This class provides two interfaces for cache access. |
33 |
The first, traditional interface provides the following functions: |
33 |
The first, traditional OO interface provides the following functions: |
34 |
|
34 |
|
35 |
=head1 FUNCTIONS |
35 |
=head1 FUNCTIONS |
36 |
|
36 |
|
37 |
=cut |
37 |
=cut |
38 |
|
|
|
39 |
use strict; |
38 |
use strict; |
40 |
use warnings; |
39 |
use warnings; |
41 |
use Carp; |
40 |
use Carp; |
Lines 47-52
use base qw(Class::Accessor);
Link Here
|
47 |
__PACKAGE__->mk_ro_accessors( |
46 |
__PACKAGE__->mk_ro_accessors( |
48 |
qw( cache memcached_cache fastmmap_cache memory_cache )); |
47 |
qw( cache memcached_cache fastmmap_cache memory_cache )); |
49 |
|
48 |
|
|
|
49 |
=head2 get_instance |
50 |
|
51 |
my $cache = Koha::Cache->get_instance(); |
52 |
|
53 |
This gets a shared instance of the cache, set up in a very default way. This is |
54 |
the recommended way to fetch a cache object. If possible, it'll be |
55 |
persistent across multiple instances. |
56 |
|
57 |
=cut |
58 |
|
59 |
our $singleton_cache; |
60 |
sub get_instance { |
61 |
my ($class) = @_; |
62 |
$singleton_cache = $class->new() unless $singleton_cache; |
63 |
return $singleton_cache; |
64 |
} |
65 |
|
50 |
=head2 new |
66 |
=head2 new |
51 |
|
67 |
|
52 |
Create a new Koha::Cache object. This is required for all cache-related functionality. |
68 |
Create a new Koha::Cache object. This is required for all cache-related functionality. |
Lines 92-106
sub new {
Link Here
|
92 |
} |
108 |
} |
93 |
} |
109 |
} |
94 |
|
110 |
|
95 |
# NOTE: The following five lines could be uncommented if we wanted to |
111 |
# Unless a default has already been picked, we go through in best-to- |
96 |
# fall back to any functioning cache. Commented out since this would |
112 |
# least-best order, looking for something we can use. fastmmap_cache |
97 |
# represent a change in behavior. |
113 |
# is excluded because it doesn't support expiry in a useful way. |
98 |
# |
114 |
unless ( defined( $self->{'cache'} ) ) { |
99 |
#unless (defined($self->{'cache'})) { |
115 |
foreach my $cachemember (qw(memcached_cache memory_cache )) { |
100 |
# foreach my $cachemember (qw(memory_cache fastmmap_cache memcached_cache)) { |
116 |
if ( defined( $self->{$cachemember} ) ) { |
101 |
# $self->{'cache'} = $self->{$cachemember} if (defined($self->{$cachemember})); |
117 |
$self->{'cache'} = $self->{$cachemember}; |
102 |
# } |
118 |
last; |
103 |
#} |
119 |
} |
|
|
120 |
} |
121 |
} |
122 |
|
123 |
$ENV{DEBUG} && carp "Selected caching system: " . ($self->{'cache'} // 'none'); |
104 |
|
124 |
|
105 |
return |
125 |
return |
106 |
bless $self, |
126 |
bless $self, |
Lines 112-131
sub _initialize_memcached {
Link Here
|
112 |
my @servers = |
132 |
my @servers = |
113 |
split /,/, $self->{'cache_servers'} |
133 |
split /,/, $self->{'cache_servers'} |
114 |
? $self->{'cache_servers'} |
134 |
? $self->{'cache_servers'} |
115 |
: $ENV{MEMCACHED_SERVERS}; |
135 |
: ($ENV{MEMCACHED_SERVERS} || ''); |
|
|
136 |
return if !@servers; |
116 |
|
137 |
|
117 |
$ENV{DEBUG} |
138 |
$ENV{DEBUG} |
118 |
&& carp "Memcached server settings: " |
139 |
&& carp "Memcached server settings: " |
119 |
. join( ', ', @servers ) |
140 |
. join( ', ', @servers ) |
120 |
. " with " |
141 |
. " with " |
121 |
. $self->{'namespace'}; |
142 |
. $self->{'namespace'}; |
122 |
$self->{'memcached_cache'} = Cache::Memcached::Fast->new( |
143 |
# Cache::Memcached::Fast doesn't allow a default expire time to be set |
|
|
144 |
# so we force it on setting. |
145 |
my $memcached = Cache::Memcached::Fast->new( |
123 |
{ |
146 |
{ |
124 |
servers => \@servers, |
147 |
servers => \@servers, |
125 |
compress_threshold => 10_000, |
148 |
compress_threshold => 10_000, |
126 |
namespace => $self->{'namespace'}, |
149 |
namespace => $self->{'namespace'}, |
|
|
150 |
utf8 => 1, |
127 |
} |
151 |
} |
128 |
); |
152 |
); |
|
|
153 |
# Ensure we can actually talk to the memcached server |
154 |
my $ismemcached = $memcached->set('ismemcached','1'); |
155 |
return $self unless $ismemcached; |
156 |
$self->{'memcached_cache'} = $memcached; |
129 |
return $self; |
157 |
return $self; |
130 |
} |
158 |
} |
131 |
|
159 |
|
Lines 143-190
sub _initialize_fastmmap {
Link Here
|
143 |
sub _initialize_memory { |
171 |
sub _initialize_memory { |
144 |
my ($self) = @_; |
172 |
my ($self) = @_; |
145 |
|
173 |
|
146 |
$self->{'memory_cache'} = Cache::Memory->new( |
174 |
# Default cache time for memory is _always_ short unless it's specially |
|
|
175 |
# defined, to allow it to work reliably in a persistent environment. |
176 |
my $cache = Cache::Memory->new( |
147 |
'namespace' => $self->{'namespace'}, |
177 |
'namespace' => $self->{'namespace'}, |
148 |
'default_expires' => $self->{'timeout'} |
178 |
'default_expires' => "$self->{'timeout'} sec" || "10 sec", |
149 |
); |
179 |
); |
|
|
180 |
$self->{'memory_cache'} = $cache; |
181 |
# Memory cache can't handle complex types for some reason, so we use its |
182 |
# freeze and thaw functions. |
183 |
$self->{ref($cache) . '_set'} = sub { |
184 |
my ($key, $val, $exp) = @_; |
185 |
# Refer to set_expiry in Cache::Entry for why we do this 'sec' thing. |
186 |
$exp = "$exp sec" if defined $exp; |
187 |
# Because we need to use freeze, it must be a reference type. |
188 |
$cache->freeze($key, [$val], $exp); |
189 |
}; |
190 |
$self->{ref($cache) . '_get'} = sub { |
191 |
my $res = $cache->thaw(shift); |
192 |
return unless defined $res; |
193 |
return $res->[0]; |
194 |
}; |
150 |
return $self; |
195 |
return $self; |
151 |
} |
196 |
} |
152 |
|
197 |
|
153 |
=head2 is_cache_active |
198 |
=head2 is_cache_active |
154 |
|
199 |
|
155 |
Routine that checks whether or not a caching system has been selected. This is |
200 |
Routine that checks whether or not a default caching method is active on this |
156 |
not an instance method. |
201 |
object. |
157 |
|
202 |
|
158 |
=cut |
203 |
=cut |
159 |
|
204 |
|
160 |
sub is_cache_active { |
205 |
sub is_cache_active { |
161 |
return $ENV{CACHING_SYSTEM} ? '1' : ''; |
206 |
my $self = shift; |
|
|
207 |
return $self->{'cache'} ? 1 : 0; |
162 |
} |
208 |
} |
163 |
|
209 |
|
164 |
=head2 set_in_cache |
210 |
=head2 set_in_cache |
165 |
|
211 |
|
166 |
$cache->set_in_cache($key, $value, [$expiry]); |
212 |
$cache->set_in_cache($key, $value, [$options]); |
|
|
213 |
|
214 |
Save a value to the specified key in the cache. A hashref of options may be |
215 |
specified. |
167 |
|
216 |
|
168 |
Save a value to the specified key in the default cache, optionally with a |
217 |
The possible options are: |
169 |
particular expiry. |
218 |
|
|
|
219 |
=over |
220 |
|
221 |
=item expiry |
222 |
|
223 |
Expiry time of this cached entry in seconds. |
224 |
|
225 |
=item deepcopy |
226 |
|
227 |
If set, this will perform a deep copy of the item when it's retrieved. This |
228 |
means that it'll be safe if something later modifies the result of the |
229 |
function. Will be ignored in situations where the same behaviour comes from |
230 |
the caching layer anyway. |
231 |
|
232 |
=item cache |
233 |
|
234 |
The cache object to use if you want to provide your own. It should be an |
235 |
instance of C<Cache::*> and follow the same interface as L<Cache::Memcache>. |
170 |
|
236 |
|
171 |
=cut |
237 |
=cut |
172 |
|
238 |
|
173 |
sub set_in_cache { |
239 |
sub set_in_cache { |
174 |
my ( $self, $key, $value, $expiry, $cache ) = @_; |
240 |
my ( $self, $key, $value, $options, $_cache) = @_; |
175 |
$cache ||= 'cache'; |
241 |
# This is a bit of a hack to support the old API in case things still use it |
|
|
242 |
if (defined $options && (ref($options) ne 'HASH')) { |
243 |
my $new_options; |
244 |
$new_options->{expiry} = $options; |
245 |
$new_options->{cache} = $_cache if defined $_cache; |
246 |
$options = $new_options; |
247 |
} |
248 |
|
249 |
# the key mustn't contain whitespace (or control characters) for memcache |
250 |
# but shouldn't be any harm in applying it globally. |
251 |
$key =~ s/[\x00-\x20]/_/g; |
252 |
|
253 |
my $cache = $options->{cache} || 'cache'; |
176 |
croak "No key" unless $key; |
254 |
croak "No key" unless $key; |
177 |
$ENV{DEBUG} && carp "set_in_cache for $key"; |
255 |
$ENV{DEBUG} && carp "set_in_cache for $key"; |
178 |
|
256 |
|
179 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
257 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
180 |
if ( defined $expiry ) { |
258 |
my $expiry = $options->{expiry}; |
181 |
if ( ref( $self->{$cache} ) eq 'Cache::Memory' ) { |
259 |
$expiry //= $self->{timeout}; |
182 |
$expiry = "$expiry sec"; |
260 |
my $set_sub = $self->{ref($self->{$cache}) . "_set"}; |
183 |
} |
261 |
# We consider an expiry of 0 to be inifinite |
184 |
return $self->{$cache}->set( $key, $value, $expiry ); |
262 |
if ( $expiry ) { |
|
|
263 |
return $set_sub |
264 |
? $set_sub->( $key, $value, $expiry ) |
265 |
: $self->{$cache}->set( $key, $value, $expiry ); |
185 |
} |
266 |
} |
186 |
else { |
267 |
else { |
187 |
return $self->{$cache}->set( $key, $value ); |
268 |
return $set_sub |
|
|
269 |
? $set_sub->( $key, $value ) |
270 |
: $self->{$cache}->set( $key, $value ); |
188 |
} |
271 |
} |
189 |
} |
272 |
} |
190 |
|
273 |
|
Lines 198-208
Retrieve the value stored under the specified key in the default cache.
Link Here
|
198 |
|
281 |
|
199 |
sub get_from_cache { |
282 |
sub get_from_cache { |
200 |
my ( $self, $key, $cache ) = @_; |
283 |
my ( $self, $key, $cache ) = @_; |
|
|
284 |
$key =~ s/[\x00-\x20]/_/g; |
201 |
$cache ||= 'cache'; |
285 |
$cache ||= 'cache'; |
202 |
croak "No key" unless $key; |
286 |
croak "No key" unless $key; |
203 |
$ENV{DEBUG} && carp "get_from_cache for $key"; |
287 |
$ENV{DEBUG} && carp "get_from_cache for $key"; |
204 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
288 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
205 |
return $self->{$cache}->get($key); |
289 |
my $get_sub = $self->{ref($self->{$cache}) . "_get"}; |
|
|
290 |
return $get_sub ? $get_sub->($key) : $self->{$cache}->get($key); |
206 |
} |
291 |
} |
207 |
|
292 |
|
208 |
=head2 clear_from_cache |
293 |
=head2 clear_from_cache |
Lines 215-225
Remove the value identified by the specified key from the default cache.
Link Here
|
215 |
|
300 |
|
216 |
sub clear_from_cache { |
301 |
sub clear_from_cache { |
217 |
my ( $self, $key, $cache ) = @_; |
302 |
my ( $self, $key, $cache ) = @_; |
|
|
303 |
$key =~ s/[\x00-\x20]/_/g; |
218 |
$cache ||= 'cache'; |
304 |
$cache ||= 'cache'; |
219 |
croak "No key" unless $key; |
305 |
croak "No key" unless $key; |
220 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
306 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
221 |
return $self->{$cache}->delete($key) |
307 |
return $self->{$cache}->delete($key) |
222 |
if ( ref( $self->{$cache} ) eq 'Cache::Memcached::Fast' ); |
308 |
if ( ref( $self->{$cache} ) =~ m'^Cache::Memcached' ); |
223 |
return $self->{$cache}->remove($key); |
309 |
return $self->{$cache}->remove($key); |
224 |
} |
310 |
} |
225 |
|
311 |
|
Lines 236-242
sub flush_all {
Link Here
|
236 |
$cache ||= 'cache'; |
322 |
$cache ||= 'cache'; |
237 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
323 |
return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ ); |
238 |
return $self->{$cache}->flush_all() |
324 |
return $self->{$cache}->flush_all() |
239 |
if ( ref( $self->{$cache} ) eq 'Cache::Memcached::Fast' ); |
325 |
if ( ref( $self->{$cache} ) =~ m'^Cache::Memcached' ); |
240 |
return $self->{$cache}->clear(); |
326 |
return $self->{$cache}->clear(); |
241 |
} |
327 |
} |
242 |
|
328 |
|