wiki.techinc.nl/includes/objectcache/HashBagOStuff.php
Matthias Mullie 2a4dfa169b Don't use complex datatypes as CAS tokens
For caches where CAS is not natively supported, we have a workaround, where the
CAS token is (based on) the stored value.

To confirm the data can be written to cache, the CAS token is compared against
"whatever is currently in cache", so we pull the cached data and rebuild the
value.

In the case of objects, we have now pulled & rebuilt (unserialized) 2 objects
that are actually the same object (for CAS purpose - it's the correct value to
overwrite), but in terms of ===, they're 2 different values.

This patch should make sure CAS tokens are always a serialized version of the
value we're saving (where no native CAS exists); these serialized versions can
reliably be compared.

Bug: 59941
Change-Id: I2760416c48f2ceb7a0e0c874dd70ec07b4dccdfc
2014-01-14 16:45:32 +01:00

112 lines
2.4 KiB
PHP

<?php
/**
* Object caching using PHP arrays.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
* @ingroup Cache
*/
/**
* This is a test of the interface, mainly. It stores things in an associative
* array, which is not going to persist between program runs.
*
* @ingroup Cache
*/
class HashBagOStuff extends BagOStuff {
var $bag;
function __construct() {
$this->bag = array();
}
/**
* @param $key string
* @return bool
*/
protected function expire( $key ) {
$et = $this->bag[$key][1];
if ( ( $et == 0 ) || ( $et > time() ) ) {
return false;
}
$this->delete( $key );
return true;
}
/**
* @param $key string
* @param $casToken[optional] mixed
* @return bool|mixed
*/
function get( $key, &$casToken = null ) {
if ( !isset( $this->bag[$key] ) ) {
return false;
}
if ( $this->expire( $key ) ) {
return false;
}
$casToken = serialize( $this->bag[$key][0] );
return $this->bag[$key][0];
}
/**
* @param $key string
* @param $value mixed
* @param $exptime int
* @return bool
*/
function set( $key, $value, $exptime = 0 ) {
$this->bag[$key] = array( $value, $this->convertExpiry( $exptime ) );
return true;
}
/**
* @param $casToken mixed
* @param $key string
* @param $value mixed
* @param $exptime int
* @return bool
*/
function cas( $casToken, $key, $value, $exptime = 0 ) {
if ( serialize( $this->get( $key ) ) === $casToken ) {
return $this->set( $key, $value, $exptime );
}
return false;
}
/**
* @param $key string
* @param $time int
* @return bool
*/
function delete( $key, $time = 0 ) {
if ( !isset( $this->bag[$key] ) ) {
return false;
}
unset( $this->bag[$key] );
return true;
}
}