MediaWiki REL1_35
APCUBagOStuff.php
Go to the documentation of this file.
1<?php
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 $ttl = $this->getExpirationAsTTL( $exptime );
79 $success = apcu_store( $key . self::KEY_SUFFIX, $blob, $ttl );
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 $ttl = $this->getExpirationAsTTL( $exptime );
86 $success = apcu_add( $key . self::KEY_SUFFIX, $blob, $ttl );
87 return $success;
88 }
89
90 protected function doDelete( $key, $flags = 0 ) {
91 apcu_delete( $key . self::KEY_SUFFIX );
92
93 return true;
94 }
95
96 public function incr( $key, $value = 1, $flags = 0 ) {
97 $result = false;
98
99 // https://github.com/krakjoe/apcu/issues/166
100 for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
101 $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
102 if ( !is_int( $oldCount ) ) {
103 break;
104 }
105 $count = $oldCount + (int)$value;
106 if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
107 $result = $count;
108 break;
109 }
110 }
111
112 return $result;
113 }
114
115 public function decr( $key, $value = 1, $flags = 0 ) {
116 $result = false;
117
118 // https://github.com/krakjoe/apcu/issues/166
119 for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
120 $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
121 if ( !is_int( $oldCount ) ) {
122 break;
123 }
124 $count = $oldCount - (int)$value;
125 if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
126 $result = $count;
127 break;
128 }
129 }
130
131 return $result;
132 }
133
134 public function incrWithInit( $key, $exptime, $value = 1, $init = null, $flags = 0 ) {
135 $init = is_int( $init ) ? $init : $value;
136 // Use apcu 5.1.12 $ttl argument if apcu_inc() will initialize to $init:
137 // https://www.php.net/manual/en/function.apcu-inc.php
138 if ( $value === $init && $this->useIncrTTLArg ) {
140 $ttl = $this->getExpirationAsTTL( $exptime );
141 $result = apcu_inc( $key . self::KEY_SUFFIX, $value, $success, $ttl );
142 } else {
143 $result = false;
144 for ( $i = 0; $i < self::$CAS_MAX_ATTEMPTS; ++$i ) {
145 $oldCount = apcu_fetch( $key . self::KEY_SUFFIX );
146 if ( $oldCount === false ) {
147 $count = (int)$init;
148 $ttl = $this->getExpirationAsTTL( $exptime );
149 if ( apcu_add( $key . self::KEY_SUFFIX, $count, $ttl ) ) {
150 $result = $count;
151 break;
152 }
153 } elseif ( is_int( $oldCount ) ) {
154 $count = $oldCount + (int)$value;
155 if ( apcu_cas( $key . self::KEY_SUFFIX, $oldCount, $count ) ) {
156 $result = $count;
157 break;
158 }
159 } else {
160 break;
161 }
162 }
163 }
164
165 return $result;
166 }
167}
This is a wrapper for APCU's shared memory functions.
doAdd( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
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.
decr( $key, $value=1, $flags=0)
Decrease stored value of $key by $value while preserving its TTL.
doSet( $key, $value, $exptime=0, $flags=0)
Set an item.
doDelete( $key, $flags=0)
Delete an item.
bool $nativeSerialize
Whether to trust the APC implementation to serialization.
static int $CAS_MAX_ATTEMPTS
Max attempts for implicit CAS operations.
__construct(array $params=[])
doGet( $key, $flags=0, &$casToken=null)
incr( $key, $value=1, $flags=0)
Increase stored value of $key by $value while preserving its TTL.
Storage medium specific cache for storing items (e.g.
getSerialized( $value, $key)
Get the serialized form a value, using any applicable prepared value.
getExpirationAsTTL( $exptime)
Convert an optionally absolute expiry time to a relative time.