MediaWiki  REL1_23
LoadMonitor.php
Go to the documentation of this file.
00001 <?php
00029 interface LoadMonitor {
00035     public function __construct( $parent );
00036 
00043     public function scaleLoads( &$loads, $group = false, $wiki = false );
00044 
00053     public function getLagTimes( $serverIndexes, $wiki );
00054 }
00055 
00056 class LoadMonitorNull implements LoadMonitor {
00057     public function __construct( $parent ) {
00058     }
00059 
00060     public function scaleLoads( &$loads, $group = false, $wiki = false ) {
00061     }
00062 
00063     public function getLagTimes( $serverIndexes, $wiki ) {
00064         return array_fill_keys( $serverIndexes, 0 );
00065     }
00066 }
00067 
00074 class LoadMonitorMySQL implements LoadMonitor {
00076     public $parent;
00077 
00078     public function __construct( $parent ) {
00079         $this->parent = $parent;
00080     }
00081 
00082     public function scaleLoads( &$loads, $group = false, $wiki = false ) {
00083     }
00084 
00085     public function getLagTimes( $serverIndexes, $wiki ) {
00086         if ( count( $serverIndexes ) == 1 && reset( $serverIndexes ) == 0 ) {
00087             // Single server only, just return zero without caching
00088             return array( 0 => 0 );
00089         }
00090 
00091         $section = new ProfileSection( __METHOD__ );
00092 
00093         $expiry = 5;
00094         $requestRate = 10;
00095 
00096         global $wgMemc;
00097         if ( empty( $wgMemc ) ) {
00098             $wgMemc = wfGetMainCache();
00099         }
00100 
00101         $masterName = $this->parent->getServerName( 0 );
00102         $memcKey = wfMemcKey( 'lag_times', $masterName );
00103         $times = $wgMemc->get( $memcKey );
00104         if ( is_array( $times ) ) {
00105             # Randomly recache with probability rising over $expiry
00106             $elapsed = time() - $times['timestamp'];
00107             $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
00108             if ( mt_rand( 0, $chance ) != 0 ) {
00109                 unset( $times['timestamp'] ); // hide from caller
00110 
00111                 return $times;
00112             }
00113             wfIncrStats( 'lag_cache_miss_expired' );
00114         } else {
00115             wfIncrStats( 'lag_cache_miss_absent' );
00116         }
00117 
00118         # Cache key missing or expired
00119         if ( $wgMemc->add( "$memcKey:lock", 1, 10 ) ) {
00120             # Let this process alone update the cache value
00121             $unlocker = new ScopedCallback( function () use ( $wgMemc, $memcKey ) {
00122                 $wgMemc->delete( $memcKey );
00123             } );
00124         } elseif ( is_array( $times ) ) {
00125             # Could not acquire lock but an old cache exists, so use it
00126             unset( $times['timestamp'] ); // hide from caller
00127 
00128             return $times;
00129         }
00130 
00131         $times = array();
00132         foreach ( $serverIndexes as $i ) {
00133             if ( $i == 0 ) { # Master
00134                 $times[$i] = 0;
00135             } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) {
00136                 $times[$i] = $conn->getLag();
00137             } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) {
00138                 $times[$i] = $conn->getLag();
00139             }
00140         }
00141 
00142         # Add a timestamp key so we know when it was cached
00143         $times['timestamp'] = time();
00144         $wgMemc->set( $memcKey, $times, $expiry + 10 );
00145         unset( $times['timestamp'] ); // hide from caller
00146 
00147         return $times;
00148     }
00149 }