MediaWiki  master
CachedBagOStuff.php
Go to the documentation of this file.
1 <?php
37 class CachedBagOStuff extends BagOStuff {
39  protected $store;
41  protected $procCache;
42 
48  public function __construct( BagOStuff $backend, $params = [] ) {
49  $params['keyspace'] = $backend->keyspace;
50  parent::__construct( $params );
51 
52  $this->store = $backend;
53  $this->procCache = new HashBagOStuff( $params );
54 
55  $this->attrMap = $backend->attrMap;
56  }
57 
58  public function get( $key, $flags = 0 ) {
59  $value = $this->procCache->get( $key, $flags );
60  if ( $value !== false || $this->procCache->hasKey( $key ) ) {
61  return $value;
62  }
63 
64  $value = $this->store->proxyCall(
65  __FUNCTION__,
66  self::ARG0_KEY,
67  self::RES_NONKEY,
68  func_get_args(),
69  $this
70  );
71  $this->set( $key, $value, self::TTL_INDEFINITE, self::WRITE_CACHE_ONLY );
72 
73  return $value;
74  }
75 
76  public function getMulti( array $keys, $flags = 0 ) {
77  $valueByKeyCached = [];
78 
79  $keysFetch = [];
80  foreach ( $keys as $key ) {
81  $value = $this->procCache->get( $key, $flags );
82  if ( $value === false && !$this->procCache->hasKey( $key ) ) {
83  $keysFetch[] = $key;
84  } else {
85  $valueByKeyCached[$key] = $value;
86  }
87  }
88 
89  $valueByKeyFetched = $this->store->proxyCall(
90  __FUNCTION__,
91  self::ARG0_KEYARR,
92  self::RES_KEYMAP,
93  [ $keysFetch, $flags ],
94  $this
95  );
96  $this->setMulti( $valueByKeyFetched, self::TTL_INDEFINITE, self::WRITE_CACHE_ONLY );
97 
98  return $valueByKeyCached + $valueByKeyFetched;
99  }
100 
101  public function set( $key, $value, $exptime = 0, $flags = 0 ) {
102  $this->procCache->set( $key, $value, $exptime, $flags );
103 
104  if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
105  return true;
106  }
107 
108  return $this->store->proxyCall(
109  __FUNCTION__,
110  self::ARG0_KEY,
111  self::RES_NONKEY,
112  func_get_args(),
113  $this
114  );
115  }
116 
117  public function delete( $key, $flags = 0 ) {
118  $this->procCache->delete( $key, $flags );
119 
120  if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
121  return true;
122  }
123 
124  return $this->store->proxyCall(
125  __FUNCTION__,
126  self::ARG0_KEY,
127  self::RES_NONKEY,
128  func_get_args(),
129  $this
130  );
131  }
132 
133  public function add( $key, $value, $exptime = 0, $flags = 0 ) {
134  if ( $this->get( $key ) === false ) {
135  return $this->set( $key, $value, $exptime, $flags );
136  }
137 
138  return false; // key already set
139  }
140 
141  // These just call the backend (tested elsewhere)
142  // @codeCoverageIgnoreStart
143 
144  public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
145  $this->procCache->delete( $key );
146 
147  return $this->store->proxyCall(
148  __FUNCTION__,
149  self::ARG0_KEY,
150  self::RES_NONKEY,
151  func_get_args(),
152  $this
153  );
154  }
155 
156  public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
157  $this->procCache->delete( $key );
158 
159  return $this->store->proxyCall(
160  __FUNCTION__,
161  self::ARG0_KEY,
162  self::RES_NONKEY,
163  func_get_args(),
164  $this
165  );
166  }
167 
168  public function lock( $key, $timeout = 6, $exptime = 6, $rclass = '' ) {
169  return $this->store->proxyCall(
170  __FUNCTION__,
171  self::ARG0_KEY,
172  self::RES_NONKEY,
173  func_get_args(),
174  $this
175  );
176  }
177 
178  public function unlock( $key ) {
179  return $this->store->proxyCall(
180  __FUNCTION__,
181  self::ARG0_KEY,
182  self::RES_NONKEY,
183  func_get_args(),
184  $this
185  );
186  }
187 
189  $timestamp,
190  callable $progress = null,
191  $limit = INF,
192  string $tag = null
193  ) {
194  $this->procCache->deleteObjectsExpiringBefore( $timestamp, $progress, $limit, $tag );
195 
196  return $this->store->proxyCall(
197  __FUNCTION__,
198  self::ARG0_NONKEY,
199  self::RES_NONKEY,
200  func_get_args(),
201  $this
202  );
203  }
204 
205  public function makeKeyInternal( $keyspace, $components ) {
206  return $this->genericKeyFromComponents( $keyspace, ...$components );
207  }
208 
209  public function makeKey( $collection, ...$components ) {
210  return $this->genericKeyFromComponents( $this->keyspace, $collection, ...$components );
211  }
212 
213  public function makeGlobalKey( $collection, ...$components ) {
214  return $this->genericKeyFromComponents( self::GLOBAL_KEYSPACE, $collection, ...$components );
215  }
216 
217  protected function convertGenericKey( $key ) {
218  return $key; // short-circuit; already uses "generic" keys
219  }
220 
221  public function setMulti( array $valueByKey, $exptime = 0, $flags = 0 ) {
222  $this->procCache->setMulti( $valueByKey, $exptime, $flags );
223 
224  if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
225  return true;
226  }
227 
228  return $this->store->proxyCall(
229  __FUNCTION__,
230  self::ARG0_KEYMAP,
231  self::RES_NONKEY,
232  func_get_args(),
233  $this
234  );
235  }
236 
237  public function deleteMulti( array $keys, $flags = 0 ) {
238  $this->procCache->deleteMulti( $keys, $flags );
239 
240  if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
241  return true;
242  }
243 
244  return $this->store->proxyCall(
245  __FUNCTION__,
246  self::ARG0_KEYARR,
247  self::RES_NONKEY,
248  func_get_args(),
249  $this
250  );
251  }
252 
253  public function changeTTLMulti( array $keys, $exptime, $flags = 0 ) {
254  $this->procCache->changeTTLMulti( $keys, $exptime, $flags );
255 
256  if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) {
257  return true;
258  }
259 
260  return $this->store->proxyCall(
261  __FUNCTION__,
262  self::ARG0_KEYARR,
263  self::RES_NONKEY,
264  func_get_args(),
265  $this
266  );
267  }
268 
269  public function incr( $key, $value = 1, $flags = 0 ) {
270  $this->procCache->delete( $key );
271 
272  return $this->store->proxyCall(
273  __FUNCTION__,
274  self::ARG0_KEY,
275  self::RES_NONKEY,
276  func_get_args(),
277  $this
278  );
279  }
280 
281  public function decr( $key, $value = 1, $flags = 0 ) {
282  $this->procCache->delete( $key );
283 
284  return $this->store->proxyCall(
285  __FUNCTION__,
286  self::ARG0_KEY,
287  self::RES_NONKEY,
288  func_get_args(),
289  $this
290  );
291  }
292 
293  public function incrWithInit( $key, $exptime, $step = 1, $init = null, $flags = 0 ) {
294  $this->procCache->delete( $key );
295 
296  return $this->store->proxyCall(
297  __FUNCTION__,
298  self::ARG0_KEY,
299  self::RES_NONKEY,
300  func_get_args(),
301  $this
302  );
303  }
304 
305  public function addBusyCallback( callable $workCallback ) {
306  $this->store->addBusyCallback( $workCallback );
307  }
308 
309  public function setNewPreparedValues( array $valueByKey ) {
310  return $this->store->proxyCall(
311  __FUNCTION__,
312  self::ARG0_KEYMAP,
313  self::RES_NONKEY,
314  func_get_args(),
315  $this
316  );
317  }
318 
319  public function setMockTime( &$time ) {
320  parent::setMockTime( $time );
321  $this->procCache->setMockTime( $time );
322  $this->store->setMockTime( $time );
323  }
324 
325  // @codeCoverageIgnoreEnd
326 }
Class representing a cache/ephemeral data store.
Definition: BagOStuff.php:87
get( $key, $flags=0)
Get an item with the given key.
genericKeyFromComponents(... $components)
At a minimum, there must be a keyspace and collection name component.
Definition: BagOStuff.php:706
const WRITE_CACHE_ONLY
Definition: BagOStuff.php:122
string $keyspace
Default keyspace; used by makeKey()
Definition: BagOStuff.php:104
fieldHasFlags( $field, $flags)
Definition: BagOStuff.php:613
Wrapper around a BagOStuff that caches data in memory.
__construct(BagOStuff $backend, $params=[])
decr( $key, $value=1, $flags=0)
Decrease stored value of $key by $value while preserving its TTL.
getMulti(array $keys, $flags=0)
Get an associative array containing the item for each of the keys that have items.
makeGlobalKey( $collection,... $components)
Make a cache key for the default keyspace and given components.
unlock( $key)
Release an advisory lock on a key string.
makeKeyInternal( $keyspace, $components)
Make a cache key for the given keyspace and components.
deleteMulti(array $keys, $flags=0)
Batch deletion.
makeKey( $collection,... $components)
Make a cache key for the global keyspace and given components.
deleteObjectsExpiringBefore( $timestamp, callable $progress=null, $limit=INF, string $tag=null)
Delete all objects expiring before a certain date.
changeTTLMulti(array $keys, $exptime, $flags=0)
Change the expiration of multiple keys that exist.
setNewPreparedValues(array $valueByKey)
Stage a set of new key values for storage and estimate the amount of bytes needed.
add( $key, $value, $exptime=0, $flags=0)
Insert an item if it does not already exist.
HashBagOStuff $procCache
lock( $key, $timeout=6, $exptime=6, $rclass='')
Acquire an advisory lock on a key string, exclusive to the caller.
changeTTL( $key, $exptime=0, $flags=0)
Change the expiration on a key if it exists.
addBusyCallback(callable $workCallback)
Let a callback be run to avoid wasting time on special blocking calls.
merge( $key, callable $callback, $exptime=0, $attempts=10, $flags=0)
Merge changes into the existing cache value (possibly creating a new one)
setMulti(array $valueByKey, $exptime=0, $flags=0)
Batch insertion/replace.
incrWithInit( $key, $exptime, $step=1, $init=null, $flags=0)
Increase the value of the given key (no TTL change) if it exists or create it otherwise.
incr( $key, $value=1, $flags=0)
Increase stored value of $key by $value while preserving its TTL.
convertGenericKey( $key)
Convert a "generic" reversible cache key into one for this cache.
Simple store for keeping values in an associative array for the current process.