const READ_LATEST = 1; // use latest data for replicated stores
const READ_VERIFIED = 2; // promise that caller can tell when keys are stale
/** Bitfield constants for set()/merge() */
- const WRITE_SYNC = 1; // synchronously write to all locations for replicated stores
- const WRITE_CACHE_ONLY = 2; // Only change state of the in-memory cache
+ const WRITE_SYNC = 4; // synchronously write to all locations for replicated stores
+ const WRITE_CACHE_ONLY = 8; // Only change state of the in-memory cache
/**
* $params include:
* @param string $key
* @param int $ttl Time-to-live (seconds)
* @param callable $callback Callback that derives the new value
- * @param int $flags Bitfield of BagOStuff::READ_* constants [optional]
+ * @param int $flags Bitfield of BagOStuff::READ_* or BagOStuff::WRITE_* constants [optional]
* @return mixed The cached value if found or the result of $callback otherwise
* @since 1.27
*/
}
$value = call_user_func( $callback );
if ( $value !== false ) {
- $this->set( $key, $value, $ttl );
+ $this->set( $key, $value, $ttl, $flags );
}
}
* @param callable $callback Callback method to be executed
* @param int $exptime Either an interval in seconds or a unix timestamp for expiry
* @param int $attempts The amount of times to attempt a merge in case of failure
+ * @param int $flags Bitfield of BagOStuff::WRITE_* constants
* @return bool Success
*/
- protected function mergeViaCas( $key, $callback, $exptime = 0, $attempts = 10 ) {
+ protected function mergeViaCas( $key, $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
do {
$this->clearLastError();
$reportDupes = $this->reportDupes;
$success = true; // do nothing
} elseif ( $currentValue === false ) {
// Try to create the key, failing if it gets created in the meantime
- $success = $this->add( $key, $value, $exptime );
+ $success = $this->add( $key, $value, $exptime, $flags );
} else {
// Try to update the key, failing if it gets changed in the meantime
- $success = $this->cas( $casToken, $key, $value, $exptime );
+ $success = $this->cas( $casToken, $key, $value, $exptime, $flags );
}
if ( $this->getLastError() ) {
$this->logger->warning(
* @param string $key
* @param mixed $value
* @param int $exptime Either an interval in seconds or a unix timestamp for expiry
+ * @param int $flags Bitfield of BagOStuff::WRITE_* constants
* @return bool Success
* @throws Exception
*/
- protected function cas( $casToken, $key, $value, $exptime = 0 ) {
+ protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
if ( !$this->lock( $key, 0 ) ) {
return false; // non-blocking
}
$curCasToken = null; // passed by reference
$this->getWithToken( $key, $curCasToken, self::READ_LATEST );
if ( $casToken === $curCasToken ) {
- $success = $this->set( $key, $value, $exptime );
+ $success = $this->set( $key, $value, $exptime, $flags );
} else {
$this->logger->info(
__METHOD__ . ' failed due to race condition for {key}.',
*
* @param string $key
* @param int $expiry
+ * @param int $flags Bitfield of BagOStuff::WRITE_* constants (since 1.33)
* @return bool Success Returns false if there is no key
* @since 1.28
*/
- public function changeTTL( $key, $expiry = 0 ) {
+ public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
$value = $this->get( $key );
- return ( $value === false ) ? false : $this->set( $key, $value, $expiry );
+ return ( $value === false ) ? false : $this->set( $key, $value, $expiry, $flags );
}
/**
/**
* Get an associative array containing the item for each of the keys that have items.
- * @param array $keys List of strings
+ * @param string[] $keys List of keys
* @param int $flags Bitfield; supports READ_LATEST [optional]
* @return array
*/
public function getMulti( array $keys, $flags = 0 ) {
$res = [];
foreach ( $keys as $key ) {
- $val = $this->get( $key );
+ $val = $this->get( $key, $flags );
if ( $val !== false ) {
$res[$key] = $val;
}
}
+
return $res;
}
/**
- * Batch insertion
- * @param array $data $key => $value assoc array
+ * Batch insertion/replace
+ * @param mixed[] $data Map of (key => value)
* @param int $exptime Either an interval in seconds or a unix timestamp for expiry
+ * @param int $flags Bitfield of BagOStuff::WRITE_* constants (since 1.33)
* @return bool Success
* @since 1.24
*/
- public function setMulti( array $data, $exptime = 0 ) {
+ public function setMulti( array $data, $exptime = 0, $flags = 0 ) {
$res = true;
foreach ( $data as $key => $value ) {
- if ( !$this->set( $key, $value, $exptime ) ) {
+ if ( !$this->set( $key, $value, $exptime, $flags ) ) {
$res = false;
}
}
+
return $res;
}
/**
+ * Insertion
* @param string $key
* @param mixed $value
* @param int $exptime
+ * @param int $flags Bitfield of BagOStuff::WRITE_* constants (since 1.33)
* @return bool Success
*/
- public function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0, $flags = 0 ) {
// @note: avoid lock() here since that method uses *this* method by default
if ( $this->get( $key ) === false ) {
- return $this->set( $key, $value, $exptime );
+ return $this->set( $key, $value, $exptime, $flags );
}
+
return false; // key already set
}
if ( !$this->lock( $key, 1 ) ) {
return false;
}
- $n = $this->get( $key );
+ $n = $this->get( $key, self::READ_LATEST );
if ( $this->isInteger( $n ) ) { // key exists?
$n += intval( $value );
$this->set( $key, max( 0, $n ) ); // exptime?
return false;
}
- public function add( $key, $value, $exp = 0 ) {
+ public function add( $key, $value, $exp = 0, $flags = 0 ) {
return true;
}
$this->fixExpiry( $exptime ) );
}
- protected function cas( $casToken, $key, $value, $exptime = 0 ) {
+ protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
return $this->client->cas( $casToken, $this->validateKeyEncoding( $key ),
$value, $this->fixExpiry( $exptime ) );
}
return $this->client->delete( $this->validateKeyEncoding( $key ) );
}
- public function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0, $flags = 0 ) {
return $this->client->add( $this->validateKeyEncoding( $key ), $value,
$this->fixExpiry( $exptime ) );
}
return $this->mergeViaCas( $key, $callback, $exptime, $attempts );
}
- public function changeTTL( $key, $exptime = 0 ) {
+ public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
return $this->client->touch( $this->validateKeyEncoding( $key ),
$this->fixExpiry( $exptime ) );
}
public function set( $key, $value, $exptime = 0, $flags = 0 ) {
$this->debugLog( "set($key)" );
- $result = parent::set( $key, $value, $exptime );
+ $result = parent::set( $key, $value, $exptime, $flags = 0 );
if ( $result === false && $this->client->getResultCode() === Memcached::RES_NOTSTORED ) {
// "Not stored" is always used as the mcrouter response with AllAsyncRoute
return true;
return $this->checkResult( $key, $result );
}
- protected function cas( $casToken, $key, $value, $exptime = 0 ) {
+ protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
$this->debugLog( "cas($key)" );
- return $this->checkResult( $key, parent::cas( $casToken, $key, $value, $exptime ) );
+ return $this->checkResult( $key, parent::cas( $casToken, $key, $value, $exptime, $flags ) );
}
public function delete( $key, $flags = 0 ) {
return $this->checkResult( $key, $result );
}
- public function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0, $flags = 0 ) {
$this->debugLog( "add($key)" );
return $this->checkResult( $key, parent::add( $key, $value, $exptime ) );
}
return $this->checkResult( false, $result );
}
- /**
- * @param array $data
- * @param int $exptime
- * @return bool
- */
- public function setMulti( array $data, $exptime = 0 ) {
+ public function setMulti( array $data, $exptime = 0, $flags = 0 ) {
$this->debugLog( '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 ) {
+ public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
$this->debugLog( "touch($key)" );
$result = $this->client->touch( $key, $expiry );
return $this->checkResult( $key, $result );
return $this->doWrite( $this->cacheIndexes, $this->asyncWrites, 'delete', $key );
}
- public function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0, $flags = 0 ) {
// Try the write to the top-tier cache
$ok = $this->doWrite( [ 0 ], $this->asyncWrites, 'add', $key, $value, $exptime );
if ( $ok ) {
return $result;
}
- /**
- * @param array $data
- * @param int $expiry
- * @return bool
- */
- public function setMulti( array $data, $expiry = 0 ) {
+ public function setMulti( array $data, $expiry = 0, $flags = 0 ) {
$batches = [];
$conns = [];
foreach ( $data as $key => $value ) {
return $result;
}
- public function add( $key, $value, $expiry = 0 ) {
+ public function add( $key, $value, $expiry = 0, $flags = 0 ) {
list( $server, $conn ) = $this->getConnection( $key );
if ( !$conn ) {
return false;
return $result;
}
- public function changeTTL( $key, $expiry = 0 ) {
+ public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
list( $server, $conn ) = $this->getConnection( $key );
if ( !$conn ) {
return false;
return $this->writeStore->delete( $key, $flags );
}
- public function add( $key, $value, $exptime = 0 ) {
+ public function add( $key, $value, $exptime = 0, $flags = 0 ) {
return $this->writeStore->add( $key, $value, $exptime );
}
return $values;
}
- public function setMulti( array $data, $expiry = 0 ) {
+ public function setMulti( array $data, $expiry = 0, $flags = 0 ) {
$keysByTable = [];
foreach ( $data as $key => $value ) {
list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
return $ok;
}
- protected function cas( $casToken, $key, $value, $exptime = 0 ) {
+ protected function cas( $casToken, $key, $value, $exptime = 0, $flags = 0 ) {
list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
$db = null;
$silenceScope = $this->silenceTransactionProfiler();
}
public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
- $ok = $this->mergeViaCas( $key, $callback, $exptime, $attempts );
+ $ok = $this->mergeViaCas( $key, $callback, $exptime, $attempts, $flags );
if ( ( $flags & self::WRITE_SYNC ) == self::WRITE_SYNC ) {
$ok = $this->waitForReplication() && $ok;
}
return $ok;
}
- public function changeTTL( $key, $expiry = 0 ) {
+ public function changeTTL( $key, $expiry = 0, $flags = 0 ) {
list( $serverIndex, $tableName ) = $this->getTableByKey( $key );
$db = null;
$silenceScope = $this->silenceTransactionProfiler();