Bug 16229: Deep copy on first L2 fetch
authorJonathan Druart <jonathan.druart@bugs.koha-community.org>
Fri, 8 Apr 2016 12:08:55 +0000 (13:08 +0100)
committerJulian Maurice <julian.maurice@biblibre.com>
Thu, 23 Jun 2016 07:22:34 +0000 (09:22 +0200)
When a value exists in L2 cache but not in L1 cache, it should be deep
copied if needed (i.e. not a scalar). Otherwise the calling code is able
to modify the value in cache.
Note that is theoretical, it's possible that no code does that.

Signed-off-by: Jacek Ablewicz <abl@biblos.pk.edu.pl>
Signed-off-by: Tomas Cohen Arazi <tomascohen@unc.edu.ar>

Signed-off-by: Brendan Gallagher <bredan@bywatersolutions.com>
(cherry picked from commit 956dc953b52a1fd525bc75682bbdfe6848683ace)
Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>

Koha/Cache.pm
t/Cache.t

index f980da5..5e4471c 100644 (file)
@@ -321,6 +321,8 @@ sub get_from_cache {
     # Otherwise the L1 cache won't ever be populated
     $L1_cache{$key} = $value;
 
+    $value = clone $value if ref $L1_cache{$key} and not $unsafe;
+
     return $value;
 }
 
index c8887db..7ec72ef 100644 (file)
--- a/t/Cache.t
+++ b/t/Cache.t
@@ -17,7 +17,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 39;
+use Test::More tests => 40;
 
 my $destructorcount = 0;
 
@@ -34,7 +34,7 @@ SKIP: {
     $ENV{ MEMCACHED_NAMESPACE } = 'unit_tests';
     my $cache = Koha::Cache->get_instance();
 
-    skip "Cache not enabled", 33
+    skip "Cache not enabled", 34
       unless ( $cache->is_cache_active() && defined $cache );
 
     # test fetching an item that isnt in the cache
@@ -182,6 +182,12 @@ SKIP: {
     $item_from_cache = $cache->get_from_cache('test_deep_copy_array');
     @$item_from_cache = qw( another array ref );
     is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( an array ref ) ], 'An array will be deep copied');
+
+    $cache->flush_L1_cache();
+    $item_from_cache = $cache->get_from_cache('test_deep_copy_array');
+    @$item_from_cache = qw( another array ref );
+    is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( an array ref ) ], 'An array will be deep copied even it is the first fetch from L2');
+
     $item_from_cache = $cache->get_from_cache('test_deep_copy_array', { unsafe => 1 });
     @$item_from_cache = qw( another array ref );
     is_deeply( $cache->get_from_cache('test_deep_copy_array'), [ qw ( another array ref ) ], 'An array will not be deep copied if the unsafe flag is set');