Time out long running database list

This commit is contained in:
Jakub Vrana 2012-08-19 17:12:19 -07:00
parent 5e0038b62d
commit 1f53cd3386
7 changed files with 69 additions and 14 deletions

View file

@ -268,15 +268,18 @@ if (!defined("DRIVER")) {
function get_databases($flush) {
global $connection;
// SHOW DATABASES can take a very long time so it is cached
$return = &get_session("dbs");
$return = get_session("dbs");
if ($return === null) {
$kill = ($flush ? kill_timeout() : 0);
$return = @get_vals("/* Adminer $kill */ " . ($connection->server_info >= 5 // @ - may be killed
? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA"
: "SHOW DATABASES"
)); // SHOW DATABASES can be disabled by skip_show_database
if ($flush) {
ob_flush();
flush();
cancel_kill_timeout();
}
$databases = get_vals($connection->server_info >= 5 ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" : "SHOW DATABASES"); // SHOW DATABASES can be disabled by skip_show_database
restart_session();
$return = $databases;
set_session("dbs", $return);
stop_session();
}
return $return;
@ -932,10 +935,11 @@ if (!defined("DRIVER")) {
}
/** Get process list
* @param bool
* @return array ($row)
*/
function process_list() {
return get_rows("SHOW FULL PROCESSLIST");
function process_list($full = true) {
return get_rows("SHOW" . ($full ? " FULL" : "") . " PROCESSLIST");
}
/** Get status variables

View file

@ -42,6 +42,13 @@ class Adminer {
return get_databases($flush);
}
/** Specify limit for waiting on some slow queries like DB list
* @return float number of seconds
*/
function queryTimeout() {
return 5;
}
/** Headers to send before HTML output
* @return bool true to send security headers
*/

View file

@ -22,6 +22,7 @@ if (isset($_GET["file"])) {
include "../adminer/include/functions.inc.php";
global $adminer, $connection, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $structured_types, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
}
@ -73,12 +74,13 @@ include "./include/adminer.inc.php";
include "../adminer/include/design.inc.php";
include "../adminer/include/xxtea.inc.php";
include "../adminer/include/auth.inc.php";
include "./include/connect.inc.php";
include "./include/editing.inc.php";
if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled
session_cache_limiter(""); // to allow restarting session
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
}
include "./include/connect.inc.php";
include "./include/editing.inc.php";
$on_actions = "RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT"; ///< @var string used in foreign_keys()

View file

@ -23,9 +23,6 @@ function connect_error() {
}
echo "<p>" . lang('%s version: %s through PHP extension %s', $drivers[DRIVER], "<b>$connection->server_info</b>", "<b>$connection->extension</b>") . "\n";
echo "<p>" . lang('Logged as: %s', "<b>" . h(logged_user()) . "</b>") . "\n";
if ($_GET["refresh"]) {
set_session("dbs", null);
}
$refresh = "<a href='" . h(ME) . "refresh=1'>" . lang('Refresh') . "</a>\n";
$databases = $adminer->databases();
if ($databases) {
@ -61,8 +58,9 @@ function connect_error() {
if (isset($_GET["status"])) {
$_GET["variables"] = $_GET["status"];
}
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect")) {
if (DB != "") {
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill")) {
if (DB != "" || $_GET["refresh"]) {
restart_session();
set_session("dbs", null);
}
connect_error(); // separate function to catch SQLite error

View file

@ -898,3 +898,38 @@ function is_url($string) {
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN
return (preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string, $match) ? strtolower($match[1]) : ""); //! restrict path, query and fragment characters
}
/** Launch timeout after which the query will be killed
* @return int kill token
*/
function kill_timeout() {
global $adminer, $token;
$kill = mt_rand();
?>
<script type="text/javascript">
var timeout = setTimeout(function () {
ajax('<?php echo js_escape(ME); ?>script=kill', function () {
}, 'token=<?php echo $token; ?>&kill=<?php echo $kill; ?>');
}, <?php echo 1000 * $adminer->queryTimeout(); ?>);
</script>
<?php
ob_flush();
flush();
return $kill;
}
/** Cancel kill query timeout
* @return null
*/
function cancel_kill_timeout() {
global $connection;
echo "<script type='text/javascript'>clearTimeout(timeout);</script>\n";
ob_flush();
flush();
if ($connection->errno == 2006) { // 2006 - CR_SERVER_GONE_ERROR
$connection2 = connect();
if (is_object($connection2)) {
$connection = $connection2;
}
}
}

View file

@ -31,6 +31,14 @@ if ($_GET["script"] == "db") {
json_row("sum-$key", number_format($val, 0, '.', lang(',')));
}
json_row("");
} elseif ($_GET["script"] == "kill") {
foreach (process_list(false) as $process) {
if (ereg('^/\* Adminer ' . (+$_POST["kill"]) . ' \*/', $process["Info"])) {
$connection->query("KILL $process[Id]");
}
}
} else { // connect
foreach (count_tables($adminer->databases()) as $db => $val) {
json_row("tables-" . js_escape($db), $val);

View file

@ -1,5 +1,6 @@
Adminer 3.5.2-dev:
Edit strings with \n in textarea
Time out long running database list
Use VALUES() in INSERT+UPDATE export
Style logout button as link