3 # Copyright 2009 Chris Cormack and The Koha Dev Team
4 # Parts copyright 2012-2013 C & P Bibliography Services
6 # This file is part of Koha.
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License along
18 # with Koha; if not, write to the Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 Koha::Cache - Handling caching of html and Objects for Koha
28 my $cache = Koha::Cache->new({cache_type => $cache_type, %params});
32 Koha caching routines. This class provides two interfaces for cache access.
33 The first, traditional interface provides the following functions:
42 use Module
::Load
::Conditional
qw(can_load);
43 use Koha
::Cache
::Object
;
45 use base
qw(Class::Accessor);
47 __PACKAGE__
->mk_ro_accessors(
48 qw( cache memcached_cache fastmmap_cache memory_cache ));
52 Create a new Koha::Cache object. This is required for all cache-related functionality.
57 my ( $class, $self ) = @_;
58 $self->{'default_type'} =
60 || $ENV{CACHING_SYSTEM
}
63 $ENV{DEBUG
} && carp
"Default caching system: $self->{'default_type'}";
65 $self->{'timeout'} ||= 0;
66 $self->{'namespace'} ||= $ENV{MEMCACHED_NAMESPACE
} || 'koha';
68 if ( can_load
( modules
=> { 'Cache::Memcached::Fast' => undef } ) ) {
69 _initialize_memcached
($self);
70 if ( $self->{'default_type'} eq 'memcached'
71 && defined( $self->{'memcached_cache'} ) )
73 $self->{'cache'} = $self->{'memcached_cache'};
77 if ( can_load
( modules
=> { 'Cache::FastMmap' => undef } ) ) {
78 _initialize_fastmmap
($self);
79 if ( $self->{'default_type'} eq 'fastmmap'
80 && defined( $self->{'fastmmap_cache'} ) )
82 $self->{'cache'} = $self->{'fastmmap_cache'};
86 if ( can_load
( modules
=> { 'Cache::Memory' => undef } ) ) {
87 _initialize_memory
($self);
88 if ( $self->{'default_type'} eq 'memory'
89 && defined( $self->{'memory_cache'} ) )
91 $self->{'cache'} = $self->{'memory_cache'};
95 # NOTE: The following five lines could be uncommented if we wanted to
96 # fall back to any functioning cache. Commented out since this would
97 # represent a change in behavior.
99 #unless (defined($self->{'cache'})) {
100 # foreach my $cachemember (qw(memory_cache fastmmap_cache memcached_cache)) {
101 # $self->{'cache'} = $self->{$cachemember} if (defined($self->{$cachemember}));
110 sub _initialize_memcached
{
113 split /,/, $self->{'cache_servers'}
114 ?
$self->{'cache_servers'}
115 : $ENV{MEMCACHED_SERVERS
};
118 && carp
"Memcached server settings: "
119 . join( ', ', @servers )
121 . $self->{'namespace'};
122 $self->{'memcached_cache'} = Cache
::Memcached
::Fast
->new(
124 servers
=> \
@servers,
125 compress_threshold
=> 10_000
,
126 namespace
=> $self->{'namespace'},
132 sub _initialize_fastmmap
{
135 $self->{'fastmmap_cache'} = Cache
::FastMmap
->new(
136 'share_file' => "/tmp/sharefile-koha-$self->{'namespace'}",
137 'expire_time' => $self->{'timeout'},
138 'unlink_on_exit' => 0,
143 sub _initialize_memory
{
146 $self->{'memory_cache'} = Cache
::Memory
->new(
147 'namespace' => $self->{'namespace'},
148 'default_expires' => $self->{'timeout'}
153 =head2 is_cache_active
155 Routine that checks whether or not a caching system has been selected. This is
156 not an instance method.
160 sub is_cache_active
{
161 return $ENV{CACHING_SYSTEM
} ?
'1' : '';
166 $cache->set_in_cache($key, $value, [$expiry]);
168 Save a value to the specified key in the default cache, optionally with a
174 my ( $self, $key, $value, $expiry, $cache ) = @_;
176 croak
"No key" unless $key;
177 $ENV{DEBUG
} && carp
"set_in_cache for $key";
179 return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ );
180 if ( defined $expiry ) {
181 if ( ref( $self->{$cache} ) eq 'Cache::Memory' ) {
182 $expiry = "$expiry sec";
184 return $self->{$cache}->set( $key, $value, $expiry );
187 return $self->{$cache}->set( $key, $value );
191 =head2 get_from_cache
193 my $value = $cache->get_from_cache($key);
195 Retrieve the value stored under the specified key in the default cache.
200 my ( $self, $key, $cache ) = @_;
202 croak
"No key" unless $key;
203 $ENV{DEBUG
} && carp
"get_from_cache for $key";
204 return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ );
205 return $self->{$cache}->get($key);
208 =head2 clear_from_cache
210 $cache->clear_from_cache($key);
212 Remove the value identified by the specified key from the default cache.
216 sub clear_from_cache
{
217 my ( $self, $key, $cache ) = @_;
219 croak
"No key" unless $key;
220 return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ );
221 return $self->{$cache}->delete($key)
222 if ( ref( $self->{$cache} ) eq 'Cache::Memcached::Fast' );
223 return $self->{$cache}->remove($key);
230 Clear the entire default cache.
235 my ( $self, $cache ) = shift;
237 return unless ( $self->{$cache} && ref( $self->{$cache} ) =~ m/^Cache::/ );
238 return $self->{$cache}->flush_all()
239 if ( ref( $self->{$cache} ) eq 'Cache::Memcached::Fast' );
240 return $self->{$cache}->clear();
243 =head1 TIED INTERFACE
245 Koha::Cache also provides a tied interface which enables users to provide a
246 constructor closure and (after creation) treat cached data like normal reference
247 variables and rely on the cache Just Working and getting updated when it
250 my $cache = Koha::Cache->new();
251 my $data = 'whatever';
252 my $scalar = Koha::Cache->create_scalar(
256 'constructor' => sub { return $data; },
259 print "$$scalar\n"; # Prints "whatever"
260 $data = 'somethingelse';
261 print "$$scalar\n"; # Prints "whatever" because it is cached
262 sleep 2; # Wait until the cache entry has expired
263 print "$$scalar\n"; # Prints "somethingelse"
265 my $hash = Koha::Cache->create_hash(
269 'constructor' => sub { return $data; },
272 print "$$variable\n"; # Prints "whatever"
274 The gotcha with this interface, of course, is that the variable returned by
275 create_scalar and create_hash is a I<reference> to a tied variable and not a
276 tied variable itself.
278 The tied variable is configured by means of a hashref passed in to the
279 create_scalar and create_hash methods. The following parameters are supported:
285 Required. The key to use for identifying the variable in the cache.
289 Required. A closure (or reference to a function) that will return the value that
290 needs to be stored in the cache.
294 Optional. A closure (or reference to a function) that gets run to initialize
295 the cache when creating the tied variable.
299 Optional. Array reference with the arguments that should be passed to the
300 constructor function.
304 Optional. The cache timeout in seconds for the variable. Defaults to 600
309 Optional. Which type of cache to use for the variable. Defaults to whatever is
310 set in the environment variable CACHING_SYSTEM. If set to 'null', disables
311 caching for the tied variable.
315 Optional. Boolean flag to allow the variable to be updated directly. When this
316 is set and the variable is used as an l-value, the cache will be updated
317 immediately with the new value. Using this is probably a bad idea on a
318 multi-threaded system. When I<allowupdate> is not set to true, using the
319 tied variable as an l-value will have no effect.
323 Optional. A closure (or reference to a function) that should be called when the
324 tied variable is destroyed.
328 Optional. Boolean flag to tell the object to remove the variable from the cache
329 when it is destroyed or goes out of scope.
333 Optional. Boolean flag to tell the object not to refresh the variable from the
334 cache every time the value is desired, but rather only when the I<local> copy
335 of the variable is older than the timeout.
341 my $scalar = Koha::Cache->create_scalar(\%params);
343 Create scalar tied to the cache.
348 my ( $self, $args ) = @_;
350 $self->_set_tied_defaults($args);
352 tie
my $scalar, 'Koha::Cache::Object', $args;
357 my ( $self, $args ) = @_;
359 $self->_set_tied_defaults($args);
361 tie
my %hash, 'Koha::Cache::Object', $args;
365 sub _set_tied_defaults
{
366 my ( $self, $args ) = @_;
368 $args->{'timeout'} = '600' unless defined( $args->{'timeout'} );
369 $args->{'inprocess'} = '0' unless defined( $args->{'inprocess'} );
370 unless ( lc( $args->{'cache_type'} ) eq 'null' ) {
371 $args->{'cache'} = $self;
372 $args->{'cache_type'} ||= $ENV{'CACHING_SYSTEM'};
388 Chris Cormack, E<lt>chris@bigballofwax.co.nzE<gt>
389 Paul Poulain, E<lt>paul.poulain@biblibre.comE<gt>
390 Jared Camins-Esakov, E<lt>jcamins@cpbibliography.comE<gt>