]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/db/LoadMonitor.php
MediaWiki 1.17.0
[autoinstalls/mediawiki.git] / includes / db / LoadMonitor.php
1 <?php
2 /**
3  * Database load monitoring
4  *
5  * @file
6  * @ingroup Database
7  */
8
9 /**
10  * An interface for database load monitoring
11  *
12  * @ingroup Database
13  */
14 interface LoadMonitor {
15         /**
16          * Construct a new LoadMonitor with a given LoadBalancer parent
17          */
18         function __construct( $parent );
19         
20         /**
21          * Perform pre-connection load ratio adjustment.
22          * @param $loads Array
23          * @param $group String: the selected query group
24          * @param $wiki String
25          */
26         function scaleLoads( &$loads, $group = false, $wiki = false );
27
28         /**
29          * Perform post-connection backoff.
30          *
31          * If the connection is in overload, this should return a backoff factor 
32          * which will be used to control polling time. The number of threads 
33          * connected is a good measure.
34          *
35          * If there is no overload, zero can be returned.
36          *
37          * A threshold thread count is given, the concrete class may compare this 
38          * to the running thread count. The threshold may be false, which indicates
39          * that the sysadmin has not configured this feature.
40          *
41          * @param $conn DatabaseBase
42          * @param $threshold Float
43          */
44         function postConnectionBackoff( $conn, $threshold );
45
46         /**
47          * Return an estimate of replication lag for each server
48          */
49         function getLagTimes( $serverIndexes, $wiki );
50 }
51
52
53 /**
54  * Basic MySQL load monitor with no external dependencies
55  * Uses memcached to cache the replication lag for a short time
56  *
57  * @ingroup Database
58  */
59 class LoadMonitor_MySQL implements LoadMonitor {
60         var $parent; // LoadBalancer
61
62         function __construct( $parent ) {
63                 $this->parent = $parent;
64         }
65
66         function scaleLoads( &$loads, $group = false, $wiki = false ) {
67         }
68
69         function getLagTimes( $serverIndexes, $wiki ) {
70                 wfProfileIn( __METHOD__ );
71                 $expiry = 5;
72                 $requestRate = 10;
73
74                 global $wgMemc;
75                 if ( empty( $wgMemc ) )
76                         $wgMemc = wfGetMainCache();
77                 
78                 $masterName = $this->parent->getServerName( 0 );
79                 $memcKey = wfMemcKey( 'lag_times', $masterName );
80                 $times = $wgMemc->get( $memcKey );
81                 if ( $times ) {
82                         # Randomly recache with probability rising over $expiry
83                         $elapsed = time() - $times['timestamp'];
84                         $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
85                         if ( mt_rand( 0, $chance ) != 0 ) {
86                                 unset( $times['timestamp'] );
87                                 wfProfileOut( __METHOD__ );
88                                 return $times;
89                         }
90                         wfIncrStats( 'lag_cache_miss_expired' );
91                 } else {
92                         wfIncrStats( 'lag_cache_miss_absent' );
93                 }
94
95                 # Cache key missing or expired
96
97                 $times = array();
98                 foreach ( $serverIndexes as $i ) {
99                         if ($i == 0) { # Master
100                                 $times[$i] = 0;
101                         } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) {
102                                 $times[$i] = $conn->getLag();
103                         } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) {
104                                 $times[$i] = $conn->getLag();
105                         }
106                 }
107
108                 # Add a timestamp key so we know when it was cached
109                 $times['timestamp'] = time();
110                 $wgMemc->set( $memcKey, $times, $expiry );
111
112                 # But don't give the timestamp to the caller
113                 unset($times['timestamp']);
114                 $lagTimes = $times;
115
116                 wfProfileOut( __METHOD__ );
117                 return $lagTimes;
118         }
119
120         function postConnectionBackoff( $conn, $threshold ) {
121                 if ( !$threshold ) {
122                         return 0;
123                 }
124                 $status = $conn->getStatus("Thread%");
125                 if ( $status['Threads_running'] > $threshold ) {
126                         return $status['Threads_connected'];
127                 } else {
128                         return 0;
129                 }
130         }
131 }
132