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