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