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 
64  protected function doGet( $key, $flags = 0, &$casToken = null ) {
65  $casToken = null;
66 
67  $blob = apcu_fetch( $key . self::KEY_SUFFIX );
68  $value = $this->nativeSerialize ? $blob : $this->unserialize( $blob );
69  if ( $value !== false ) {
70  $casToken = $blob; // don't bother hashing this
71  }
72 
73  return $value;
74  }
75 
76  protected function doSet( $key, $value, $exptime = 0, $flags = 0 ) {
77  $blob = $this->nativeSerialize ? $value : $this->getSerialized( $value, $key );
78  $success = apcu_store( $key . self::KEY_SUFFIX, $blob, $exptime );
79  return $success;
80  }
81 
82  protected function doAdd( $key, $value, $exptime = 0, $flags = 0 ) {
83  $blob = $this->nativeSerialize ? $value : $this->getSerialized( $value, $key );
84  $success = apcu_add( $key . self::KEY_SUFFIX, $blob, $exptime );
85  return $success;
86  }
87 
88  protected function doDelete( $key, $flags = 0 ) {
89  apcu_delete( $key . self::KEY_SUFFIX );
90 
91  return true;
92  }
93 
94  public function incr( $key, $value = 1, $flags = 0 ) {
95  $result = false;
96 
97  // https://github.com/krakjoe/apcu/issues/166
98  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
99  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
100  if ( !is_int( $oldCount ) ) {
101  break;
102  }
103  $count = $oldCount + (int)$value;
104  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
105  $result = $count;
106  break;
107  }
108  }
109 
110  return $result;
111  }
112 
113  public function decr( $key, $value = 1, $flags = 0 ) {
114  $result = false;
115 
116  // https://github.com/krakjoe/apcu/issues/166
117  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
118  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
119  if ( !is_int( $oldCount ) ) {
120  break;
121  }
122  $count = $oldCount - (int)$value;
123  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
124  $result = $count;
125  break;
126  }
127  }
128 
129  return $result;
130  }
131 
132  public function incrWithInit( $key, $exptime, $value = 1, $init = null, $flags = 0 ) {
133  // Use apcu 5.1.12 $ttl argument if apcu_inc() will initialize to $init:
134  // https://www.php.net/manual/en/function.apcu-inc.php
135  if ( $value === $init && $this->useIncrTTLArg ) {
137  $result = apcu_inc( $key . self::KEY_SUFFIX, $value, $success, $exptime );
138  } else {
139  $result = false;
140  for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
141  $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
142  if ( $oldCount === false ) {
143  $count = (int)$init;
144  if ( apcu_add( $key . self::KEY_SUFFIX, $count, $exptime ) ) {
145  $result = $count;
146  break;
147  }
148  } elseif ( is_int( $oldCount ) ) {
149  $count = $oldCount + (int)$value;
150  if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
151  $result = $count;
152  break;
153  }
154  } else {
155  break;
156  }
157  }
158  }
159 
160  return $result;
161  }
162 }
APCUBagOStuff\doAdd
doAdd( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
Definition: APCUBagOStuff.php:82
$success
$success
Definition: NoLocalSettings.php:42
APCUBagOStuff\doGet
doGet( $key, $flags=0, &$casToken=null)
Definition: APCUBagOStuff.php:64
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:88
$blob
$blob
Definition: testCompression.php:70
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:113
APCUBagOStuff\__construct
__construct(array $params=[])
Definition: APCUBagOStuff.php:52
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:968
MediumSpecificBagOStuff\unserialize
unserialize( $value)
Definition: MediumSpecificBagOStuff.php:1054
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:132
APCUBagOStuff\incr
incr( $key, $value=1, $flags=0)
Increase stored value of $key by $value while preserving its TTL.
Definition: APCUBagOStuff.php:94
APCUBagOStuff\doSet
doSet( $key, $value, $exptime=0, $flags=0)
Set an item.
Definition: APCUBagOStuff.php:76