3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
20 namespace Wikimedia\ObjectCache
;
23 * Wrap any BagOStuff and add an in-process memory cache to it.
25 * The differences between CachedBagOStuff and MultiWriteBagOStuff are:
26 * - CachedBagOStuff supports only one "backend".
27 * - There's a flag for writes to only go to the in-memory cache.
28 * - The in-memory cache is always updated.
29 * - Locks go to the backend cache (with MultiWriteBagOStuff, it would wind
30 * up going to the HashBagOStuff used for the in-memory cache).
35 class CachedBagOStuff
extends BagOStuff
{
38 /** @var HashBagOStuff */
44 * @param BagOStuff $backend Permanent backend to use
45 * @param array $params Parameters for HashBagOStuff
47 public function __construct( BagOStuff
$backend, $params = [] ) {
48 $params['keyspace'] = $backend->keyspace
;
49 parent
::__construct( $params );
51 $this->store
= $backend;
52 $this->procCache
= new HashBagOStuff( $params );
54 $this->attrMap
= $backend->attrMap
;
57 public function get( $key, $flags = 0 ) {
58 $value = $this->procCache
->get( $key, $flags );
59 if ( $value !== false ||
$this->procCache
->hasKey( $key ) ) {
63 $value = $this->store
->proxyCall(
70 $this->set( $key, $value, self
::TTL_INDEFINITE
, self
::WRITE_CACHE_ONLY
);
75 public function getMulti( array $keys, $flags = 0 ) {
76 $valueByKeyCached = [];
79 foreach ( $keys as $key ) {
80 $value = $this->procCache
->get( $key, $flags );
81 if ( $value === false && !$this->procCache
->hasKey( $key ) ) {
84 $valueByKeyCached[$key] = $value;
88 $valueByKeyFetched = $this->store
->proxyCall(
92 [ $keysFetch, $flags ],
95 $this->setMulti( $valueByKeyFetched, self
::TTL_INDEFINITE
, self
::WRITE_CACHE_ONLY
);
97 return $valueByKeyCached +
$valueByKeyFetched;
100 public function set( $key, $value, $exptime = 0, $flags = 0 ) {
101 $this->procCache
->set( $key, $value, $exptime, $flags );
103 if ( $this->fieldHasFlags( $flags, self
::WRITE_CACHE_ONLY
) ) {
107 return $this->store
->proxyCall(
116 public function delete( $key, $flags = 0 ) {
117 $this->procCache
->delete( $key, $flags );
119 if ( $this->fieldHasFlags( $flags, self
::WRITE_CACHE_ONLY
) ) {
123 return $this->store
->proxyCall(
132 public function add( $key, $value, $exptime = 0, $flags = 0 ) {
133 if ( $this->get( $key ) === false ) {
134 return $this->set( $key, $value, $exptime, $flags );
141 // These just call the backend (tested elsewhere)
142 // @codeCoverageIgnoreStart
144 public function merge( $key, callable
$callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
145 $this->procCache
->delete( $key );
147 return $this->store
->proxyCall(
156 public function changeTTL( $key, $exptime = 0, $flags = 0 ) {
157 $this->procCache
->delete( $key );
159 return $this->store
->proxyCall(
168 public function lock( $key, $timeout = 6, $exptime = 6, $rclass = '' ) {
169 return $this->store
->proxyCall(
178 public function unlock( $key ) {
179 return $this->store
->proxyCall(
188 public function deleteObjectsExpiringBefore(
190 ?callable
$progress = null,
194 $this->procCache
->deleteObjectsExpiringBefore( $timestamp, $progress, $limit, $tag );
196 return $this->store
->proxyCall(
205 public function setMulti( array $valueByKey, $exptime = 0, $flags = 0 ) {
206 $this->procCache
->setMulti( $valueByKey, $exptime, $flags );
208 if ( $this->fieldHasFlags( $flags, self
::WRITE_CACHE_ONLY
) ) {
212 return $this->store
->proxyCall(
221 public function deleteMulti( array $keys, $flags = 0 ) {
222 $this->procCache
->deleteMulti( $keys, $flags );
224 if ( $this->fieldHasFlags( $flags, self
::WRITE_CACHE_ONLY
) ) {
228 return $this->store
->proxyCall(
237 public function changeTTLMulti( array $keys, $exptime, $flags = 0 ) {
238 $this->procCache
->changeTTLMulti( $keys, $exptime, $flags );
240 if ( $this->fieldHasFlags( $flags, self
::WRITE_CACHE_ONLY
) ) {
244 return $this->store
->proxyCall(
253 public function incrWithInit( $key, $exptime, $step = 1, $init = null, $flags = 0 ) {
254 $this->procCache
->delete( $key );
256 return $this->store
->proxyCall(
265 public function setMockTime( &$time ) {
266 parent
::setMockTime( $time );
267 $this->procCache
->setMockTime( $time );
268 $this->store
->setMockTime( $time );
271 // @codeCoverageIgnoreEnd
274 /** @deprecated class alias since 1.43 */
275 class_alias( CachedBagOStuff
::class, 'CachedBagOStuff' );