Skip to content
Snippets Groups Projects
Commit f3767256 authored by lechuck's avatar lechuck Committed by lechuck
Browse files

hyperdb update reprise

parent 4da566d0
No related branches found
No related tags found
No related merge requests found
......@@ -141,6 +141,12 @@ class hyperdb extends wpdb {
*/
var $open_connections = array();
/**
* Lookup array (dbhname => host:port)
* @var array
*/
var $dbh2host = array();
/**
* The last server used and the database name selected
* @var array
......@@ -245,7 +251,7 @@ class hyperdb extends wpdb {
// Remove characters that can legally trail the table name
$q = rtrim($q, ';/-#');
// allow (select...) union [...] style queries. Use the first queries table name.
$q = ltrim($q, "\t (");
$q = ltrim($q, "\t (");
// Quickly match most common queries
if ( preg_match('/^\s*(?:'
......@@ -261,10 +267,11 @@ class hyperdb extends wpdb {
if ( preg_match('/^\s*SELECT.*?\s+FOUND_ROWS\(\)/is', $q) )
return $this->last_table;
// SHOW TABLE STATUS LIKE and SHOW TABLE STATUS WHERE Name =
if ( preg_match('/^\s*'
// SHOW TABLE STATUS and SHOW TABLES
if ( preg_match('/^\s*(?:'
. 'SHOW\s+TABLE\s+STATUS.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
. '\W(\w+)\W/is', $q, $maybe) )
. '|SHOW\s+(?:FULL\s+)?TABLES.+(?:LIKE\s+|WHERE\s+Name\s*=\s*)'
. ')\W(\w+)\W/is', $q, $maybe) )
return $maybe[1];
// Big pattern for the rest of the table-related queries in MySQL 5.0
......@@ -313,7 +320,7 @@ class hyperdb extends wpdb {
* of them returns something other than null.
*/
function run_callbacks( $group, $args = null) {
if ( !is_array( $this->hyper_callbacks[ $group ] ) )
if ( !isset( $this->hyper_callbacks[ $group ] ) || !is_array( $this->hyper_callbacks[ $group ] ) )
return null;
if ( !isset($args) ) {
......@@ -336,7 +343,7 @@ class hyperdb extends wpdb {
* @param string query
* @return resource mysql database connection
*/
function &db_connect( $query = '' ) {
function db_connect( $query = '' ) {
$connect_function = $this->persistent ? 'mysql_pconnect' : 'mysql_connect';
if ( empty( $this->hyper_servers ) ) {
if ( is_resource( $this->dbh ) )
......@@ -385,7 +392,7 @@ class hyperdb extends wpdb {
$this->dataset = $dataset;
// Determine whether the query must be sent to the master (a writable server)
if ( $use_master || $this->srtm === true || isset($this->srtm[$this->table]) ) {
if ( !empty( $use_master ) || $this->srtm === true || isset($this->srtm[$this->table]) ) {
$use_master = true;
} elseif ( $is_write = $this->is_write_query($query) ) {
$use_master = true;
......@@ -393,11 +400,14 @@ class hyperdb extends wpdb {
$this->srtm[$this->table] = true;
} elseif ( !isset($use_master) && is_array($this->srtm) && !empty($this->srtm) ) {
// Detect queries that have a join in the srtm array.
$pattern = '/' . implode('|', array_keys($this->srtm)) . '/i';
if ( preg_match($pattern, substr($query, 0, 1000)) )
$use_master = true;
else
$use_master = false;
$use_master = false;
$query_match = substr( $query, 0, 1000 );
foreach ( $this->srtm as $key => $value ) {
if ( false !== stripos( $query_match, $key ) ) {
$use_master = true;
break;
}
}
} else {
$use_master = false;
}
......@@ -411,7 +421,7 @@ class hyperdb extends wpdb {
}
// Try to reuse an existing connection
while ( is_resource($this->dbhs[$dbhname]) ) {
while ( isset( $this->dbhs[$dbhname] ) && is_resource( $this->dbhs[$dbhname] ) ) {
// Find the connection for incrementing counters
foreach ( array_keys($this->db_connections) as $i )
if ( $this->db_connections[$i]['dbhname'] == $dbhname )
......@@ -423,7 +433,11 @@ class hyperdb extends wpdb {
if ( $name != $this->used_servers[$dbhname]['name'] ) {
if ( !mysql_select_db($name, $this->dbhs[$dbhname]) ) {
// this can happen when the user varies and lacks permission on the $name database
++$conn['disconnect (select failed)'];
if ( isset( $conn['disconnect (select failed)'] ) )
++$conn['disconnect (select failed)'];
else
$conn['disconnect (select failed)'] = 1;
$this->disconnect($dbhname);
break;
}
......@@ -445,17 +459,24 @@ class hyperdb extends wpdb {
$this->last_connection = compact('dbhname', 'name');
if ( !mysql_ping($this->dbhs[$dbhname]) ) {
++$conn['disconnect (ping failed)'];
if ( isset( $conn['disconnect (ping failed)'] ) )
++$conn['disconnect (ping failed)'];
else
$conn['disconnect (ping failed)'] = 1;
$this->disconnect($dbhname);
break;
}
++$conn['queries'];
if ( isset( $conn['queries'] ) )
++$conn['queries'];
else
$conn['queries'] = 1;
return $this->dbhs[$dbhname];
}
if ( $this->write && defined( "MASTER_DB_DEAD" ) ) {
if ( $use_master && defined( "MASTER_DB_DEAD" ) ) {
return $this->bail("We're updating the database, please try back in 5 minutes. If you are posting to your blog please hit the refresh button on your browser in a few minutes to post the data again. It will be posted as soon as the database is back online again.");
}
......@@ -500,8 +521,7 @@ class hyperdb extends wpdb {
// $host, $user, $password, $name, $read, $write [, $lag_threshold, $connect_function, $timeout ]
extract($this->hyper_servers[$dataset][$operation][$group][$key], EXTR_OVERWRITE);
list($host, $port) = explode(':', $host);
$port = null;
// Split host:port into $host and $port
if ( strpos($host, ':') )
......@@ -537,13 +557,13 @@ class hyperdb extends wpdb {
&& ( $lagged_status = $this->get_lag_cache() ) === HYPERDB_LAG_BEHIND
) {
// If it is the last lagged slave and it is with the best preference we will ignore its lag
if ( !isset( $unique_lagged_slaves[ "$host:$port" ] )
if ( !isset( $unique_lagged_slaves["$host:$port"] )
&& $unique_servers == count( $unique_lagged_slaves ) + 1
&& $group == $min_group )
{
$this->lag_threshold = null;
} else {
$unique_lagged_slaves["$host.$port"] = $this->lag;
$unique_lagged_slaves["$host:$port"] = $this->lag;
continue;
}
}
......@@ -572,7 +592,7 @@ class hyperdb extends wpdb {
&& $lagged_status !== HYPERDB_LAG_OK
&& ( $lagged_status = $this->get_lag() ) === HYPERDB_LAG_BEHIND
&& !(
!isset( $unique_lagged_slaves[ "$host:$port" ] )
!isset( $unique_lagged_slaves["$host:$port"] )
&& $unique_servers == count( $unique_lagged_slaves ) + 1
&& $group == $min_group
)
......@@ -590,8 +610,7 @@ class hyperdb extends wpdb {
$this->dbh2host[$dbhname] = "$host:$port";
$queries = 1;
$lag = isset( $this->lag ) ? $this->lag : 0;
$this->last_connection = compact('dbhname', 'host', 'port', 'user', 'name', 'tcp', 'elapsed', 'success', 'querie
s', 'lag');
$this->last_connection = compact('dbhname', 'host', 'port', 'user', 'name', 'tcp', 'elapsed', 'success', 'queries', 'lag');
$this->db_connections[] = $this->last_connection;
$this->open_connections[] = $dbhname;
break;
......@@ -601,7 +620,6 @@ s', 'lag');
$success = false;
$this->last_connection = compact('dbhname', 'host', 'port', 'user', 'name', 'tcp', 'elapsed', 'success');
$this->db_connections[] = $this->last_connection;
$msg = date( "Y-m-d H:i:s" ) . " Can't select $dbhname - \n";
$msg .= "'referrer' => '{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}',\n";
$msg .= "'server' => {$server},\n";
......@@ -621,7 +639,7 @@ s', 'lag');
$tries_remaining = count( $servers );
continue;
}
$error_details = array(
'host' => $host,
'port' => $port,
......@@ -638,6 +656,12 @@ s', 'lag');
break;
} while ( true );
if ( !isset( $charset ) )
$charset = null;
if ( !isset( $collate ) )
$collate = null;
$this->set_charset($this->dbhs[$dbhname], $charset, $collate);
$this->dbh = $this->dbhs[$dbhname]; // needed by $wpdb->_real_escape()
......@@ -901,11 +925,39 @@ s', 'lag');
* Check the responsiveness of a tcp/ip daemon
* @return (bool) true when $host:$post responds within $float_timeout seconds, else (bool) false
*/
function check_tcp_responsiveness($host, $port, $float_timeout) {
$socket = @ fsockopen($host, $port, $errno, $errstr, $float_timeout);
if ( $socket === false )
function check_tcp_responsiveness( $host, $port, $float_timeout ) {
if ( function_exists( 'apc_store' ) ) {
$use_apc = true;
$apc_key = "{$host}{$port}";
$apc_ttl = 10;
} else {
$use_apc = false;
}
if ( $use_apc ) {
$cached_value = apc_fetch( $apc_key );
switch ( $cached_value ) {
case 'up':
$this->tcp_responsive = 'true';
return true;
case 'down':
$this->tcp_responsive = 'false';
return false;
}
}
$socket = @ fsockopen( $host, $port, $errno, $errstr, $float_timeout );
if ( $socket === false ) {
if ( $use_apc )
apc_store( $apc_key, 'down', $apc_ttl );
return "[ > $float_timeout ] ($errno) '$errstr'";
fclose($socket);
}
fclose( $socket );
if ( $use_apc )
apc_store( $apc_key, 'up', $apc_ttl );
return true;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment