MediaWiki  REL1_19
CacheDependency.php
Go to the documentation of this file.
00001 <?php
00009 class DependencyWrapper {
00010         var $value;
00011         var $deps;
00012 
00019         function __construct( $value = false, $deps = array() ) {
00020                 $this->value = $value;
00021 
00022                 if ( !is_array( $deps ) ) {
00023                         $deps = array( $deps );
00024                 }
00025 
00026                 $this->deps = $deps;
00027         }
00028 
00034         function isExpired() {
00035                 foreach ( $this->deps as $dep ) {
00036                         if ( $dep->isExpired() ) {
00037                                 return true;
00038                         }
00039                 }
00040 
00041                 return false;
00042         }
00043 
00048         function initialiseDeps() {
00049                 foreach ( $this->deps as $dep ) {
00050                         $dep->loadDependencyValues();
00051                 }
00052         }
00053 
00058         function getValue() {
00059                 return $this->value;
00060         }
00061 
00069         function storeToCache( $cache, $key, $expiry = 0 ) {
00070                 $this->initialiseDeps();
00071                 $cache->set( $key, $this, $expiry );
00072         }
00073 
00091         static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false,
00092                 $callbackParams = array(), $deps = array() )
00093         {
00094                 $obj = $cache->get( $key );
00095 
00096                 if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) {
00097                         $value = $obj->value;
00098                 } elseif ( $callback ) {
00099                         $value = call_user_func_array( $callback, $callbackParams );
00100                         # Cache the newly-generated value
00101                         $wrapper = new DependencyWrapper( $value, $deps );
00102                         $wrapper->storeToCache( $cache, $key, $expiry );
00103                 } else {
00104                         $value = null;
00105                 }
00106 
00107                 return $value;
00108         }
00109 }
00110 
00114 abstract class CacheDependency {
00118         abstract function isExpired();
00119 
00123         function loadDependencyValues() { }
00124 }
00125 
00129 class FileDependency extends CacheDependency {
00130         var $filename, $timestamp;
00131 
00144         function __construct( $filename, $timestamp = null ) {
00145                 $this->filename = $filename;
00146                 $this->timestamp = $timestamp;
00147         }
00148 
00152         function __sleep() {
00153                 $this->loadDependencyValues();
00154                 return array( 'filename', 'timestamp' );
00155         }
00156 
00157         function loadDependencyValues() {
00158                 if ( is_null( $this->timestamp ) ) {
00159                         if ( !file_exists( $this->filename ) ) {
00160                                 # Dependency on a non-existent file
00161                                 # This is a valid concept!
00162                                 $this->timestamp = false;
00163                         } else {
00164                                 $this->timestamp = filemtime( $this->filename );
00165                         }
00166                 }
00167         }
00168 
00172         function isExpired() {
00173                 if ( !file_exists( $this->filename ) ) {
00174                         if ( $this->timestamp === false ) {
00175                                 # Still nonexistent
00176                                 return false;
00177                         } else {
00178                                 # Deleted
00179                                 wfDebug( "Dependency triggered: {$this->filename} deleted.\n" );
00180                                 return true;
00181                         }
00182                 } else {
00183                         $lastmod = filemtime( $this->filename );
00184                         if ( $lastmod > $this->timestamp ) {
00185                                 # Modified or created
00186                                 wfDebug( "Dependency triggered: {$this->filename} changed.\n" );
00187                                 return true;
00188                         } else {
00189                                 # Not modified
00190                                 return false;
00191                         }
00192                 }
00193         }
00194 }
00195 
00199 class TitleDependency extends CacheDependency {
00200         var $titleObj;
00201         var $ns, $dbk;
00202         var $touched;
00203 
00208         function __construct( Title $title ) {
00209                 $this->titleObj = $title;
00210                 $this->ns = $title->getNamespace();
00211                 $this->dbk = $title->getDBkey();
00212         }
00213 
00214         function loadDependencyValues() {
00215                 $this->touched = $this->getTitle()->getTouched();
00216         }
00217 
00223         function __sleep() {
00224                 return array( 'ns', 'dbk', 'touched' );
00225         }
00226 
00230         function getTitle() {
00231                 if ( !isset( $this->titleObj ) ) {
00232                         $this->titleObj = Title::makeTitle( $this->ns, $this->dbk );
00233                 }
00234 
00235                 return $this->titleObj;
00236         }
00237 
00241         function isExpired() {
00242                 $touched = $this->getTitle()->getTouched();
00243 
00244                 if ( $this->touched === false ) {
00245                         if ( $touched === false ) {
00246                                 # Still missing
00247                                 return false;
00248                         } else {
00249                                 # Created
00250                                 return true;
00251                         }
00252                 } elseif ( $touched === false ) {
00253                         # Deleted
00254                         return true;
00255                 } elseif ( $touched > $this->touched ) {
00256                         # Updated
00257                         return true;
00258                 } else {
00259                         # Unmodified
00260                         return false;
00261                 }
00262         }
00263 }
00264 
00268 class TitleListDependency extends CacheDependency {
00269         var $linkBatch;
00270         var $timestamps;
00271 
00276         function __construct( LinkBatch $linkBatch ) {
00277                 $this->linkBatch = $linkBatch;
00278         }
00279 
00283         function calculateTimestamps() {
00284                 # Initialise values to false
00285                 $timestamps = array();
00286 
00287                 foreach ( $this->getLinkBatch()->data as $ns => $dbks ) {
00288                         if ( count( $dbks ) > 0 ) {
00289                                 $timestamps[$ns] = array();
00290 
00291                                 foreach ( $dbks as $dbk => $value ) {
00292                                         $timestamps[$ns][$dbk] = false;
00293                                 }
00294                         }
00295                 }
00296 
00297                 # Do the query
00298                 if ( count( $timestamps ) ) {
00299                         $dbr = wfGetDB( DB_SLAVE );
00300                         $where = $this->getLinkBatch()->constructSet( 'page', $dbr );
00301                         $res = $dbr->select(
00302                                 'page',
00303                                 array( 'page_namespace', 'page_title', 'page_touched' ),
00304                                 $where,
00305                                 __METHOD__
00306                         );
00307 
00308                         foreach ( $res as $row ) {
00309                                 $timestamps[$row->page_namespace][$row->page_title] = $row->page_touched;
00310                         }
00311                 }
00312 
00313                 return $timestamps;
00314         }
00315 
00316         function loadDependencyValues() {
00317                 $this->timestamps = $this->calculateTimestamps();
00318         }
00319 
00323         function __sleep() {
00324                 return array( 'timestamps' );
00325         }
00326 
00330         function getLinkBatch() {
00331                 if ( !isset( $this->linkBatch ) ) {
00332                         $this->linkBatch = new LinkBatch;
00333                         $this->linkBatch->setArray( $this->timestamps );
00334                 }
00335                 return $this->linkBatch;
00336         }
00337 
00341         function isExpired() {
00342                 $newTimestamps = $this->calculateTimestamps();
00343 
00344                 foreach ( $this->timestamps as $ns => $dbks ) {
00345                         foreach ( $dbks as $dbk => $oldTimestamp ) {
00346                                 $newTimestamp = $newTimestamps[$ns][$dbk];
00347 
00348                                 if ( $oldTimestamp === false ) {
00349                                         if ( $newTimestamp === false ) {
00350                                                 # Still missing
00351                                         } else {
00352                                                 # Created
00353                                                 return true;
00354                                         }
00355                                 } elseif ( $newTimestamp === false ) {
00356                                         # Deleted
00357                                         return true;
00358                                 } elseif ( $newTimestamp > $oldTimestamp ) {
00359                                         # Updated
00360                                         return true;
00361                                 } else {
00362                                         # Unmodified
00363                                 }
00364                         }
00365                 }
00366 
00367                 return false;
00368         }
00369 }
00370 
00374 class GlobalDependency extends CacheDependency {
00375         var $name, $value;
00376 
00377         function __construct( $name ) {
00378                 $this->name = $name;
00379                 $this->value = $GLOBALS[$name];
00380         }
00381 
00385         function isExpired() {
00386                 if( !isset($GLOBALS[$this->name]) ) {
00387                         return true;
00388                 }
00389                 return $GLOBALS[$this->name] != $this->value;
00390         }
00391 }
00392 
00396 class ConstantDependency extends CacheDependency {
00397         var $name, $value;
00398 
00399         function __construct( $name ) {
00400                 $this->name = $name;
00401                 $this->value = constant( $name );
00402         }
00403 
00407         function isExpired() {
00408                 return constant( $this->name ) != $this->value;
00409         }
00410 }