[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Data caching with dependencies. 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 * This class stores an arbitrary value along with its dependencies. 26 * Users should typically only use DependencyWrapper::getValueFromCache(), 27 * rather than instantiating one of these objects directly. 28 * @ingroup Cache 29 */ 30 class DependencyWrapper { 31 private $value; 32 /** @var CacheDependency[] */ 33 private $deps; 34 35 /** 36 * Create an instance. 37 * @param mixed $value The user-supplied value 38 * @param CacheDependency|CacheDependency[] $deps A dependency or dependency 39 * array. All dependencies must be objects implementing CacheDependency. 40 */ 41 function __construct( $value = false, $deps = array() ) { 42 $this->value = $value; 43 44 if ( !is_array( $deps ) ) { 45 $deps = array( $deps ); 46 } 47 48 $this->deps = $deps; 49 } 50 51 /** 52 * Returns true if any of the dependencies have expired 53 * 54 * @return bool 55 */ 56 function isExpired() { 57 foreach ( $this->deps as $dep ) { 58 if ( $dep->isExpired() ) { 59 return true; 60 } 61 } 62 63 return false; 64 } 65 66 /** 67 * Initialise dependency values in preparation for storing. This must be 68 * called before serialization. 69 */ 70 function initialiseDeps() { 71 foreach ( $this->deps as $dep ) { 72 $dep->loadDependencyValues(); 73 } 74 } 75 76 /** 77 * Get the user-defined value 78 * @return bool|mixed 79 */ 80 function getValue() { 81 return $this->value; 82 } 83 84 /** 85 * Store the wrapper to a cache 86 * 87 * @param BagOStuff $cache 88 * @param string $key 89 * @param int $expiry 90 */ 91 function storeToCache( $cache, $key, $expiry = 0 ) { 92 $this->initialiseDeps(); 93 $cache->set( $key, $this, $expiry ); 94 } 95 96 /** 97 * Attempt to get a value from the cache. If the value is expired or missing, 98 * it will be generated with the callback function (if present), and the newly 99 * calculated value will be stored to the cache in a wrapper. 100 * 101 * @param BagOStuff $cache A cache object such as $wgMemc 102 * @param string $key The cache key 103 * @param int $expiry The expiry timestamp or interval in seconds 104 * @param bool|callable $callback The callback for generating the value, or false 105 * @param array $callbackParams The function parameters for the callback 106 * @param array $deps The dependencies to store on a cache miss. Note: these 107 * are not the dependencies used on a cache hit! Cache hits use the stored 108 * dependency array. 109 * 110 * @return mixed The value, or null if it was not present in the cache and no 111 * callback was defined. 112 */ 113 static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false, 114 $callbackParams = array(), $deps = array() 115 ) { 116 $obj = $cache->get( $key ); 117 118 if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) { 119 $value = $obj->value; 120 } elseif ( $callback ) { 121 $value = call_user_func_array( $callback, $callbackParams ); 122 # Cache the newly-generated value 123 $wrapper = new DependencyWrapper( $value, $deps ); 124 $wrapper->storeToCache( $cache, $key, $expiry ); 125 } else { 126 $value = null; 127 } 128 129 return $value; 130 } 131 } 132 133 /** 134 * @ingroup Cache 135 */ 136 abstract class CacheDependency { 137 /** 138 * Returns true if the dependency is expired, false otherwise 139 */ 140 abstract function isExpired(); 141 142 /** 143 * Hook to perform any expensive pre-serialize loading of dependency values. 144 */ 145 function loadDependencyValues() { 146 } 147 } 148 149 /** 150 * @ingroup Cache 151 */ 152 class FileDependency extends CacheDependency { 153 private $filename; 154 private $timestamp; 155 156 /** 157 * Create a file dependency 158 * 159 * @param string $filename The name of the file, preferably fully qualified 160 * @param null|bool|int $timestamp The unix last modified timestamp, or false if the 161 * file does not exist. If omitted, the timestamp will be loaded from 162 * the file. 163 * 164 * A dependency on a nonexistent file will be triggered when the file is 165 * created. A dependency on an existing file will be triggered when the 166 * file is changed. 167 */ 168 function __construct( $filename, $timestamp = null ) { 169 $this->filename = $filename; 170 $this->timestamp = $timestamp; 171 } 172 173 /** 174 * @return array 175 */ 176 function __sleep() { 177 $this->loadDependencyValues(); 178 179 return array( 'filename', 'timestamp' ); 180 } 181 182 function loadDependencyValues() { 183 if ( is_null( $this->timestamp ) ) { 184 if ( !file_exists( $this->filename ) ) { 185 # Dependency on a non-existent file 186 # This is a valid concept! 187 $this->timestamp = false; 188 } else { 189 $this->timestamp = filemtime( $this->filename ); 190 } 191 } 192 } 193 194 /** 195 * @return bool 196 */ 197 function isExpired() { 198 if ( !file_exists( $this->filename ) ) { 199 if ( $this->timestamp === false ) { 200 # Still nonexistent 201 return false; 202 } else { 203 # Deleted 204 wfDebug( "Dependency triggered: {$this->filename} deleted.\n" ); 205 206 return true; 207 } 208 } else { 209 $lastmod = filemtime( $this->filename ); 210 if ( $lastmod > $this->timestamp ) { 211 # Modified or created 212 wfDebug( "Dependency triggered: {$this->filename} changed.\n" ); 213 214 return true; 215 } else { 216 # Not modified 217 return false; 218 } 219 } 220 } 221 } 222 223 /** 224 * @ingroup Cache 225 */ 226 class GlobalDependency extends CacheDependency { 227 private $name; 228 private $value; 229 230 function __construct( $name ) { 231 $this->name = $name; 232 $this->value = $GLOBALS[$name]; 233 } 234 235 /** 236 * @return bool 237 */ 238 function isExpired() { 239 if ( !isset( $GLOBALS[$this->name] ) ) { 240 return true; 241 } 242 243 return $GLOBALS[$this->name] != $this->value; 244 } 245 } 246 247 /** 248 * @ingroup Cache 249 */ 250 class ConstantDependency extends CacheDependency { 251 private $name; 252 private $value; 253 254 function __construct( $name ) { 255 $this->name = $name; 256 $this->value = constant( $name ); 257 } 258 259 /** 260 * @return bool 261 */ 262 function isExpired() { 263 return constant( $this->name ) != $this->value; 264 } 265 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |