From 58c81f5b86a454e51af247117d3c0d3adabbc5d4 Mon Sep 17 00:00:00 2001 From: Matthias Mullie Date: Wed, 2 Sep 2015 15:02:36 +0200 Subject: [PATCH] Decode Memcached keys before returning getMulti result Keys are sent to Memcached encoded. However, getMulti() will respond in [key => value] format. The keys it responds with should not be the encoded versions, or callers won't be able to map them to the results. Bug: T111138 Change-Id: I0d821b1219a492be8e93453f0249c78f18e24533 --- includes/objectcache/MemcachedPeclBagOStuff.php | 9 +++++++-- includes/objectcache/MemcachedPhpBagOStuff.php | 8 +++++++- tests/phpunit/includes/objectcache/BagOStuffTest.php | 8 ++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/includes/objectcache/MemcachedPeclBagOStuff.php b/includes/objectcache/MemcachedPeclBagOStuff.php index 7e6a4d7074..1b2c8db62e 100644 --- a/includes/objectcache/MemcachedPeclBagOStuff.php +++ b/includes/objectcache/MemcachedPeclBagOStuff.php @@ -236,8 +236,13 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff { public function getMulti( array $keys, $flags = 0 ) { $this->debugLog( 'getMulti(' . implode( ', ', $keys ) . ')' ); $callback = array( $this, 'encodeKey' ); - $result = $this->client->getMulti( array_map( $callback, $keys ) ); - $result = $result ?: array(); // must be an array + $encodedResult = $this->client->getMulti( array_map( $callback, $keys ) ); + $encodedResult = $encodedResult ?: array(); // must be an array + $result = array(); + foreach ( $encodedResult as $key => $value ) { + $key = $this->decodeKey( $key ); + $result[$key] = $value; + } return $this->checkResult( false, $result ); } diff --git a/includes/objectcache/MemcachedPhpBagOStuff.php b/includes/objectcache/MemcachedPhpBagOStuff.php index 69792ada56..6f0ba58820 100644 --- a/includes/objectcache/MemcachedPhpBagOStuff.php +++ b/includes/objectcache/MemcachedPhpBagOStuff.php @@ -59,7 +59,13 @@ class MemcachedPhpBagOStuff extends MemcachedBagOStuff { public function getMulti( array $keys, $flags = 0 ) { $callback = array( $this, 'encodeKey' ); - return $this->client->get_multi( array_map( $callback, $keys ) ); + $encodedResult = $this->client->get_multi( array_map( $callback, $keys ) ); + $result = array(); + foreach ( $encodedResult as $key => $value ) { + $key = $this->decodeKey( $key ); + $result[$key] = $value; + } + return $result; } /** diff --git a/tests/phpunit/includes/objectcache/BagOStuffTest.php b/tests/phpunit/includes/objectcache/BagOStuffTest.php index f5814e4483..b684006202 100644 --- a/tests/phpunit/includes/objectcache/BagOStuffTest.php +++ b/tests/phpunit/includes/objectcache/BagOStuffTest.php @@ -138,21 +138,25 @@ class BagOStuffTest extends MediaWikiTestCase { public function testGetMulti() { $value1 = array( 'this' => 'is', 'a' => 'test' ); $value2 = array( 'this' => 'is', 'another' => 'test' ); + $value3 = array( 'testing a key that may be encoded when sent to cache backend' ); $key1 = wfMemcKey( 'test1' ); $key2 = wfMemcKey( 'test2' ); + $key3 = wfMemcKey( 'will-%-encode' ); // internally, MemcachedBagOStuffs will encode to will-%25-encode $this->cache->add( $key1, $value1 ); $this->cache->add( $key2, $value2 ); + $this->cache->add( $key3, $value3 ); $this->assertEquals( - $this->cache->getMulti( array( $key1, $key2 ) ), - array( $key1 => $value1, $key2 => $value2 ) + array( $key1 => $value1, $key2 => $value2, $key3 => $value3 ), + $this->cache->getMulti( array( $key1, $key2, $key3 ) ) ); // cleanup $this->cache->delete( $key1 ); $this->cache->delete( $key2 ); + $this->cache->delete( $key3 ); } /** -- 2.20.1