PluginProbe
Seraphinite Accelerator / trunk
Seraphinite Accelerator vtrunk
2.29.24 2.29.23 2.29.22 2.29.21 2.29.20 2.29.19 2.29.18 2.29.17 2.29.16 2.29.15 2.29.14 2.29.13 2.29.12 2.29.11 2.29.10 2.29.9 2.20.18 2.20.19 2.20.2 2.20.20 2.20.21 2.20.22 2.20.23 2.20.24 2.20.25 All 418 releases
seraphinite-accelerator / cache_obj.php

cache_obj.php in Seraphinite Accelerator trunk, at cache_obj.php

685 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if( !defined( 'ABSPATH' ) )
4 exit;
5
6 if( !defined( 'SERAPH_ACCEL_PLUGIN_DIR' ) ) define( 'SERAPH_ACCEL_PLUGIN_DIR', __DIR__ ); else if( SERAPH_ACCEL_PLUGIN_DIR != __DIR__ ) return;
7
8 require_once( __DIR__ . '/common.php' );
9
10 function wp_cache_add_global_groups( $groups )
11 {
12 global $wp_object_cache;
13 $wp_object_cache -> add_global_groups( $groups );
14 }
15
16 function wp_cache_add_non_persistent_groups( $groups )
17 {
18 global $wp_object_cache;
19 $wp_object_cache -> add_non_persistent_groups( $groups );
20 }
21
22 function wp_cache_supports( $feature )
23 {
24 static $g_aFeature = array( 'add_multiple' => 1, 'set_multiple' => 1, 'get_multiple' => 1, 'delete_multiple' => 1, 'flush_runtime' => 1, 'flush_group' => 1 );
25 return( isset( $g_aFeature[ $feature ] ) );
26 }
27
28 function wp_cache_init()
29 {
30 global $wp_object_cache;
31 $wp_object_cache = new WP_Object_Cache();
32
33 global $batcache;
34 if( $batcache && method_exists( $batcache, 'configure_groups' ) )
35 $batcache -> configure_groups();
36 }
37
38 function wp_cache_add( $key, $data, $group = '', $expire = 0 )
39 {
40 global $wp_object_cache;
41 return( $wp_object_cache -> add( $key, $data, $group, $expire ) );
42 }
43
44 function wp_cache_add_multiple( array $data, $group = '', $expire = 0 )
45 {
46 global $wp_object_cache;
47 return( $wp_object_cache -> add_multiple( $data, $group, $expire ) );
48 }
49
50 function wp_cache_replace( $key, $data, $group = '', $expire = 0 )
51 {
52 global $wp_object_cache;
53 return( $wp_object_cache -> replace( $key, $data, $group, $expire ) );
54 }
55
56 function wp_cache_set( $key, $data, $group = '', $expire = 0 )
57 {
58 global $wp_object_cache;
59 return( $wp_object_cache -> set( $key, $data, $group, $expire ) );
60 }
61
62 function wp_cache_set_multiple( array $data, $group = '', $expire = 0 )
63 {
64 global $wp_object_cache;
65 return( $wp_object_cache -> set_multiple( $data, $group, $expire ) );
66 }
67
68 function wp_cache_get( $key, $group = '', $force = false, &$found = null )
69 {
70 global $wp_object_cache;
71 return( $wp_object_cache -> get( $key, $group, $force, $found ) );
72 }
73
74 function wp_cache_get_multiple( $keys, $group = '', $force = false )
75 {
76 global $wp_object_cache;
77 return( $wp_object_cache -> get_multiple( $keys, $group, $force ) );
78 }
79
80 function wp_cache_delete( $key, $group = '' )
81 {
82 global $wp_object_cache;
83 return( $wp_object_cache -> delete( $key, $group ) );
84 }
85
86 function wp_cache_delete_multiple( array $keys, $group = '' )
87 {
88 global $wp_object_cache;
89 return( $wp_object_cache -> delete_multiple( $keys, $group ) );
90 }
91
92 function wp_cache_incr( $key, $offset = 1, $group = '' )
93 {
94 global $wp_object_cache;
95 return( $wp_object_cache -> incr( $key, $offset, $group ) );
96 }
97
98 function wp_cache_decr( $key, $offset = 1, $group = '' )
99 {
100 global $wp_object_cache;
101 return( $wp_object_cache -> decr( $key, $offset, $group ) );
102 }
103
104 function wp_cache_flush()
105 {
106 global $wp_object_cache;
107 return( $wp_object_cache -> flush() );
108 }
109
110 function wp_cache_flush_runtime()
111 {
112 return( wp_cache_flush() );
113 }
114
115 function wp_cache_flush_group( $group )
116 {
117 global $wp_object_cache;
118 return( $wp_object_cache -> flush_group( $group ) );
119 }
120
121 function wp_cache_close()
122 {
123 return( true );
124 }
125
126 function wp_cache_switch_to_blog( $blog_id )
127 {
128 global $wp_object_cache;
129 $wp_object_cache -> switch_to_blog( $blog_id );
130 }
131
132 function wp_cache_reset()
133 {
134 global $wp_object_cache;
135 $wp_object_cache -> reset();
136 }
137
138 class WP_Object_Cache
139 {
140 public $nHits = 0;
141 public $nMisses = 0;
142
143 protected $aGlobalGroup = array();
144 protected $aNonPersistentGroup = array();
145
146 private $aData = array();
147 private $inited;
148 private $curSite;
149 private $curSiteId;
150 private $dataDir;
151 private $lock;
152
153 public function __construct()
154 {
155 }
156
157 function __destruct()
158 {
159
160 }
161
162 public function add_global_groups( $groups )
163 {
164 $this -> aGlobalGroup = array_merge( $this -> aGlobalGroup, array_fill_keys( ( array )$groups, true ) );
165 }
166
167 public function add_non_persistent_groups( $groups )
168 {
169 $this -> aNonPersistentGroup = array_merge( $this -> aNonPersistentGroup, array_fill_keys( ( array )$groups, true ) );
170 }
171
172 protected function _init()
173 {
174 if( $this -> inited )
175 return;
176
177 global $seraph_accel_settObjCache;
178
179 $this -> inited = true;
180
181 if( is_multisite() && function_exists( 'get_current_site' ) )
182 {
183 $this -> curSite = get_current_site();
184 $this -> curSite = new \seraph_accel\AnyObj( array( 'blog_id' => get_current_blog_id(), 'site_id' => $this -> curSite -> site_id ) );
185 $this -> curSite -> blog_id_orig = $this -> curSite -> blog_id;
186 }
187 else
188 $this -> curSite = null;
189 $this -> curSiteId = \seraph_accel\GetSiteId( $this -> curSite );
190
191 $dataDir = \seraph_accel\GetCacheDir() . '/oc';
192 $this -> lock = new \seraph_accel\Lock( $dataDir . '/l', false );
193 $this -> dataDir = $dataDir . '/g';
194
195 $this -> add_global_groups( \seraph_accel\Gen::GetArrField( $seraph_accel_settObjCache, array( 'cacheObj', 'groupsGlobal' ), array() ) );
196 $this -> add_non_persistent_groups( \seraph_accel\Gen::GetArrField( $seraph_accel_settObjCache, array( 'cacheObj', 'groupsNonPersistent' ), array() ) );
197
198 add_filter( 'pre_cache_alloptions',
199 function( $alloptions )
200 {
201 unset( $alloptions[ 'cron' ] );
202 return( $alloptions );
203 }
204 , PHP_INT_MAX );
205
206 add_action( 'added_option', array( $this, '_clnWpOption' ), PHP_INT_MAX );
207 add_action( 'updated_option', array( $this, '_clnWpOption' ), PHP_INT_MAX );
208 add_action( 'deleted_option', array( $this, '_clnWpOption' ), PHP_INT_MAX );
209 }
210
211 function _clnWpOption( $option )
212 {
213 if( wp_installing() )
214 return;
215
216 $alloptions = wp_load_alloptions();
217 if( isset( $alloptions[ $option ] ) )
218 add_action( 'shutdown', array( $this, '_delWpAllOptions' ), PHP_INT_MAX - 1 );
219 unset( $alloptions );
220 }
221
222 function _delWpAllOptions()
223 {
224 $this -> delete( 'alloptions', 'options' );
225 }
226
227 protected function _getPath( $group, $key )
228 {
229 return( array( empty( $group ) ? '@' : $group, isset( $this -> aGlobalGroup[ $group ] ) ? 'g' : 's/' . $this -> curSiteId, $key ) );
230 }
231
232 protected static function _normPath( &$path )
233 {
234 if( strlen( $path ) > 200 )
235 $path = md5( $path );
236 else
237 $path = str_replace( array( ':', '?', '|', '&', '=', '#' ), array( '@', '@', '~', '+', '-', '@' ), $path );
238 }
239
240 protected static function _normExpiration( $expire )
241 {
242 global $seraph_accel_settObjCache;
243
244 $nMax = \seraph_accel\Gen::GetArrField( $seraph_accel_settObjCache, array( 'cacheObj', 'timeout' ), 60 );
245
246 $expire = ( int )$expire;
247 if( $expire <= 0 || $expire > $nMax )
248 $expire = $nMax;
249
250 return( $expire );
251 }
252
253 protected function _getFilePath( $aPath )
254 {
255 self::_normPath( $aPath[ 0 ] );
256 self::_normPath( $aPath[ count( $aPath ) - 1 ] );
257 return( $this -> dataDir . '/' . implode( '/', $aPath ) . '.dat.gz' );
258 }
259
260 private function _updateFromStg( $aPath )
261 {
262
263 $file = $this -> _getFilePath( $aPath );
264
265 $v = null;
266 if( ( $lr = $this -> lock -> Acquire() ) !== false )
267 {
268 $v = @file_exists( $file ) ? array( @file_get_contents( $file ), @filemtime( $file ) ) : null;
269 if( $lr )
270 $this -> lock -> Release();
271
272 if( $v !== null )
273 {
274 if( is_string( $v[ 0 ] ) && is_int( $v[ 1 ] ) )
275 {
276 if( is_string( $v[ 0 ] = @gzdecode( $v[ 0 ] ) ) )
277 {
278 $bOk = false;
279 $v[ 0 ] = \seraph_accel\Gen::Unserialize( $v[ 0 ], null, $bOk );
280 if( !$bOk )
281 $v = null;
282 }
283 else
284 $v = null;
285 }
286 else
287 $v = null;
288 }
289 }
290
291 if( $v !== null )
292 \seraph_accel\Gen::SetArrField( $this -> aData, $aPath, $v );
293 else
294 \seraph_accel\Gen::UnsetArrField( $this -> aData, $aPath );
295
296 return( $v );
297
298 }
299
300 private function _updateToStg( $aPath, $v )
301 {
302
303 $file = $this -> _getFilePath( $aPath );
304
305 if( $v === null )
306 {
307 if( ( $lr = $this -> lock -> Acquire() ) === false )
308 return( false );
309
310 if( @file_exists( $file ) )
311 @unlink( $file );
312
313 if( $lr )
314 $this -> lock -> Release();
315
316 return( true );
317 }
318
319 if( !is_string( $data = \seraph_accel\Gen::Serialize( $v[ 0 ] ) ) )
320 return( false );
321 if( !is_string( $data = @gzencode( $data, 9 ) ) )
322 return( false );
323
324 if( ( $lr = $this -> lock -> Acquire() ) === false )
325 return( false );
326
327 \seraph_accel\Gen::MakeDir( @dirname( $file ), true );
328 $res = \seraph_accel\Gen::FileWriteTmpAndReplace( $this -> lock, $file, $data, $v[ 1 ] );
329
330 if( $lr )
331 $this -> lock -> Release();
332
333 return( $res );
334
335 }
336
337 public function __get( $name )
338 {
339 return $this -> $name;
340 }
341
342 public function __set( $name, $value )
343 {
344 $this -> $name = $value;
345 }
346
347 public function __isset( $name )
348 {
349 return isset( $this -> $name );
350 }
351
352 public function __unset( $name )
353 {
354 unset( $this -> $name );
355 }
356
357 static protected function _is_valid_key( $key )
358 {
359 if( is_int( $key ) )
360 return( true );
361
362 if( is_string( $key ) && trim( $key ) !== '' )
363 return( true );
364
365 return( false );
366 }
367
368 protected function _add( $bSetExist, $key, $data, $group, $expire, $time )
369 {
370
371 if( !self::_is_valid_key( $key ) )
372 return( false );
373
374 $aPath = $this -> _getPath( $group, $key );
375 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
376
377 $v = \seraph_accel\Gen::GetArrField( $this -> aData, $aPath );
378 if( $v === null && !$bNonPersistentGroup )
379 $v = $this -> _updateFromStg( $aPath );
380 if( $bSetExist ? ( $v === null ) : ( $v !== null ) )
381 return( false );
382
383 return( $this -> _set( $aPath, $bNonPersistentGroup, $data, $expire, $time ) );
384 }
385
386 public function add( $key, $data, $group = '', $expire = 0 )
387 {
388 if( function_exists( 'wp_suspend_cache_addition' ) && wp_suspend_cache_addition() )
389 return( false );
390
391 $this -> _init();
392
393 return( $this -> _add( false, $key, $data, $group, self::_normExpiration( $expire ), time() ) );
394 }
395
396 public function add_multiple( array $aData, $group = '', $expire = 0 )
397 {
398 if( function_exists( 'wp_suspend_cache_addition' ) && wp_suspend_cache_addition() )
399 return( array_fill_keys( array_keys( $aData ), false ) );
400
401 $this -> _init();
402
403 $expire = self::_normExpiration( $expire );
404 $time = time();
405
406 $aRes = array();
407
408 foreach( $aData as $key => $data )
409 $aRes[ $key ] = $this -> _add( false, $key, $data, $group, $expire, $time );
410
411 return( $aRes );
412 }
413
414 public function replace( $key, $data, $group = '', $expire = 0 )
415 {
416
417 $this -> _init();
418
419 return( $this -> _add( true, $key, $data, $group, self::_normExpiration( $expire ), time() ) );
420 }
421
422 protected function _set( $aPath, $bNonPersistentGroup, $data, $expire, $time )
423 {
424 if( is_object( $data ) )
425 $data = clone $data;
426
427 $v = array( $data, $time + $expire );
428 \seraph_accel\Gen::SetArrField( $this -> aData, $aPath, $v );
429 if( !$bNonPersistentGroup )
430 $this -> _updateToStg( $aPath, $v );
431
432 return( true );
433 }
434
435 public function set( $key, $data, $group = '', $expire = 0 )
436 {
437
438 if( !self::_is_valid_key( $key ) )
439 return( false );
440
441 $this -> _init();
442
443 $aPath = $this -> _getPath( $group, $key );
444 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
445 return( $this -> _set( $aPath, $bNonPersistentGroup, $data, self::_normExpiration( $expire ), time() ) );
446 }
447
448 public function set_multiple( array $aData, $group = '', $expire = 0 )
449 {
450
451 $this -> _init();
452
453 $expire = self::_normExpiration( $expire );
454 $time = time();
455
456 $aRes = array();
457
458 foreach( $aData as $key => $data )
459 {
460 $aPath = $this -> _getPath( $group, $key );
461 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
462 $aRes[ $key ] = self::_is_valid_key( $key ) ? $this -> _set( $aPath, $bNonPersistentGroup, $data, $expire, $time ) : false;
463 }
464
465 return( $aRes );
466 }
467
468 public function get( $key, $group = '', $force = false, &$found = null )
469 {
470 if( !self::_is_valid_key( $key ) )
471 return( false );
472
473 $this -> _init();
474
475 $aPath = $this -> _getPath( $group, $key );
476 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
477
478 $v = null;
479
480 if( $force && !$bNonPersistentGroup )
481 $v = $this -> _updateFromStg( $aPath );
482 else
483
484 {
485 $v = \seraph_accel\Gen::GetArrField( $this -> aData, $aPath );
486 if( $v === null && !$bNonPersistentGroup )
487 $v = $this -> _updateFromStg( $aPath );
488 }
489
490 if( $v !== null && $v[ 1 ] && $v[ 1 ] < time() )
491 {
492 \seraph_accel\Gen::UnsetArrField( $this -> aData, $aPath );
493 $v = null;
494 if( !$bNonPersistentGroup )
495 $this -> _updateToStg( $aPath, null );
496 }
497
498 if( $v === null )
499 {
500 $found = false;
501 $this -> nMisses += 1;
502 return( false );
503 }
504
505 $v = $v[ 0 ];
506 if( is_object( $v ) )
507 $v = clone $v;
508
509 $found = true;
510 $this -> nHits += 1;
511 return( $v );
512 }
513
514 public function get_multiple( $aKey, $group = '', $force = false )
515 {
516 $this -> _init();
517
518 $aData = array();
519
520 foreach( $aKey as $key )
521 $aData[ $key ] = $this -> get( $key, $group, $force );
522
523 return( $aData );
524 }
525
526 public function delete( $key, $group = '', $deprecated = false )
527 {
528 if( !self::_is_valid_key( $key ) )
529 return( false );
530
531 $this -> _init();
532
533 $aPath = $this -> _getPath( $group, $key );
534 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
535
536 $v = \seraph_accel\Gen::GetArrField( $this -> aData, $aPath );
537 if( $v === null && !$bNonPersistentGroup )
538 $v = $this -> _updateFromStg( $aPath );
539 if( $v === null )
540 return( false );
541
542 \seraph_accel\Gen::UnsetArrField( $this -> aData, $aPath );
543 if( !$bNonPersistentGroup )
544 $this -> _updateToStg( $aPath, null );
545 return( true );
546 }
547
548 public function delete_multiple( array $aKey, $group = '' )
549 {
550 $this -> _init();
551
552 $aRes = array();
553
554 foreach( $aKey as $key )
555 $aRes[ $key ] = $this -> delete( $key, $group );
556
557 return( $aRes );
558 }
559
560 public function incr( $key, $offset = 1, $group = '' )
561 {
562
563 return( $this -> _incr( $key, $offset, $group ) );
564 }
565
566 public function decr( $key, $offset = 1, $group = '' )
567 {
568
569 return( $this -> _incr( $key, -$offset, $group ) );
570 }
571
572 private function _incr( $key, $offset = 1, $group = '' )
573 {
574 if( !self::_is_valid_key( $key ) )
575 return( false );
576
577 $this -> _init();
578
579 if( $this -> lock -> Acquire() === false )
580 return( false );
581
582 $aPath = $this -> _getPath( $group, $key );
583 $bNonPersistentGroup = isset( $this -> aNonPersistentGroup[ $aPath[ 0 ] ] );
584
585 $v = \seraph_accel\Gen::GetArrField( $this -> aData, $aPath );
586 if( $v === null && !$bNonPersistentGroup )
587 $v = $this -> _updateFromStg( $aPath );
588 if( $v === null )
589 {
590 $this -> lock -> Release();
591 return( false );
592 }
593
594 if( !is_numeric( $v[ 0 ] ) )
595 $v[ 0 ] = 0;
596
597 $v[ 0 ] += ( int )$offset;
598 if( $v[ 0 ] < 0 )
599 $v[ 0 ] = 0;
600
601 \seraph_accel\Gen::SetArrField( $this -> aData, $aPath, $v );
602 if( !$bNonPersistentGroup )
603 $this -> _updateToStg( $aPath, $v );
604
605 $this -> lock -> Release();
606
607 return( $v[ 0 ] );
608 }
609
610 public function flush()
611 {
612 $this -> _init();
613
614 $this -> aData = array();
615
616 if( $this -> lock -> Acquire() )
617
618 {
619 \seraph_accel\Gen::DelDir( $this -> dataDir, false );
620
621 $this -> lock -> Release();
622
623 }
624
625 return( true );
626 }
627
628 public function flush_group( $group )
629 {
630 $this -> _init();
631
632 $aPath = $this -> _getPath( $group, '' );
633
634 \seraph_accel\Gen::UnsetArrField( $this -> aData, array( $aPath[ 0 ] ) );
635
636 if( $this -> lock -> Acquire() )
637
638 {
639 \seraph_accel\Gen::DelDir( $this -> dataDir . '/' . $aPath[ 0 ] );
640
641 $this -> lock -> Release();
642
643 }
644
645 return( true );
646 }
647
648 public function switch_to_blog( $blog_id )
649 {
650 $this -> _init();
651
652 if( $this -> curSite )
653 {
654 $this -> curSite -> blog_id = ( int )$blog_id;
655 $this -> curSiteId = \seraph_accel\GetSiteId( $this -> curSite );
656 }
657 }
658
659 public function reset()
660 {
661 $this -> _init();
662
663 if( $this -> curSite )
664 {
665 $this -> curSite -> blog_id = $this -> curSite -> blog_id_orig;
666 $this -> curSiteId = \seraph_accel\GetSiteId( $this -> curSite );
667 }
668 }
669
670 public function stats()
671 {
672 echo '<p>';
673 echo "<strong>Cache Hits:</strong> {$this -> nHits}<br />";
674 echo "<strong>Cache Misses:</strong> {$this -> nMisses}<br />";
675 echo '</p>';
676 echo '<ul>';
677 foreach( $this -> aData as $group => $cache )
678 {
679 echo '<li><strong>Group:</strong> "' . esc_html( $group == '@' ? '' : $group ) . '" - (' . number_format( strlen( serialize( $cache ) ) / KB_IN_BYTES, 2 ) . ' KB)</li>';
680 }
681 echo '</ul>';
682 }
683 }
684
685