diff --git a/wp-content/db.php b/wp-content/db.php index c660ae8a97fd3749da23654a22e34e77ea455f2e..5b73b397c9bf0b7910e4f634364621fcec500041 100644 --- a/wp-content/db.php +++ b/wp-content/db.php @@ -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; }