Skip to content

Commit 03824b3

Browse files
authored
Initial release.
1 parent c214c75 commit 03824b3

File tree

10 files changed

+1839
-0
lines changed

10 files changed

+1839
-0
lines changed
Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
<?php
2+
3+
/*
4+
Plugin Name: APC Object Cache
5+
Description: APC backend for the WP Object Cache.
6+
Version: 2.0.3
7+
URI: http://txfx.net/wordpress-plugins/apc/
8+
Author: Mark Jaquith
9+
Author URI: http://coveredwebservices.com/
10+
11+
Install this file to wp-content/object-cache.php
12+
13+
Based on Ryan Boren's Memcached object cache backend
14+
http://wordpress.org/extend/plugins/memcached/
15+
16+
*/
17+
18+
if ( !function_exists( 'apc_fetch' ) ) {
19+
wp_die( 'You do not have APC installed, so you cannot use the APC object cache backend. Please remove the <code>object-cache.php</code> file from your content directory.' );
20+
} elseif ( version_compare( '5.2.4', phpversion(), '>=' ) ) {
21+
wp_die( 'The APC object cache backend requires PHP 5.2 or higher. You are running ' . phpversion() . '. Please remove the <code>object-cache.php</code> file from your content directory.' );
22+
}
23+
24+
// Users with setups where multiple installs share a common wp-config.php can use this
25+
// to guarantee uniqueness for the keys generated by this object cache
26+
if ( !defined( 'WP_APC_KEY_SALT' ) )
27+
define( 'WP_APC_KEY_SALT', 'wp' );
28+
29+
function wp_cache_add( $key, $data, $group = '', $expire = 0 ) {
30+
global $wp_object_cache;
31+
32+
return $wp_object_cache->add( $key, $data, $group, $expire );
33+
}
34+
35+
function wp_cache_incr( $key, $n = 1, $group = '' ) {
36+
global $wp_object_cache;
37+
38+
return $wp_object_cache->incr2( $key, $n, $group );
39+
}
40+
41+
function wp_cache_decr( $key, $n = 1, $group = '' ) {
42+
global $wp_object_cache;
43+
44+
return $wp_object_cache->decr( $key, $n, $group );
45+
}
46+
47+
function wp_cache_close() {
48+
return true;
49+
}
50+
51+
function wp_cache_delete( $key, $group = '' ) {
52+
global $wp_object_cache;
53+
54+
return $wp_object_cache->delete( $key, $group );
55+
}
56+
57+
function wp_cache_flush() {
58+
global $wp_object_cache;
59+
60+
return $wp_object_cache->flush();
61+
}
62+
63+
function wp_cache_get( $key, $group = '', $force = false ) {
64+
global $wp_object_cache;
65+
66+
return $wp_object_cache->get( $key, $group, $force );
67+
}
68+
69+
function wp_cache_init() {
70+
global $wp_object_cache;
71+
72+
$wp_object_cache = new APC_Object_Cache();
73+
}
74+
75+
function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) {
76+
global $wp_object_cache;
77+
78+
return $wp_object_cache->replace( $key, $data, $group, $expire );
79+
}
80+
81+
function wp_cache_set( $key, $data, $group = '', $expire = 0 ) {
82+
global $wp_object_cache;
83+
84+
if ( defined('WP_INSTALLING') == false )
85+
return $wp_object_cache->set( $key, $data, $group, $expire );
86+
else
87+
return $wp_object_cache->delete( $key, $group );
88+
}
89+
90+
function wp_cache_add_global_groups( $groups ) {
91+
global $wp_object_cache;
92+
93+
$wp_object_cache->add_global_groups( $groups );
94+
}
95+
96+
function wp_cache_add_non_persistent_groups( $groups ) {
97+
global $wp_object_cache;
98+
99+
$wp_object_cache->add_non_persistent_groups( $groups );
100+
}
101+
102+
class WP_Object_Cache {
103+
var $global_groups = array();
104+
105+
var $no_mc_groups = array();
106+
107+
var $cache = array();
108+
var $stats = array( 'get' => 0, 'delete' => 0, 'add' => 0 );
109+
var $group_ops = array();
110+
111+
var $cache_enabled = true;
112+
var $default_expiration = 0;
113+
var $abspath = '';
114+
var $debug = false;
115+
116+
function add( $id, $data, $group = 'default', $expire = 0 ) {
117+
$key = $this->key( $id, $group );
118+
119+
if ( is_object( $data ) )
120+
$data = clone $data;
121+
122+
$store_data = $data;
123+
124+
if ( is_array( $data ) )
125+
$store_data = new ArrayObject( $data );
126+
127+
if ( in_array( $group, $this->no_mc_groups ) ) {
128+
$this->cache[$key] = $data;
129+
return true;
130+
} elseif ( isset( $this->cache[$key] ) && $this->cache[$key] !== false ) {
131+
return false;
132+
}
133+
134+
$expire = ( $expire == 0 ) ? $this->default_expiration : $expire;
135+
136+
$result = apc_add( $key, $store_data, $expire );
137+
if ( false !== $result ) {
138+
@ ++$this->stats['add'];
139+
$this->group_ops[$group][] = "add $id";
140+
$this->cache[$key] = $data;
141+
}
142+
143+
return $result;
144+
}
145+
146+
function add_global_groups( $groups ) {
147+
if ( !is_array( $groups ) )
148+
$groups = (array) $groups;
149+
150+
$this->global_groups = array_merge( $this->global_groups, $groups );
151+
$this->global_groups = array_unique( $this->global_groups );
152+
}
153+
154+
function add_non_persistent_groups( $groups ) {
155+
if ( !is_array( $groups ) )
156+
$groups = (array) $groups;
157+
158+
$this->no_mc_groups = array_merge( $this->no_mc_groups, $groups );
159+
$this->no_mc_groups = array_unique( $this->no_mc_groups );
160+
}
161+
162+
// This is named incr2 because Batcache looks for incr
163+
// We will define that in a class extension if it is available (APC 3.1.1 or higher)
164+
function incr2( $id, $n = 1, $group = 'default' ) {
165+
$key = $this->key( $id, $group );
166+
if ( function_exists( 'apc_inc' ) )
167+
return apc_inc( $key, $n );
168+
else
169+
return false;
170+
}
171+
172+
function decr( $id, $n = 1, $group = 'default' ) {
173+
$key = $this->key( $id, $group );
174+
if ( function_exists( 'apc_dec' ) )
175+
return apc_dec( $id, $n );
176+
else
177+
return false;
178+
}
179+
180+
function close() {
181+
return true;
182+
}
183+
184+
function delete( $id, $group = 'default' ) {
185+
$key = $this->key( $id, $group );
186+
187+
if ( in_array( $group, $this->no_mc_groups ) ) {
188+
unset( $this->cache[$key] );
189+
return true;
190+
}
191+
192+
$result = apc_delete( $key );
193+
194+
@ ++$this->stats['delete'];
195+
$this->group_ops[$group][] = "delete $id";
196+
197+
if ( false !== $result )
198+
unset( $this->cache[$key] );
199+
200+
return $result;
201+
}
202+
203+
function flush() {
204+
// Don't flush if multi-blog.
205+
if ( function_exists( 'is_site_admin' ) || defined( 'CUSTOM_USER_TABLE' ) && defined( 'CUSTOM_USER_META_TABLE' ) )
206+
return true;
207+
208+
return apc_clear_cache( 'user' );
209+
}
210+
211+
function get($id, $group = 'default', $force = false) {
212+
$key = $this->key($id, $group);
213+
214+
if ( isset($this->cache[$key]) && ( !$force || in_array($group, $this->no_mc_groups) ) ) {
215+
if ( is_object( $this->cache[$key] ) )
216+
$value = clone $this->cache[$key];
217+
else
218+
$value = $this->cache[$key];
219+
} else if ( in_array($group, $this->no_mc_groups) ) {
220+
$this->cache[$key] = $value = false;
221+
} else {
222+
$value = apc_fetch( $key );
223+
if ( is_object( $value ) && 'ArrayObject' == get_class( $value ) )
224+
$value = $value->getArrayCopy();
225+
if ( NULL === $value )
226+
$value = false;
227+
$this->cache[$key] = $value;
228+
}
229+
230+
@ ++$this->stats['get'];
231+
$this->group_ops[$group][] = "get $id";
232+
233+
if ( 'checkthedatabaseplease' === $value ) {
234+
unset( $this->cache[$key] );
235+
$value = false;
236+
}
237+
238+
return $value;
239+
}
240+
241+
function key( $key, $group ) {
242+
if ( empty( $group ) )
243+
$group = 'default';
244+
245+
if ( false !== array_search( $group, $this->global_groups ) )
246+
$prefix = $this->global_prefix;
247+
else
248+
$prefix = $this->blog_prefix;
249+
250+
return WP_APC_KEY_SALT . ':' . $this->abspath . ":$prefix$group:$key";
251+
}
252+
253+
function replace( $id, $data, $group = 'default', $expire = 0 ) {
254+
return $this->set( $id, $data, $group, $expire );
255+
}
256+
257+
function set( $id, $data, $group = 'default', $expire = 0 ) {
258+
$key = $this->key( $id, $group );
259+
if ( isset( $this->cache[$key] ) && ('checkthedatabaseplease' === $this->cache[$key] ) )
260+
return false;
261+
262+
if ( is_object( $data ) )
263+
$data = clone $data;
264+
265+
$store_data = $data;
266+
267+
if ( is_array( $data ) )
268+
$store_data = new ArrayObject( $data );
269+
270+
$this->cache[$key] = $data;
271+
272+
if ( in_array( $group, $this->no_mc_groups ) )
273+
return true;
274+
275+
$expire = ( $expire == 0 ) ? $this->default_expiration : $expire;
276+
$result = apc_store( $key, $store_data, $expire );
277+
278+
return $result;
279+
}
280+
281+
function colorize_debug_line( $line ) {
282+
$colors = array(
283+
'get' => 'green',
284+
'set' => 'purple',
285+
'add' => 'blue',
286+
'delete' => 'red');
287+
288+
$cmd = substr( $line, 0, strpos( $line, ' ' ) );
289+
290+
$cmd2 = "<span style='color:{$colors[$cmd]}'>$cmd</span>";
291+
292+
return $cmd2 . substr( $line, strlen( $cmd ) ) . "\n";
293+
}
294+
295+
function stats() {
296+
echo "<p>\n";
297+
foreach ( $this->stats as $stat => $n ) {
298+
echo "<strong>$stat</strong> $n";
299+
echo "<br/>\n";
300+
}
301+
echo "</p>\n";
302+
echo "<h3>APC:</h3>";
303+
foreach ( $this->group_ops as $group => $ops ) {
304+
if ( !isset( $_GET['debug_queries'] ) && 500 < count( $ops ) ) {
305+
$ops = array_slice( $ops, 0, 500 );
306+
echo "<big>Too many to show! <a href='" . add_query_arg( 'debug_queries', 'true' ) . "'>Show them anyway</a>.</big>\n";
307+
}
308+
echo "<h4>$group commands</h4>";
309+
echo "<pre>\n";
310+
$lines = array();
311+
foreach ( $ops as $op ) {
312+
$lines[] = $this->colorize_debug_line($op);
313+
}
314+
print_r($lines);
315+
echo "</pre>\n";
316+
}
317+
if ( $this->debug ) {
318+
$apc_info = apc_cache_info();
319+
echo "<p>";
320+
echo "<strong>Cache Hits:</strong> {$apc_info['num_hits']}<br/>\n";
321+
echo "<strong>Cache Misses:</strong> {$apc_info['num_misses']}\n";
322+
echo "</p>\n";
323+
}
324+
}
325+
326+
function WP_Object_Cache() {
327+
$this->abspath = md5( ABSPATH );
328+
329+
global $blog_id, $table_prefix;
330+
$this->global_prefix = '';
331+
$this->blog_prefix = '';
332+
if ( function_exists( 'is_multisite' ) ) {
333+
$this->global_prefix = ( is_multisite() || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') ) ? '' : $table_prefix;
334+
$this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':';
335+
}
336+
337+
$this->cache_hits =& $this->stats['get'];
338+
$this->cache_misses =& $this->stats['add'];
339+
}
340+
}
341+
342+
if ( function_exists( 'apc_inc' ) ) {
343+
class APC_Object_Cache extends WP_Object_Cache {
344+
function incr( $id, $n = 1, $group = 'default' ) {
345+
return parent::incr2( $id, $n, $group );
346+
}
347+
}
348+
} else {
349+
class APC_Object_Cache extends WP_Object_Cache {
350+
// Blank
351+
}
352+
}

0 commit comments

Comments
 (0)