PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 1.2.7
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v1.2.7
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / dropins / memcache-object-cache.php

memcache-object-cache.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 1.2.7, at includes/dropins/memcache-object-cache.php

460 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || exit;
3
4 // We need Memcache to continue
5 if ( class_exists( 'Memcache' ) ):
6
7 /**
8 * Copyright (C) 2016 Ryan Boren, Denis de Bernardy, Matt Martz
9 */
10
11 if ( ! defined( 'WP_CACHE_KEY_SALT' ) ) {
12 define( 'WP_CACHE_KEY_SALT', DB_NAME );
13 }
14
15 function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
16
17 global $wp_object_cache;
18
19 return $wp_object_cache->add( $key, $data, $group, $expire );
20 }
21
22 function wp_cache_incr( $key, $n = 1, $group = '' ) {
23
24 global $wp_object_cache;
25
26 return $wp_object_cache->incr( $key, $n, $group );
27 }
28
29 function wp_cache_decr( $key, $n = 1, $group = '' ) {
30
31 global $wp_object_cache;
32
33 return $wp_object_cache->decr( $key, $n, $group );
34 }
35
36 function wp_cache_close() {
37
38 global $wp_object_cache;
39
40 return $wp_object_cache->close();
41 }
42
43 function wp_cache_delete( $key, $group = '' ) {
44
45 global $wp_object_cache;
46
47 return $wp_object_cache->delete( $key, $group );
48 }
49
50 function wp_cache_flush() {
51
52 global $wp_object_cache;
53
54 return $wp_object_cache->flush();
55 }
56
57 function wp_cache_get( $key, $group = '', $force = false ) {
58
59 global $wp_object_cache;
60
61 return $wp_object_cache->get( $key, $group, $force );
62 }
63
64 function wp_cache_init() {
65
66 global $wp_object_cache;
67
68 $wp_object_cache = new WP_Object_Cache();
69 }
70
71 function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) {
72
73 global $wp_object_cache;
74
75 return $wp_object_cache->replace( $key, $data, $group, $expire );
76 }
77
78 function wp_cache_set( $key, $data, $group = '', $expire = 0 ) {
79
80 global $wp_object_cache;
81
82 if ( defined( 'WP_INSTALLING' ) == false ) {
83 return $wp_object_cache->set( $key, $data, $group, $expire );
84 } else {
85 return $wp_object_cache->delete( $key, $group );
86 }
87 }
88
89 function wp_cache_switch_to_blog( $blog_id ) {
90
91 global $wp_object_cache;
92
93 return $wp_object_cache->switch_to_blog( $blog_id );
94 }
95
96 function wp_cache_add_global_groups( $groups ) {
97
98 global $wp_object_cache;
99
100 $wp_object_cache->add_global_groups( $groups );
101 }
102
103 function wp_cache_add_non_persistent_groups( $groups ) {
104
105 global $wp_object_cache;
106
107 $wp_object_cache->add_non_persistent_groups( $groups );
108 }
109
110 class WP_Object_Cache {
111 var $global_groups = array();
112
113 var $no_mc_groups = array();
114
115 var $cache = array();
116 var $mc = array();
117 var $stats = array();
118 var $group_ops = array();
119
120 var $cache_enabled = true;
121 var $default_expiration = 0;
122
123 function add( $id, $data, $group = 'default', $expire = 0 ) {
124
125 $key = $this->key( $id, $group );
126
127 if ( is_object( $data ) ) {
128 $data = clone $data;
129 }
130
131 if ( in_array( $group, $this->no_mc_groups ) ) {
132 $this->cache[ $key ] = $data;
133 return true;
134 } elseif ( isset( $this->cache[ $key ] ) && $this->cache[ $key ] !== false ) {
135 return false;
136 }
137
138 $mc =& $this->get_mc( $group );
139 $expire = ($expire == 0) ? $this->default_expiration : $expire;
140 $result = $mc->add( $key, $data, false, $expire );
141
142 if ( false !== $result ) {
143 @ ++$this->stats['add'];
144 $this->group_ops[ $group ][] = "add $id";
145 $this->cache[ $key ] = $data;
146 }
147
148 return $result;
149 }
150
151 function add_global_groups( $groups ) {
152
153 if ( ! is_array( $groups ) ) {
154 $groups = (array) $groups;
155 }
156
157 $this->global_groups = array_merge( $this->global_groups, $groups );
158 $this->global_groups = array_unique( $this->global_groups );
159 }
160
161 function add_non_persistent_groups( $groups ) {
162
163 if ( ! is_array( $groups ) ) {
164 $groups = (array) $groups;
165 }
166
167 $this->no_mc_groups = array_merge( $this->no_mc_groups, $groups );
168 $this->no_mc_groups = array_unique( $this->no_mc_groups );
169 }
170
171 function incr( $id, $n = 1, $group = 'default' ) {
172
173 $key = $this->key( $id, $group );
174 $mc =& $this->get_mc( $group );
175 $this->cache[ $key ] = $mc->increment( $key, $n );
176 return $this->cache[ $key ];
177 }
178
179 function decr( $id, $n = 1, $group = 'default' ) {
180
181 $key = $this->key( $id, $group );
182 $mc =& $this->get_mc( $group );
183 $this->cache[ $key ] = $mc->decrement( $key, $n );
184 return $this->cache[ $key ];
185 }
186
187 function close() {
188
189 foreach ( $this->mc as $bucket => $mc ) {
190 $mc->close();
191 }
192 }
193
194 function delete( $id, $group = 'default' ) {
195
196 $key = $this->key( $id, $group );
197
198 if ( in_array( $group, $this->no_mc_groups ) ) {
199 unset( $this->cache[ $key ] );
200 return true;
201 }
202
203 $mc =& $this->get_mc( $group );
204
205 $result = $mc->delete( $key );
206
207 @ ++$this->stats['delete'];
208 $this->group_ops[ $group ][] = "delete $id";
209
210 if ( false !== $result ) {
211 unset( $this->cache[ $key ] );
212 }
213
214 return $result;
215 }
216
217 function flush() {
218 $ret = true;
219 foreach ( array_keys( $this->mc ) as $group ) {
220 $ret &= $this->mc[ $group ]->flush();
221 }
222 return $ret;
223 }
224
225 function get( $id, $group = 'default', $force = false ) {
226
227 $key = $this->key( $id, $group );
228 $mc =& $this->get_mc( $group );
229
230 if ( isset( $this->cache[ $key ] ) && ( ! $force || in_array( $group, $this->no_mc_groups ) ) ) {
231 if ( is_object( $this->cache[ $key ] ) ) {
232 $value = clone $this->cache[ $key ];
233 } else {
234 $value = $this->cache[ $key ];
235 }
236 } else if ( in_array( $group, $this->no_mc_groups ) ) {
237 $this->cache[ $key ] = $value = false;
238 } else {
239 $value = $mc->get( $key );
240 if ( null === $value ) {
241 $value = false;
242 }
243 $this->cache[ $key ] = $value;
244 }
245
246 @ ++$this->stats['get'];
247 $this->group_ops[ $group ][] = "get $id";
248
249 if ( 'checkthedatabaseplease' === $value ) {
250 unset( $this->cache[ $key ] );
251 $value = false;
252 }
253
254 return $value;
255 }
256
257 function get_multi( $groups ) {
258
259 /*
260 format: $get['group-name'] = array( 'key1', 'key2' );
261 */
262 $return = array();
263 foreach ( $groups as $group => $ids ) {
264 $mc =& $this->get_mc( $group );
265 foreach ( $ids as $id ) {
266 $key = $this->key( $id, $group );
267 if ( isset( $this->cache[ $key ] ) ) {
268 if ( is_object( $this->cache[ $key ] ) ) {
269 $return[ $key ] = clone $this->cache[ $key ];
270 } else {
271 $return[ $key ] = $this->cache[ $key ];
272 }
273 continue;
274 } else if ( in_array( $group, $this->no_mc_groups ) ) {
275 $return[ $key ] = false;
276 continue;
277 } else {
278 $return[ $key ] = $mc->get( $key );
279 }
280 }
281 if ( $to_get ) {
282 $vals = $mc->get_multi( $to_get );
283 $return = array_merge( $return, $vals );
284 }
285 }
286 @ ++$this->stats['get_multi'];
287 $this->group_ops[ $group ][] = "get_multi $id";
288 $this->cache = array_merge( $this->cache, $return );
289 return $return;
290 }
291
292 function key( $key, $group ) {
293
294 if ( empty( $group ) ) {
295 $group = 'default';
296 }
297
298 if ( false !== array_search( $group, $this->global_groups ) ) {
299 $prefix = $this->global_prefix;
300 } else {
301 $prefix = $this->blog_prefix;
302 }
303
304 return preg_replace( '/\s+/', '', WP_CACHE_KEY_SALT . "$prefix$group:$key" );
305 }
306
307 function replace( $id, $data, $group = 'default', $expire = 0 ) {
308
309 $key = $this->key( $id, $group );
310 $expire = ($expire == 0) ? $this->default_expiration : $expire;
311 $mc =& $this->get_mc( $group );
312
313 if ( is_object( $data ) ) {
314 $data = clone $data;
315 }
316
317 $result = $mc->replace( $key, $data, false, $expire );
318 if ( false !== $result ) {
319 $this->cache[ $key ] = $data;
320 }
321 return $result;
322 }
323
324 function set( $id, $data, $group = 'default', $expire = 0 ) {
325
326 $key = $this->key( $id, $group );
327 if ( isset( $this->cache[ $key ] ) && ('checkthedatabaseplease' === $this->cache[ $key ]) ) {
328 return false;
329 }
330
331 if ( is_object( $data ) ) {
332 $data = clone $data;
333 }
334
335 $this->cache[ $key ] = $data;
336
337 if ( in_array( $group, $this->no_mc_groups ) ) {
338 return true;
339 }
340
341 $expire = ($expire == 0) ? $this->default_expiration : $expire;
342 $mc =& $this->get_mc( $group );
343 $result = $mc->set( $key, $data, false, $expire );
344
345 return $result;
346 }
347
348 function switch_to_blog( $blog_id ) {
349
350 global $table_prefix;
351
352 $blog_id = (int) $blog_id;
353 $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':';
354 }
355
356 function colorize_debug_line( $line ) {
357
358 $colors = array(
359 'get' => 'green',
360 'set' => 'purple',
361 'add' => 'blue',
362 'delete' => 'red',
363 );
364
365 $cmd = substr( $line, 0, strpos( $line, ' ' ) );
366
367 $cmd2 = "<span style='color:{$colors[$cmd]}'>$cmd</span>";
368
369 return $cmd2 . substr( $line, strlen( $cmd ) ) . "\n";
370 }
371
372 function stats() {
373
374 echo "<p>\n";
375 foreach ( $this->stats as $stat => $n ) {
376 echo "<strong>$stat</strong> $n";
377 echo "<br/>\n";
378 }
379 echo "</p>\n";
380 echo '<h3>Memcached:</h3>';
381 foreach ( $this->group_ops as $group => $ops ) {
382 if ( ! isset( $_GET['debug_queries'] ) && 500 < count( $ops ) ) {
383 $ops = array_slice( $ops, 0, 500 );
384 echo "<big>Too many to show! <a href='" . add_query_arg( 'debug_queries', 'true' ) . "'>Show them anyway</a>.</big>\n";
385 }
386 echo "<h4>$group commands</h4>";
387 echo "<pre>\n";
388 $lines = array();
389 foreach ( $ops as $op ) {
390 $lines[] = $this->colorize_debug_line( $op );
391 }
392 print_r( $lines );
393 echo "</pre>\n";
394 }
395 }
396
397 function &get_mc( $group ) {
398
399 if ( isset( $this->mc[ $group ] ) ) {
400 return $this->mc[ $group ];
401 }
402 return $this->mc['default'];
403 }
404
405 function failure_callback( $host, $port ) {
406
407 //error_log("Connection failure for $host:$port\n", 3, '/tmp/memcached.txt');
408 }
409
410 function __construct() {
411
412 global $memcached_servers;
413
414 if ( isset( $memcached_servers ) ) {
415 $buckets = $memcached_servers;
416 } else {
417 $buckets = array( '127.0.0.1:11211' );
418 }
419
420 reset( $buckets );
421 if ( is_int( key( $buckets ) ) ) {
422 $buckets = array( 'default' => $buckets );
423 }
424
425 foreach ( $buckets as $bucket => $servers ) {
426 $this->mc[ $bucket ] = new Memcache();
427 foreach ( $servers as $server ) {
428 if ( 'unix://' == substr( $server, 0, 7 ) ) {
429 $node = $server;
430 $port = 0;
431 } else {
432 list ( $node, $port ) = explode( ':', $server );
433 if ( ! $port ) {
434 $port = ini_get( 'memcache.default_port' );
435 }
436 $port = intval( $port );
437 if ( ! $port ) {
438 $port = 11211;
439 }
440 }
441 $this->mc[ $bucket ]->addServer( $node, $port, true, 1, 1, 15, true, array( $this, 'failure_callback' ) );
442 $this->mc[ $bucket ]->setCompressThreshold( 20000, 0.2 );
443 }
444 }
445
446 global $blog_id, $table_prefix;
447 $this->global_prefix = '';
448 $this->blog_prefix = '';
449 if ( function_exists( 'is_multisite' ) ) {
450 $this->global_prefix = ( is_multisite() || defined( 'CUSTOM_USER_TABLE' ) && defined( 'CUSTOM_USER_META_TABLE' ) ) ? '' : $table_prefix;
451 $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':';
452 }
453
454 $this->cache_hits =& $this->stats['get'];
455 $this->cache_misses =& $this->stats['add'];
456 }
457 }
458 endif;
459 ?>
460