Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
66.07% |
37 / 56 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
CachedBagOStuff | |
66.07% |
37 / 56 |
|
66.67% |
4 / 6 |
55.47 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
get | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
3 | |||
getMulti | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
set | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
delete | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
add | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
merge | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
changeTTL | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
lock | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
unlock | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
deleteObjectsExpiringBefore | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
setMulti | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
deleteMulti | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
changeTTLMulti | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
incrWithInit | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
setMockTime | n/a |
0 / 0 |
n/a |
0 / 0 |
1 |
1 | <?php |
2 | /** |
3 | * Wrapper around a BagOStuff that caches data in memory |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @ingroup Cache |
22 | */ |
23 | |
24 | /** |
25 | * Wrapper around a BagOStuff that caches data in memory |
26 | * |
27 | * The differences between CachedBagOStuff and MultiWriteBagOStuff are: |
28 | * * CachedBagOStuff supports only one "backend". |
29 | * * There's a flag for writes to only go to the in-memory cache. |
30 | * * The in-memory cache is always updated. |
31 | * * Locks go to the backend cache (with MultiWriteBagOStuff, it would wind |
32 | * up going to the HashBagOStuff used for the in-memory cache). |
33 | * |
34 | * @newable |
35 | * @ingroup Cache |
36 | */ |
37 | class CachedBagOStuff extends BagOStuff { |
38 | /** @var BagOStuff */ |
39 | protected $store; |
40 | /** @var HashBagOStuff */ |
41 | protected $procCache; |
42 | |
43 | /** |
44 | * @stable to call |
45 | * @param BagOStuff $backend Permanent backend to use |
46 | * @param array $params Parameters for HashBagOStuff |
47 | */ |
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 | // key already set |
139 | return false; |
140 | } |
141 | |
142 | // These just call the backend (tested elsewhere) |
143 | // @codeCoverageIgnoreStart |
144 | |
145 | public function merge( $key, callable $callback, $exptime = 0, $attempts = 10, $flags = 0 ) { |
146 | $this->procCache->delete( $key ); |
147 | |
148 | return $this->store->proxyCall( |
149 | __FUNCTION__, |
150 | self::ARG0_KEY, |
151 | self::RES_NONKEY, |
152 | func_get_args(), |
153 | $this |
154 | ); |
155 | } |
156 | |
157 | public function changeTTL( $key, $exptime = 0, $flags = 0 ) { |
158 | $this->procCache->delete( $key ); |
159 | |
160 | return $this->store->proxyCall( |
161 | __FUNCTION__, |
162 | self::ARG0_KEY, |
163 | self::RES_NONKEY, |
164 | func_get_args(), |
165 | $this |
166 | ); |
167 | } |
168 | |
169 | public function lock( $key, $timeout = 6, $exptime = 6, $rclass = '' ) { |
170 | return $this->store->proxyCall( |
171 | __FUNCTION__, |
172 | self::ARG0_KEY, |
173 | self::RES_NONKEY, |
174 | func_get_args(), |
175 | $this |
176 | ); |
177 | } |
178 | |
179 | public function unlock( $key ) { |
180 | return $this->store->proxyCall( |
181 | __FUNCTION__, |
182 | self::ARG0_KEY, |
183 | self::RES_NONKEY, |
184 | func_get_args(), |
185 | $this |
186 | ); |
187 | } |
188 | |
189 | public function deleteObjectsExpiringBefore( |
190 | $timestamp, |
191 | callable $progress = null, |
192 | $limit = INF, |
193 | string $tag = null |
194 | ) { |
195 | $this->procCache->deleteObjectsExpiringBefore( $timestamp, $progress, $limit, $tag ); |
196 | |
197 | return $this->store->proxyCall( |
198 | __FUNCTION__, |
199 | self::ARG0_NONKEY, |
200 | self::RES_NONKEY, |
201 | func_get_args(), |
202 | $this |
203 | ); |
204 | } |
205 | |
206 | public function setMulti( array $valueByKey, $exptime = 0, $flags = 0 ) { |
207 | $this->procCache->setMulti( $valueByKey, $exptime, $flags ); |
208 | |
209 | if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) { |
210 | return true; |
211 | } |
212 | |
213 | return $this->store->proxyCall( |
214 | __FUNCTION__, |
215 | self::ARG0_KEYMAP, |
216 | self::RES_NONKEY, |
217 | func_get_args(), |
218 | $this |
219 | ); |
220 | } |
221 | |
222 | public function deleteMulti( array $keys, $flags = 0 ) { |
223 | $this->procCache->deleteMulti( $keys, $flags ); |
224 | |
225 | if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) { |
226 | return true; |
227 | } |
228 | |
229 | return $this->store->proxyCall( |
230 | __FUNCTION__, |
231 | self::ARG0_KEYARR, |
232 | self::RES_NONKEY, |
233 | func_get_args(), |
234 | $this |
235 | ); |
236 | } |
237 | |
238 | public function changeTTLMulti( array $keys, $exptime, $flags = 0 ) { |
239 | $this->procCache->changeTTLMulti( $keys, $exptime, $flags ); |
240 | |
241 | if ( $this->fieldHasFlags( $flags, self::WRITE_CACHE_ONLY ) ) { |
242 | return true; |
243 | } |
244 | |
245 | return $this->store->proxyCall( |
246 | __FUNCTION__, |
247 | self::ARG0_KEYARR, |
248 | self::RES_NONKEY, |
249 | func_get_args(), |
250 | $this |
251 | ); |
252 | } |
253 | |
254 | public function incrWithInit( $key, $exptime, $step = 1, $init = null, $flags = 0 ) { |
255 | $this->procCache->delete( $key ); |
256 | |
257 | return $this->store->proxyCall( |
258 | __FUNCTION__, |
259 | self::ARG0_KEY, |
260 | self::RES_NONKEY, |
261 | func_get_args(), |
262 | $this |
263 | ); |
264 | } |
265 | |
266 | public function setMockTime( &$time ) { |
267 | parent::setMockTime( $time ); |
268 | $this->procCache->setMockTime( $time ); |
269 | $this->store->setMockTime( $time ); |
270 | } |
271 | |
272 | // @codeCoverageIgnoreEnd |
273 | } |