MediaWiki  REL1_20
CacheDependency.php
Go to the documentation of this file.
00001 <?php
00030 class DependencyWrapper {
00031         var $value;
00032         var $deps;
00033 
00040         function __construct( $value = false, $deps = array() ) {
00041                 $this->value = $value;
00042 
00043                 if ( !is_array( $deps ) ) {
00044                         $deps = array( $deps );
00045                 }
00046 
00047                 $this->deps = $deps;
00048         }
00049 
00055         function isExpired() {
00056                 foreach ( $this->deps as $dep ) {
00057                         if ( $dep->isExpired() ) {
00058                                 return true;
00059                         }
00060                 }
00061 
00062                 return false;
00063         }
00064 
00069         function initialiseDeps() {
00070                 foreach ( $this->deps as $dep ) {
00071                         $dep->loadDependencyValues();
00072                 }
00073         }
00074 
00079         function getValue() {
00080                 return $this->value;
00081         }
00082 
00090         function storeToCache( $cache, $key, $expiry = 0 ) {
00091                 $this->initialiseDeps();
00092                 $cache->set( $key, $this, $expiry );
00093         }
00094 
00112         static function getValueFromCache( $cache, $key, $expiry = 0, $callback = false,
00113                 $callbackParams = array(), $deps = array() )
00114         {
00115                 $obj = $cache->get( $key );
00116 
00117                 if ( is_object( $obj ) && $obj instanceof DependencyWrapper && !$obj->isExpired() ) {
00118                         $value = $obj->value;
00119                 } elseif ( $callback ) {
00120                         $value = call_user_func_array( $callback, $callbackParams );
00121                         # Cache the newly-generated value
00122                         $wrapper = new DependencyWrapper( $value, $deps );
00123                         $wrapper->storeToCache( $cache, $key, $expiry );
00124                 } else {
00125                         $value = null;
00126                 }
00127 
00128                 return $value;
00129         }
00130 }
00131 
00135 abstract class CacheDependency {
00139         abstract function isExpired();
00140 
00144         function loadDependencyValues() { }
00145 }
00146 
00150 class FileDependency extends CacheDependency {
00151         var $filename, $timestamp;
00152 
00165         function __construct( $filename, $timestamp = null ) {
00166                 $this->filename = $filename;
00167                 $this->timestamp = $timestamp;
00168         }
00169 
00173         function __sleep() {
00174                 $this->loadDependencyValues();
00175                 return array( 'filename', 'timestamp' );
00176         }
00177 
00178         function loadDependencyValues() {
00179                 if ( is_null( $this->timestamp ) ) {
00180                         if ( !file_exists( $this->filename ) ) {
00181                                 # Dependency on a non-existent file
00182                                 # This is a valid concept!
00183                                 $this->timestamp = false;
00184                         } else {
00185                                 $this->timestamp = filemtime( $this->filename );
00186                         }
00187                 }
00188         }
00189 
00193         function isExpired() {
00194                 if ( !file_exists( $this->filename ) ) {
00195                         if ( $this->timestamp === false ) {
00196                                 # Still nonexistent
00197                                 return false;
00198                         } else {
00199                                 # Deleted
00200                                 wfDebug( "Dependency triggered: {$this->filename} deleted.\n" );
00201                                 return true;
00202                         }
00203                 } else {
00204                         $lastmod = filemtime( $this->filename );
00205                         if ( $lastmod > $this->timestamp ) {
00206                                 # Modified or created
00207                                 wfDebug( "Dependency triggered: {$this->filename} changed.\n" );
00208                                 return true;
00209                         } else {
00210                                 # Not modified
00211                                 return false;
00212                         }
00213                 }
00214         }
00215 }
00216 
00220 class TitleDependency extends CacheDependency {
00221         var $titleObj;
00222         var $ns, $dbk;
00223         var $touched;
00224 
00229         function __construct( Title $title ) {
00230                 $this->titleObj = $title;
00231                 $this->ns = $title->getNamespace();
00232                 $this->dbk = $title->getDBkey();
00233         }
00234 
00235         function loadDependencyValues() {
00236                 $this->touched = $this->getTitle()->getTouched();
00237         }
00238 
00244         function __sleep() {
00245                 return array( 'ns', 'dbk', 'touched' );
00246         }
00247 
00251         function getTitle() {
00252                 if ( !isset( $this->titleObj ) ) {
00253                         $this->titleObj = Title::makeTitle( $this->ns, $this->dbk );
00254                 }
00255 
00256                 return $this->titleObj;
00257         }
00258 
00262         function isExpired() {
00263                 $touched = $this->getTitle()->getTouched();
00264 
00265                 if ( $this->touched === false ) {
00266                         if ( $touched === false ) {
00267                                 # Still missing
00268                                 return false;
00269                         } else {
00270                                 # Created
00271                                 return true;
00272                         }
00273                 } elseif ( $touched === false ) {
00274                         # Deleted
00275                         return true;
00276                 } elseif ( $touched > $this->touched ) {
00277                         # Updated
00278                         return true;
00279                 } else {
00280                         # Unmodified
00281                         return false;
00282                 }
00283         }
00284 }
00285 
00289 class TitleListDependency extends CacheDependency {
00290         var $linkBatch;
00291         var $timestamps;
00292 
00297         function __construct( LinkBatch $linkBatch ) {
00298                 $this->linkBatch = $linkBatch;
00299         }
00300 
00304         function calculateTimestamps() {
00305                 # Initialise values to false
00306                 $timestamps = array();
00307 
00308                 foreach ( $this->getLinkBatch()->data as $ns => $dbks ) {
00309                         if ( count( $dbks ) > 0 ) {
00310                                 $timestamps[$ns] = array();
00311 
00312                                 foreach ( $dbks as $dbk => $value ) {
00313                                         $timestamps[$ns][$dbk] = false;
00314                                 }
00315                         }
00316                 }
00317 
00318                 # Do the query
00319                 if ( count( $timestamps ) ) {
00320                         $dbr = wfGetDB( DB_SLAVE );
00321                         $where = $this->getLinkBatch()->constructSet( 'page', $dbr );
00322                         $res = $dbr->select(
00323                                 'page',
00324                                 array( 'page_namespace', 'page_title', 'page_touched' ),
00325                                 $where,
00326                                 __METHOD__
00327                         );
00328 
00329                         foreach ( $res as $row ) {
00330                                 $timestamps[$row->page_namespace][$row->page_title] = $row->page_touched;
00331                         }
00332                 }
00333 
00334                 return $timestamps;
00335         }
00336 
00337         function loadDependencyValues() {
00338                 $this->timestamps = $this->calculateTimestamps();
00339         }
00340 
00344         function __sleep() {
00345                 return array( 'timestamps' );
00346         }
00347 
00351         function getLinkBatch() {
00352                 if ( !isset( $this->linkBatch ) ) {
00353                         $this->linkBatch = new LinkBatch;
00354                         $this->linkBatch->setArray( $this->timestamps );
00355                 }
00356                 return $this->linkBatch;
00357         }
00358 
00362         function isExpired() {
00363                 $newTimestamps = $this->calculateTimestamps();
00364 
00365                 foreach ( $this->timestamps as $ns => $dbks ) {
00366                         foreach ( $dbks as $dbk => $oldTimestamp ) {
00367                                 $newTimestamp = $newTimestamps[$ns][$dbk];
00368 
00369                                 if ( $oldTimestamp === false ) {
00370                                         if ( $newTimestamp === false ) {
00371                                                 # Still missing
00372                                         } else {
00373                                                 # Created
00374                                                 return true;
00375                                         }
00376                                 } elseif ( $newTimestamp === false ) {
00377                                         # Deleted
00378                                         return true;
00379                                 } elseif ( $newTimestamp > $oldTimestamp ) {
00380                                         # Updated
00381                                         return true;
00382                                 } else {
00383                                         # Unmodified
00384                                 }
00385                         }
00386                 }
00387 
00388                 return false;
00389         }
00390 }
00391 
00395 class GlobalDependency extends CacheDependency {
00396         var $name, $value;
00397 
00398         function __construct( $name ) {
00399                 $this->name = $name;
00400                 $this->value = $GLOBALS[$name];
00401         }
00402 
00406         function isExpired() {
00407                 if( !isset($GLOBALS[$this->name]) ) {
00408                         return true;
00409                 }
00410                 return $GLOBALS[$this->name] != $this->value;
00411         }
00412 }
00413 
00417 class ConstantDependency extends CacheDependency {
00418         var $name, $value;
00419 
00420         function __construct( $name ) {
00421                 $this->name = $name;
00422                 $this->value = constant( $name );
00423         }
00424 
00428         function isExpired() {
00429                 return constant( $this->name ) != $this->value;
00430         }
00431 }