MediaWiki  master
APCUBagOStuff.php
Go to the documentation of this file.
1 <?php
40  private $useIncrTTLArg;
41 
47  private const KEY_SUFFIX = ':4';
48 
50  private static $CAS_MAX_ATTEMPTS = 100;
51 
52  public function __construct( array $params = [] ) {
53  $params['segmentationSize'] = $params['segmentationSize'] ?? INF;
54  parent::__construct( $params );
55  // The extension serializer is still buggy, unlike "php" and "igbinary"
56  $this->nativeSerialize = ( ini_get( 'apc.serializer' ) !== 'default' );
57  $this->useIncrTTLArg = version_compare( phpversion( 'apcu' ), '5.1.12', '>=' );
58  // Avoid back-dated values that expire too soon. In particular, regenerating a hot
59  // key before it expires should never have the end-result of purging that key. Using
60  // the web request time becomes increasingly problematic the longer the request lasts.
61  ini_set( 'apc.use_request_time', '0' );
62 
63  if ( PHP_SAPI === 'cli' ) {
64  $this->attrMap[self::ATTR_DURABILITY] = ini_get( 'apc.enable_cli' )
67  } else {
69  }
70  }
71 
72  protected function doGet( $key, $flags = 0, &$casToken = null ) {
73  $getToken = ( $casToken === self::PASS_BY_REF );
74  $casToken = null;
75 
76  $blob = apcu_fetch( $key . self::KEY_SUFFIX );
77  $value = $this->nativeSerialize ? $blob : $this->unserialize( $blob );
78  if ( $getToken && $value !== false ) {
79  $casToken = $blob; // don't bother hashing this
80  }
81 
82  return $value;
83  }
84 
85  protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
86  $blob = $this->nativeSerialize ? $value : $this->getSerialized( $value, $key );
87  $ttl = $this->getExpirationAsTTL( $exptime );
88  $success = apcu_store( $key . self::KEY_SUFFIX, $blob, $ttl );
89  return $success;
90  }
91 
92  protected function doAdd( $key, $value, $exptime = 0, $flags = 0 ) {
93  $blob = $this->nativeSerialize ? $value : $this->getSerialized( $value, $key );
94  $ttl = $this->getExpirationAsTTL( $exptime );
95  $success = apcu_add( $key . self::KEY_SUFFIX, $blob, $ttl );
96  return $success;
97  }
98 
99  protected function doDelete( $key, $flags = 0 ) {
100  apcu_delete( $key . self::KEY_SUFFIX );
101 
102  return true;
103  }
104 
105  public function incr( $key, $value = 1, $flags = 0 ) {
106  $result = false;
107 
108  // https://github.com/krakjoe/apcu/issues/166
109  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
110  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
111  if ( !is_int( $oldCount ) ) {
112  break;
113  }
114  $count = $oldCount + (int)$value;
115  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
116  $result = $count;
117  break;
118  }
119  }
120 
121  return $result;
122  }
123 
124  public function decr( $key, $value = 1, $flags = 0 ) {
125  $result = false;
126 
127  // https://github.com/krakjoe/apcu/issues/166
128  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
129  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
130  if ( !is_int( $oldCount ) ) {
131  break;
132  }
133  $count = $oldCount - (int)$value;
134  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
135  $result = $count;
136  break;
137  }
138  }
139 
140  return $result;
141  }
142 
143  public function incrWithInit( $key, $exptime, $value = 1, $init = null, $flags = 0 ) {
144  $init = is_int( $init ) ? $init : $value;
145  // Use apcu 5.1.12 $ttl argument if apcu_inc() will initialize to $init:
146  // https://www.php.net/manual/en/function.apcu-inc.php
147  if ( $value === $init && $this->useIncrTTLArg ) {
149  $ttl = $this->getExpirationAsTTL( $exptime );
150  $result = apcu_inc( $key . self::KEY_SUFFIX, $value, $success, $ttl );
151  } else {
152  $result = false;
153  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
154  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
155  if ( $oldCount === false ) {
156  $count = (int)$init;
157  $ttl = $this->getExpirationAsTTL( $exptime );
158  if ( apcu_add( $key . self::KEY_SUFFIX, $count, $ttl ) ) {
159  $result = $count;
160  break;
161  }
162  } elseif ( is_int( $oldCount ) ) {
163  $count = $oldCount + (int)$value;
164  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
165  $result = $count;
166  break;
167  }
168  } else {
169  break;
170  }
171  }
172  }
173 
174  return $result;
175  }
176 
177  public function makeKeyInternal( $keyspace, $components ) {
178  return $this->genericKeyFromComponents( $keyspace, ...$components );
179  }
180 
181  protected function convertGenericKey( $key ) {
182  return $key; // short-circuit; already uses "generic" keys
183  }
184 }
Wikimedia\LightweightObjectStore\StorageAwareness\QOS_DURABILITY_SCRIPT
const QOS_DURABILITY_SCRIPT
Data is lost at the end of the current web request or CLI script.
Definition: StorageAwareness.php:58
APCUBagOStuff\doAdd
doAdd( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
Definition: APCUBagOStuff.php:92
Wikimedia\LightweightObjectStore\StorageAwareness\QOS_DURABILITY_NONE
const QOS_DURABILITY_NONE
Data is never saved to begin with (blackhole store)
Definition: StorageAwareness.php:56
APCUBagOStuff\convertGenericKey
convertGenericKey( $key)
Convert a "generic" reversible cache key into one for this cache.
Definition: APCUBagOStuff.php:181
APCUBagOStuff\makeKeyInternal
makeKeyInternal( $keyspace, $components)
Make a cache key for the given keyspace and components.
Definition: APCUBagOStuff.php:177
BagOStuff\genericKeyFromComponents
genericKeyFromComponents(... $components)
At a minimum, there must be a keyspace and collection name component.
Definition: BagOStuff.php:676
$success
$success
Definition: NoLocalSettings.php:42
APCUBagOStuff\doGet
doGet( $key, $flags=0, &$casToken=null)
Definition: APCUBagOStuff.php:72
APCUBagOStuff\$CAS_MAX_ATTEMPTS
static int $CAS_MAX_ATTEMPTS
Max attempts for implicit CAS operations.
Definition: APCUBagOStuff.php:50
APCUBagOStuff\$useIncrTTLArg
bool $useIncrTTLArg
Definition: APCUBagOStuff.php:40
APCUBagOStuff\doDelete
doDelete( $key, $flags=0)
Delete an item.
Definition: APCUBagOStuff.php:99
$blob
$blob
Definition: testCompression.php:70
MediumSpecificBagOStuff\getExpirationAsTTL
getExpirationAsTTL( $exptime)
Convert an optionally absolute expiry time to a relative time.
Definition: MediumSpecificBagOStuff.php:937
MediumSpecificBagOStuff
Storage medium specific cache for storing items (e.g.
Definition: MediumSpecificBagOStuff.php:34
APCUBagOStuff\decr
decr( $key, $value=1, $flags=0)
Decrease stored value of $key by $value while preserving its TTL.
Definition: APCUBagOStuff.php:124
APCUBagOStuff\__construct
__construct(array $params=[])
Definition: APCUBagOStuff.php:52
Wikimedia\LightweightObjectStore\StorageAwareness\QOS_DURABILITY_SERVICE
const QOS_DURABILITY_SERVICE
Data is lost once the service storing the data restarts.
Definition: StorageAwareness.php:60
APCUBagOStuff\$nativeSerialize
bool $nativeSerialize
Whether to trust the APC implementation to serialization.
Definition: APCUBagOStuff.php:38
APCUBagOStuff
This is a wrapper for APCU's shared memory functions.
Definition: APCUBagOStuff.php:36
MediumSpecificBagOStuff\getSerialized
getSerialized( $value, $key)
Get the serialized form a value, using any applicable prepared value.
Definition: MediumSpecificBagOStuff.php:1026
Wikimedia\LightweightObjectStore\StorageAwareness\ATTR_DURABILITY
const ATTR_DURABILITY
Durability of writes; see QOS_DURABILITY_* (higher means stronger)
Definition: StorageAwareness.php:45
MediumSpecificBagOStuff\unserialize
unserialize( $value)
Definition: MediumSpecificBagOStuff.php:1173
APCUBagOStuff\incrWithInit
incrWithInit( $key, $exptime, $value=1, $init=null, $flags=0)
Increase the value of the given key (no TTL change) if it exists or create it otherwise.
Definition: APCUBagOStuff.php:143
BagOStuff\$keyspace
string $keyspace
Default keyspace; used by makeKey()
Definition: BagOStuff.php:103
APCUBagOStuff\incr
incr( $key, $value=1, $flags=0)
Increase stored value of $key by $value while preserving its TTL.
Definition: APCUBagOStuff.php:105
APCUBagOStuff\doSet
doSet( $key, $value, $exptime=0, $flags=0)
Set an item.
Definition: APCUBagOStuff.php:85