* @ingroup Cache
*/
class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
+ /** @var Memcached */
+ protected $client;
/**
* Available parameters are:
$this->client->setOption( Memcached::OPT_LIBKETAMA_COMPATIBLE, true );
// Set the serializer
- switch ( $params['serializer'] ) {
- case 'php':
- $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP );
- break;
- case 'igbinary':
- if ( !Memcached::HAVE_IGBINARY ) {
- throw new InvalidArgumentException(
- __CLASS__ . ': the igbinary extension is not available ' .
- 'but igbinary serialization was requested.'
- );
- }
- $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_IGBINARY );
- break;
- default:
+ $ok = false;
+ if ( $params['serializer'] === 'php' ) {
+ $ok = $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP );
+ } elseif ( $params['serializer'] === 'igbinary' ) {
+ if ( !Memcached::HAVE_IGBINARY ) {
throw new InvalidArgumentException(
- __CLASS__ . ': invalid value for serializer parameter'
+ __CLASS__ . ': the igbinary extension is not available ' .
+ 'but igbinary serialization was requested.'
);
+ }
+ $ok = $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_IGBINARY );
+ }
+ if ( !$ok ) {
+ throw new InvalidArgumentException( __CLASS__ . ': invalid serializer parameter' );
}
+
$servers = [];
foreach ( $params['servers'] as $host ) {
if ( preg_match( '/^\[(.+)\]:(\d+)$/', $host, $m ) ) {
return $params;
}
- /**
- * @suppress PhanTypeNonVarPassByRef
- */
protected function doGet( $key, $flags = 0, &$casToken = null ) {
- $this->debugLog( "get($key)" );
+ $this->debug( "get($key)" );
if ( defined( Memcached::class . '::GET_EXTENDED' ) ) { // v3.0.0
$flags = Memcached::GET_EXTENDED;
$res = $this->client->get( $this->validateKeyEncoding( $key ), null, $flags );
return $result;
}
- public function set( $key, $value, $exptime = 0, $flags = 0 ) {
- $this->debugLog( "set($key)" );
- $result = parent::set( $key, $value, $exptime, $flags = 0 );
+ protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
+ $this->debug( "set($key)" );
+ $result = $this->client->set(
+ $this->validateKeyEncoding( $key ),
+ $value,
+ $this->fixExpiry( $exptime )
+ );
if ( $result === false && $this->client->getResultCode() === Memcached::RES_NOTSTORED ) {
// "Not stored" is always used as the mcrouter response with AllAsyncRoute
return true;
}
protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
- $this->debugLog( "cas($key)" );
- return $this->checkResult( $key, parent::cas( $casToken, $key, $value, $exptime, $flags ) );
+ $this->debug( "cas($key)" );
+ $result = $this->client->cas( $casToken, $this->validateKeyEncoding( $key ),
+ $value, $this->fixExpiry( $exptime ) );
+ return $this->checkResult( $key, $result );
}
- public function delete( $key, $flags = 0 ) {
- $this->debugLog( "delete($key)" );
- $result = parent::delete( $key );
+ protected function doDelete( $key, $flags = 0 ) {
+ $this->debug( "delete($key)" );
+ $result = $this->client->delete( $this->validateKeyEncoding( $key ) );
if ( $result === false && $this->client->getResultCode() === Memcached::RES_NOTFOUND ) {
// "Not found" is counted as success in our interface
return true;
}
public function add( $key, $value, $exptime = 0, $flags = 0 ) {
- $this->debugLog( "add($key)" );
- return $this->checkResult( $key, parent::add( $key, $value, $exptime ) );
+ $this->debug( "add($key)" );
+ $result = $this->client->add(
+ $this->validateKeyEncoding( $key ),
+ $value,
+ $this->fixExpiry( $exptime )
+ );
+ return $this->checkResult( $key, $result );
}
public function incr( $key, $value = 1 ) {
- $this->debugLog( "incr($key)" );
+ $this->debug( "incr($key)" );
$result = $this->client->increment( $key, $value );
return $this->checkResult( $key, $result );
}
public function decr( $key, $value = 1 ) {
- $this->debugLog( "decr($key)" );
+ $this->debug( "decr($key)" );
$result = $this->client->decrement( $key, $value );
return $this->checkResult( $key, $result );
}
case Memcached::RES_DATA_EXISTS:
case Memcached::RES_NOTSTORED:
case Memcached::RES_NOTFOUND:
- $this->debugLog( "result: " . $this->client->getResultMessage() );
+ $this->debug( "result: " . $this->client->getResultMessage() );
break;
default:
$msg = $this->client->getResultMessage();
return $result;
}
- public function getMulti( array $keys, $flags = 0 ) {
- $this->debugLog( 'getMulti(' . implode( ', ', $keys ) . ')' );
+ public function doGetMulti( array $keys, $flags = 0 ) {
+ $this->debug( 'getMulti(' . implode( ', ', $keys ) . ')' );
foreach ( $keys as $key ) {
$this->validateKeyEncoding( $key );
}
}
public function setMulti( array $data, $exptime = 0, $flags = 0 ) {
- $this->debugLog( 'setMulti(' . implode( ', ', array_keys( $data ) ) . ')' );
+ $this->debug( 'setMulti(' . implode( ', ', array_keys( $data ) ) . ')' );
foreach ( array_keys( $data ) as $key ) {
$this->validateKeyEncoding( $key );
}
return $this->checkResult( false, $result );
}
- public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
- $this->debugLog( "touch($key)" );
- $result = $this->client->touch( $key, $expiry );
+ public function deleteMulti( array $keys, $flags = 0 ) {
+ $this->debug( 'deleteMulti(' . implode( ', ', $keys ) . ')' );
+ foreach ( $keys as $key ) {
+ $this->validateKeyEncoding( $key );
+ }
+ $result = $this->client->deleteMulti( $keys ) ?: [];
+ $ok = true;
+ foreach ( $result as $code ) {
+ if ( !in_array( $code, [ true, Memcached::RES_NOTFOUND ], true ) ) {
+ // "Not found" is counted as success in our interface
+ $ok = false;
+ }
+ }
+ return $this->checkResult( false, $ok );
+ }
+
+ public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
+ $this->debug( "touch($key)" );
+ $result = $this->client->touch( $key, $exptime );
return $this->checkResult( $key, $result );
}
+
+ protected function serialize( $value ) {
+ if ( is_int( $value ) ) {
+ return $value;
+ }
+
+ $serializer = $this->client->getOption( Memcached::OPT_SERIALIZER );
+ if ( $serializer === Memcached::SERIALIZER_PHP ) {
+ return serialize( $value );
+ } elseif ( $serializer === Memcached::SERIALIZER_IGBINARY ) {
+ return igbinary_serialize( $value );
+ }
+
+ throw new UnexpectedValueException( __METHOD__ . ": got serializer '$serializer'." );
+ }
+
+ protected function unserialize( $value ) {
+ if ( $this->isInteger( $value ) ) {
+ return (int)$value;
+ }
+
+ $serializer = $this->client->getOption( Memcached::OPT_SERIALIZER );
+ if ( $serializer === Memcached::SERIALIZER_PHP ) {
+ return unserialize( $value );
+ } elseif ( $serializer === Memcached::SERIALIZER_IGBINARY ) {
+ return igbinary_unserialize( $value );
+ }
+
+ throw new UnexpectedValueException( __METHOD__ . ": got serializer '$serializer'." );
+ }
}