/**
* Increase stored value of $key by $value while preserving its TTL
*
- * This will create the key with value $init and TTL $ttl if not present
+ * This will create the key with value $init and TTL $ttl instead if not present
*
* @param string $key
* @param int $ttl
* @param int $value
* @param int $init
- * @return bool
+ * @return int|bool New value or false on failure
* @since 1.24
*/
public function incrWithInit( $key, $ttl, $value = 1, $init = 1 ) {
- return $this->incr( $key, $value ) ||
- $this->add( $key, (int)$init, $ttl ) || $this->incr( $key, $value );
+ $newValue = $this->incr( $key, $value );
+ if ( $newValue === false ) {
+ // No key set; initialize
+ $newValue = $this->add( $key, (int)$init, $ttl ) ? $init : false;
+ }
+ if ( $newValue === false ) {
+ // Raced out initializing; increment
+ $newValue = $this->incr( $key, $value );
+ }
+
+ return $newValue;
}
/**
$cache = ObjectCache::getLocalServerInstance();
}
if ( $cache ) {
- $counter = $cache->incr( $bucket, $count );
+ $counter = $cache->incrWithInit( $bucket, $cache::TTL_INDEFINITE, $count, $count );
if ( $counter === false ) {
- if ( !$cache->add( $bucket, (int)$count ) ) {
- throw new RuntimeException( 'Unable to set value to ' . get_class( $cache ) );
- }
- $counter = $count;
+ throw new RuntimeException( 'Unable to set value to ' . get_class( $cache ) );
}
}
$this->assertEquals( $expectedValue, $actualValue, 'Value should be 1 after incrementing' );
}
+ /**
+ * @covers BagOStuff::incrWithInit
+ */
+ public function testIncrWithInit() {
+ $key = wfMemcKey( 'test' );
+ $val = $this->cache->incrWithInit( $key, 0, 1, 3 );
+ $this->assertEquals( 3, $val, "Correct init value" );
+
+ $val = $this->cache->incrWithInit( $key, 0, 1, 3 );
+ $this->assertEquals( 4, $val, "Correct init value" );
+ }
+
/**
* @covers BagOStuff::getMulti
*/