MediaWiki
REL1_23
|
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 }