WP_Object_Cache

Core class that implements an object cache.

Defined (2)

The class is defined in the following location(s).

/bp-forums/bbpress/bb-includes/backpress/class.wp-object-cache-memcached.php  
  1. class WP_Object_Cache 
  2. // WordPress would need to be initialised with this: 
  3. // wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss' ) ); 
  4. var $global_groups = array ( 
  5. '_cache_keys' 
  6. ); 
  7.  
  8. // WordPress would need to be initialised with this: 
  9. // wp_cache_add_non_persistent_groups( array( 'comment', 'counts' ) ); 
  10. var $no_mc_groups = array(); 
  11.  
  12. var $cache = array(); 
  13. var $mc = array(); 
  14. var $stats = array(); 
  15. var $group_ops = array(); 
  16.  
  17. var $default_expiration = 0; 
  18.  
  19. function __construct() 
  20. global $memcached_servers; 
  21.  
  22. if ( isset( $memcached_servers ) ) { 
  23. $buckets = $memcached_servers; 
  24. } else { 
  25. $buckets = array('default' => array('127.0.0.1:11211')); 
  26.  
  27. foreach ( $buckets as $bucket => $servers ) { 
  28. $this->mc[$bucket] = new Memcache(); 
  29. foreach ( $servers as $server ) { 
  30. list ( $node, $port ) = explode( ':', $server ); 
  31. $this->mc[$bucket]->addServer( $node, $port, true, 1, 1, 15, true, array( $this, 'failure_callback' ) ); 
  32. $this->mc[$bucket]->setCompressThreshold( 20000, 0.2 ); 
  33.  
  34. function WP_Object_Cache() 
  35. $this->__construct(); 
  36.  
  37. function &get_mc( $group ) 
  38. if ( isset( $this->mc[$group] ) ) { 
  39. return $this->mc[$group]; 
  40. return $this->mc['default']; 
  41.  
  42. function failure_callback( $host, $port ) 
  43. //error_log( "Connection failure for $host:$port\n", 3, '/tmp/memcached.txt' ); 
  44.  
  45. function close() 
  46. foreach ( $this->mc as $bucket => $mc ) { 
  47. $mc->close(); 
  48.  
  49. function add_global_groups( $groups ) 
  50. if ( !is_array( $groups ) ) { 
  51. $groups = (array) $groups; 
  52.  
  53. $this->global_groups = array_merge( $this->global_groups, $groups ); 
  54. $this->global_groups = array_unique( $this->global_groups ); 
  55.  
  56. function add_non_persistent_groups( $groups ) 
  57. if ( !is_array( $groups ) ) { 
  58. $groups = (array) $groups; 
  59.  
  60. $this->no_mc_groups = array_merge( $this->no_mc_groups, $groups ); 
  61. $this->no_mc_groups = array_unique( $this->no_mc_groups ); 
  62.  
  63. function key( $key, $group ) 
  64. if ( empty( $group ) ) { 
  65. $group = 'default'; 
  66.  
  67. if ( false !== array_search( $group, $this->global_groups ) ) { 
  68. $prefix = ''; 
  69. } else { 
  70. $prefix = backpress_get_option( 'application_id' ) . ':'; 
  71.  
  72. return preg_replace( '/\s+/', '', $prefix . $group . ':' . $key ); 
  73.  
  74. function get( $id, $group = 'default' ) 
  75. $key = $this->key( $id, $group ); 
  76. $mc =& $this->get_mc( $group ); 
  77.  
  78. if ( isset( $this->cache[$key] ) ) { 
  79. $value = $this->cache[$key]; 
  80. } elseif ( in_array( $group, $this->no_mc_groups ) ) { 
  81. $value = false; 
  82. } else { 
  83. $value = $mc->get($key); 
  84.  
  85. @ ++$this->stats['get']; 
  86. $this->group_ops[$group][] = "get $id"; 
  87.  
  88. if ( NULL === $value ) { 
  89. $value = false; 
  90.  
  91. $this->cache[$key] = $value; 
  92.  
  93. if ( 'checkthedatabaseplease' === $value ) { 
  94. $value = false; 
  95.  
  96. return $value; 
  97.  
  98. /** 
  99. format: $get['group-name'] = array( 'key1', 'key2' ); 
  100. */ 
  101. function get_multi( $groups ) 
  102. $return = array(); 
  103. foreach ( $groups as $group => $ids ) { 
  104. $mc =& $this->get_mc( $group ); 
  105. foreach ( $ids as $id ) { 
  106. $key = $this->key( $id, $group ); 
  107. if ( isset( $this->cache[$key] ) ) { 
  108. $return[$key] = $this->cache[$key]; 
  109. continue; 
  110. } elseif ( in_array( $group, $this->no_mc_groups ) ) { 
  111. $return[$key] = false; 
  112. continue; 
  113. } else { 
  114. $return[$key] = $mc->get( $key ); 
  115. if ( $to_get ) { 
  116. $vals = $mc->get_multi( $to_get ); 
  117. $return = array_merge( $return, $vals ); 
  118.  
  119. @ ++$this->stats['get_multi']; 
  120. $this->group_ops[$group][] = "get_multi $id"; 
  121.  
  122. $this->cache = array_merge( $this->cache, $return ); 
  123.  
  124. return $return; 
  125.  
  126. function add( $id, $data, $group = 'default', $expire = 0 ) 
  127. $key = $this->key( $id, $group ); 
  128.  
  129. if ( in_array( $group, $this->no_mc_groups ) ) { 
  130. $this->cache[$key] = $data; 
  131. return true; 
  132.  
  133. $mc =& $this->get_mc( $group ); 
  134. $expire = ( $expire == 0 ) ? $this->default_expiration : $expire; 
  135. $result = $mc->add( $key, $data, false, $expire ); 
  136.  
  137. @ ++$this->stats['add']; 
  138. $this->group_ops[$group][] = "add $id"; 
  139.  
  140. if ( false !== $result ) { 
  141. $this->cache[$key] = $data; 
  142. $this->add_key_to_group_keys_cache( $key, $group ); 
  143.  
  144. return $result; 
  145.  
  146. function set( $id, $data, $group = 'default', $expire = 0 ) 
  147. $key = $this->key($id, $group); 
  148.  
  149. if ( isset( $this->cache[$key] ) && 'checkthedatabaseplease' === $this->cache[$key] ) { 
  150. return false; 
  151. $this->cache[$key] = $data; 
  152.  
  153. if ( in_array( $group, $this->no_mc_groups ) ) { 
  154. return true; 
  155.  
  156. $expire = ( $expire == 0 ) ? $this->default_expiration : $expire; 
  157. $mc =& $this->get_mc( $group ); 
  158. $result = $mc->set( $key, $data, false, $expire ); 
  159.  
  160. if ( false !== $result ) { 
  161. $this->add_key_to_group_keys_cache($key, $group); 
  162.  
  163. return $result; 
  164.  
  165. function replace($id, $data, $group = 'default', $expire = 0) { 
  166. $key = $this->key($id, $group); 
  167. if ( in_array( $group, $this->no_mc_groups ) ) { 
  168. $this->cache[$key] = $data; 
  169. return true; 
  170. $expire = ($expire == 0) ? $this->default_expiration : $expire; 
  171. $mc =& $this->get_mc($group); 
  172. $result = $mc->replace($key, $data, false, $expire); 
  173. if ( false !== $result ) { 
  174. $this->cache[$key] = $data; 
  175. $this->add_key_to_group_keys_cache( $key, $group ); 
  176. return $result; 
  177.  
  178. function delete( $id, $group = 'default' ) 
  179. $key = $this->key( $id, $group ); 
  180.  
  181. if ( in_array( $group, $this->no_mc_groups ) ) { 
  182. unset( $this->cache[$key] ); 
  183. return true; 
  184.  
  185. $mc =& $this->get_mc( $group ); 
  186.  
  187. $result = $mc->delete( $key ); 
  188.  
  189. @ ++$this->stats['delete']; 
  190. $this->group_ops[$group][] = "delete $id"; 
  191.  
  192. if ( false !== $result ) { 
  193. unset( $this->cache[$key] ); 
  194. $this->remove_key_from_group_keys_cache( $key, $group ); 
  195.  
  196. return $result;  
  197.  
  198. function flush( $group = null ) 
  199. // Get all the group keys 
  200. if ( !$_groups = $this->get( 1, '_group_keys' ) ) { 
  201. return true; 
  202.  
  203. if ( !is_array( $_groups ) || !count( $_groups ) ) { 
  204. return $this->delete( 1, '_group_keys' ); 
  205.  
  206. if ( is_null( $group ) ) { 
  207. $results = array(); 
  208. foreach ( $_groups as $_group => $_keys ) { 
  209. $results[] = $this->delete_all_keys_in_group_key_cache( $_group ); 
  210. if ( in_array( false, $results ) ) { 
  211. return false; 
  212. return true; 
  213.  
  214. return $this->delete_all_keys_in_group_key_cache( $group ); 
  215.  
  216. // Update the cache of group keys or add a new cache if it isn't there 
  217. function add_key_to_group_keys_cache( $key, $group ) 
  218. if ( '_group_keys' === $group ) { 
  219. return; 
  220.  
  221. //error_log( 'Adding key ' . $key . ' to group ' . $group ); 
  222.  
  223. // Get all the group keys 
  224. if ( !$_groups = $this->get( 1, '_group_keys' ) ) { 
  225. $_groups = array( $group => array( $key ) ); 
  226. return $this->add( 1, $_groups, '_group_keys' ); 
  227.  
  228. // Don't blow up if it isn't an array 
  229. if ( !is_array( $_groups ) ) { 
  230. $_groups = array(); 
  231.  
  232. // If this group isn't in there, then insert it 
  233. if ( !isset( $_groups[$group] ) || !is_array( $_groups[$group] ) ) { 
  234. $_groups[$group] = array(); 
  235.  
  236. // If it's already there then do nothing 
  237. if ( in_array( $key, $_groups[$group] ) ) { 
  238. return true; 
  239.  
  240. $_groups[$group][] = $key; 
  241.  
  242. // Remove duplicates 
  243. $_groups[$group] = array_unique( $_groups[$group] ); 
  244.  
  245. return $this->replace( 1, $_groups, '_group_keys' ); 
  246.  
  247. // Remove the key from the cache of group keys, delete the cache if it is emptied 
  248. function remove_key_from_group_keys_cache( $key, $group ) 
  249. if ( '_group_keys' === $group ) { 
  250. return; 
  251.  
  252. //error_log( 'Removing key ' . $key . ' from group ' . $group ); 
  253.  
  254. // Get all the group keys 
  255. if ( !$_groups = $this->get( 1, '_group_keys' ) ) { 
  256. return true; 
  257.  
  258. // If group keys are somehow borked delete it all 
  259. if ( !is_array( $_groups ) ) { 
  260. return $this->delete( 1, '_group_keys' ); 
  261.  
  262. // If it's not there, we're good 
  263. if ( 
  264. !isset( $_groups[$group] ) || 
  265. !is_array( $_groups[$group] ) || 
  266. !in_array( $key, $_groups[$group] ) 
  267. ) { 
  268. return true; 
  269.  
  270. // Remove duplicates 
  271. $_groups[$group] = array_unique( $_groups[$group] ); 
  272.  
  273. // If there is only one key or no keys in the group then delete the group 
  274. if ( 2 > count( $_groups[$group] ) ) { 
  275. unset( $_groups[$group] ); 
  276. return $this->replace( 1, $_groups, '_group_keys' ); 
  277.  
  278. // array_unique() made sure there is only one 
  279. if ( $_key = array_search( $key, $_groups[$group] ) ) { 
  280. unset( $_groups[$group][$_key] ); 
  281.  
  282. return $this->replace( 1, $_groups, '_group_keys' ); 
  283.  
  284. function delete_all_keys_in_group_key_cache( $group ) 
  285. if ( '_group_keys' === $group ) { 
  286. return; 
  287.  
  288. //error_log( 'Deleting all keys in group ' . $group ); 
  289.  
  290. // Get all the group keys 
  291. if ( !$_groups = $this->get( 1, '_group_keys' ) ) { 
  292. //error_log( '--> !!!! No groups' ); 
  293. return true; 
  294.  
  295. // Check that what we want to loop over is there 
  296. if ( !is_array( $_groups ) ) { 
  297. //error_log( '--> !!!! Groups is not an array, delete whole key' ); 
  298. return $this->delete( 1, '_group_keys' ); 
  299.  
  300. // Check that what we want to loop over is there 
  301. if ( 
  302. !isset( $_groups[$group] ) || 
  303. !is_array( $_groups[$group] ) 
  304. ) { 
  305. //error_log( '--> !!!! No specific group' ); 
  306. return true; 
  307.  
  308. $_groups[$group] = array_unique( $_groups[$group] ); 
  309.  
  310. $_remaining_keys = array(); 
  311. $mc =& $this->get_mc($group); 
  312. foreach ( $_groups[$group] as $_key ) { 
  313. //error_log( '--> Deleting key ' . $_key ); 
  314. if ( false !== $mc->delete( $_key ) ) { 
  315. //error_log( '--> Deleted key ' . $_key ); 
  316. unset( $this->cache[$_key] ); 
  317.  
  318. unset( $_groups[$group] ); 
  319. if ( count( $_groups ) ) { 
  320. //error_log( '--> Remove single group' ); 
  321. return $this->replace( 1, $_groups, '_group_keys' ); 
  322.  
  323. //error_log( '--> No groups left, delete whole key' ); 
  324. return $this->delete( 1, '_group_keys' ); 
  325.  
  326. function incr( $id, $n, $group ) 
  327. $key = $this->key( $id, $group ); 
  328. $mc =& $this->get_mc( $group ); 
  329.  
  330. return $mc->increment( $key, $n ); 
  331.  
  332. function decr( $id, $n, $group ) 
  333. $key = $this->key( $id, $group ); 
  334. $mc =& $this->get_mc( $group ); 
  335.  
  336. return $mc->decrement( $key, $n ); 
  337.  
  338. function colorize_debug_line( $line ) 
  339. $colors = array( 
  340. 'get' => 'green',  
  341. 'set' => 'purple',  
  342. 'add' => 'blue',  
  343. 'delete' => 'red' 
  344. ); 
  345.  
  346. $cmd = substr( $line, 0, strpos( $line, ' ' ) ); 
  347.  
  348. $cmd2 = "<span style='color:{$colors[$cmd]}'>$cmd</span>"; 
  349.  
  350. return $cmd2 . substr( $line, strlen( $cmd ) ) . "\n"; 
  351.  
  352. function stats() 
  353. echo "<p>\n"; 
  354. foreach ( $this->stats as $stat => $n ) { 
  355. echo "<strong>$stat</strong> $n"; 
  356. echo "<br/>\n"; 
  357. echo "</p>\n"; 
  358. echo "<h3>Memcached:</h3>"; 
  359. foreach ( $this->group_ops as $group => $ops ) { 
  360. if ( !isset( $_GET['debug_queries'] ) && 500 < count( $ops ) ) {  
  361. $ops = array_slice( $ops, 0, 500 );  
  362. echo "<big>Too many to show! <a href='" . add_query_arg( 'debug_queries', 'true' ) . "'>Show them anyway</a>.</big>\n"; 
  363. }  
  364. echo "<h4>$group commands</h4>"; 
  365. echo "<pre>\n"; 
  366. $lines = array(); 
  367. foreach ( $ops as $op ) { 
  368. $lines[] = $this->colorize_debug_line( $op );  
  369. print_r( $lines ); 
  370. echo "</pre>\n"; 
  371.  
  372. if ( $this->debug ) { 
  373. var_dump( $this->memcache_debug ); 
/bp-forums/bbpress/bb-includes/backpress/class.wp-object-cache.php  
  1. class WP_Object_Cache { 
  2.  
  3. /** 
  4. * Holds the cached objects 
  5. * @var array 
  6. * @access private 
  7. * @since 2.0.0 
  8. */ 
  9. var $cache = array (); 
  10.  
  11. /** 
  12. * Cache objects that do not exist in the cache 
  13. * @var array 
  14. * @access private 
  15. * @since 2.0.0 
  16. */ 
  17. var $non_existant_objects = array (); 
  18.  
  19. /** 
  20. * The amount of times the cache data was already stored in the cache. 
  21. * @since 2.5.0 
  22. * @access private 
  23. * @var int 
  24. */ 
  25. var $cache_hits = 0; 
  26.  
  27. /** 
  28. * Amount of times the cache did not have the request in cache 
  29. * @var int 
  30. * @access public 
  31. * @since 2.0.0 
  32. */ 
  33. var $cache_misses = 0; 
  34.  
  35. /** 
  36. * Adds data to the cache if it doesn't already exist. 
  37. * @uses WP_Object_Cache::get Checks to see if the cache already has data. 
  38. * @uses WP_Object_Cache::set Sets the data after the checking the cache 
  39. * contents existance. 
  40. * @since 2.0.0 
  41. * @param int|string $id What to call the contents in the cache 
  42. * @param mixed $data The contents to store in the cache 
  43. * @param string $group Where to group the cache contents 
  44. * @param int $expire When to expire the cache contents 
  45. * @return bool False if cache ID and group already exists, true on success 
  46. */ 
  47. function add($id, $data, $group = 'default', $expire = '') { 
  48. if (empty ($group)) 
  49. $group = 'default'; 
  50.  
  51. if (false !== $this->get($id, $group, false)) 
  52. return false; 
  53.  
  54. return $this->set($id, $data, $group, $expire); 
  55.  
  56. /** 
  57. * Remove the contents of the cache ID in the group 
  58. * If the cache ID does not exist in the group and $force parameter is set 
  59. * to false, then nothing will happen. The $force parameter is set to false 
  60. * by default. 
  61. * On success the group and the id will be added to the 
  62. * $non_existant_objects property in the class. 
  63. * @since 2.0.0 
  64. * @param int|string $id What the contents in the cache are called 
  65. * @param string $group Where the cache contents are grouped 
  66. * @param bool $force Optional. Whether to force the unsetting of the cache 
  67. * ID in the group 
  68. * @return bool False if the contents weren't deleted and true on success 
  69. */ 
  70. function delete($id, $group = 'default', $force = false) { 
  71. if (empty ($group)) 
  72. $group = 'default'; 
  73.  
  74. if (!$force && false === $this->get($id, $group, false)) 
  75. return false; 
  76.  
  77. unset ($this->cache[$group][$id]); 
  78. $this->non_existant_objects[$group][$id] = true; 
  79. return true; 
  80.  
  81. /** 
  82. * Clears the object cache of all data 
  83. * @since 2.0.0 
  84. * @return bool Always returns true 
  85. */ 
  86. function flush( $group = null ) { 
  87. // WP does not support group flushing 
  88. if ( is_null($group) ) { 
  89. $this->cache = array(); 
  90. $this->non_existant_objects = array(); 
  91. return true; 
  92.  
  93. if ( isset($this->cache[$group]) ) 
  94. $this->cache[$group] = array(); 
  95. if ( isset($this->non_existant_objects[$group]) ) 
  96. $this->non_existant_objects[$group] = array(); 
  97.  
  98. /** 
  99. * Retrieves the cache contents, if it exists 
  100. * The contents will be first attempted to be retrieved by searching by the 
  101. * ID in the cache group. If the cache is hit (success) then the contents 
  102. * are returned. 
  103. * On failure, the $non_existant_objects property is checked and if the 
  104. * cache group and ID exist in there the cache misses will not be 
  105. * incremented. If not in the nonexistant objects property, then the cache 
  106. * misses will be incremented and the cache group and ID will be added to 
  107. * the nonexistant objects. 
  108. * @since 2.0.0 
  109. * @param int|string $id What the contents in the cache are called 
  110. * @param string $group Where the cache contents are grouped 
  111. * @return bool|mixed False on failure to retrieve contents or the cache 
  112. * contents on success 
  113. */ 
  114. function get($id, $group = 'default') { 
  115. if (empty ($group)) 
  116. $group = 'default'; 
  117.  
  118. if (isset ($this->cache[$group][$id])) { 
  119. $this->cache_hits += 1; 
  120. if ( is_object($this->cache[$group][$id]) ) 
  121. return wp_clone($this->cache[$group][$id]); 
  122. else 
  123. return $this->cache[$group][$id]; 
  124.  
  125. if ( isset ($this->non_existant_objects[$group][$id]) ) 
  126. return false; 
  127.  
  128. $this->non_existant_objects[$group][$id] = true; 
  129. $this->cache_misses += 1; 
  130. return false; 
  131.  
  132. /** 
  133. * Replace the contents in the cache, if contents already exist 
  134. * @since 2.0.0 
  135. * @see WP_Object_Cache::set() 
  136. * @param int|string $id What to call the contents in the cache 
  137. * @param mixed $data The contents to store in the cache 
  138. * @param string $group Where to group the cache contents 
  139. * @param int $expire When to expire the cache contents 
  140. * @return bool False if not exists, true if contents were replaced 
  141. */ 
  142. function replace($id, $data, $group = 'default', $expire = '') { 
  143. if (empty ($group)) 
  144. $group = 'default'; 
  145.  
  146. if (false === $this->get($id, $group, false)) 
  147. return false; 
  148.  
  149. return $this->set($id, $data, $group, $expire); 
  150.  
  151. /** 
  152. * Sets the data contents into the cache 
  153. * The cache contents is grouped by the $group parameter followed by the 
  154. * $id. This allows for duplicate ids in unique groups. Therefore, naming of 
  155. * the group should be used with care and should follow normal function 
  156. * naming guidelines outside of core WordPress usage. 
  157. * The $expire parameter is not used, because the cache will automatically 
  158. * expire for each time a page is accessed and PHP finishes. The method is 
  159. * more for cache plugins which use files. 
  160. * @since 2.0.0 
  161. * @param int|string $id What to call the contents in the cache 
  162. * @param mixed $data The contents to store in the cache 
  163. * @param string $group Where to group the cache contents 
  164. * @param int $expire Not Used 
  165. * @return bool Always returns true 
  166. */ 
  167. function set($id, $data, $group = 'default', $expire = '') { 
  168. if (empty ($group)) 
  169. $group = 'default'; 
  170.  
  171. if (NULL === $data) 
  172. $data = ''; 
  173.  
  174. if ( is_object($data) ) 
  175. $data = wp_clone($data); 
  176.  
  177. $this->cache[$group][$id] = $data; 
  178.  
  179. if(isset($this->non_existant_objects[$group][$id])) 
  180. unset ($this->non_existant_objects[$group][$id]); 
  181.  
  182. return true; 
  183.  
  184. /** 
  185. * Echos the stats of the caching. 
  186. * Gives the cache hits, and cache misses. Also prints every cached group,  
  187. * key and the data. 
  188. * @since 2.0.0 
  189. */ 
  190. function stats() { 
  191. echo "<p>"; 
  192. echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />"; 
  193. echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />"; 
  194. echo "</p>"; 
  195.  
  196. foreach ($this->cache as $group => $cache) { 
  197. echo "<p>"; 
  198. echo "<strong>Group:</strong> $group<br />"; 
  199. echo "<strong>Cache:</strong>"; 
  200. echo "<pre>"; 
  201. print_r($cache); 
  202. echo "</pre>"; 
  203.  
  204. function add_global_groups( $groups ) 
  205. return true; 
  206.  
  207. function add_non_persistent_groups( $groups ) 
  208. return true; 
  209.  
  210. /** 
  211. * PHP4 constructor; Calls PHP 5 style constructor 
  212. * @since 2.0.0 
  213. * @return WP_Object_Cache 
  214. */ 
  215. function WP_Object_Cache() { 
  216. return $this->__construct(); 
  217.  
  218. /** 
  219. * Sets up object properties; PHP 5 style constructor 
  220. * @since 2.0.8 
  221. * @return null|WP_Object_Cache If cache is disabled, returns null. 
  222. */ 
  223. function __construct() { 
  224. /** 
  225. * @todo This should be moved to the PHP4 style constructor, PHP5 
  226. * already calls __destruct() 
  227. */ 
  228. register_shutdown_function(array(&$this, "__destruct")); 
  229.  
  230. /** 
  231. * Will save the object cache before object is completely destroyed. 
  232. * Called upon object destruction, which should be when PHP ends. 
  233. * @since 2.0.8 
  234. * @return bool True value. Won't be used by PHP 
  235. */ 
  236. function __destruct() { 
  237. return true;