]> git.joonet.de Git - adminer.git/commitdiff
Time out long running database list
authorJakub Vrana <jakub@vrana.cz>
Mon, 20 Aug 2012 00:12:19 +0000 (17:12 -0700)
committerJakub Vrana <jakub@vrana.cz>
Mon, 20 Aug 2012 02:35:11 +0000 (19:35 -0700)
adminer/drivers/mysql.inc.php
adminer/include/adminer.inc.php
adminer/include/bootstrap.inc.php
adminer/include/connect.inc.php
adminer/include/functions.inc.php
adminer/script.inc.php
changes.txt

index dce1433eb667785a91a3ce7c8b40fae7b7b6e345..e02f818991aa5da63d8e6865e9fe8a22604df42c 100644 (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
index 6b4f1cd0daa4c08c438a99977b95c484af76f2c6..6bebe42201c5eaedff0000ad3092de280ea0b04f 100644 (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
        */
index 48a36dd1f9706fa9b0eedeedd03f6f3b616402d6..85cb90380009c3838f5c85cdc63122a70ded62bf 100644 (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()
index 90d8f063ac7493184db5c206345d724fcb793c8b..c0ce43d957efb32a5a78846ba270c1b81878fb0f 100644 (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
index 6f7004d2f37f4f8fc5780445de1772ce43dcd6d3..8030b8ec17cb6b7bc34ea3aa83367bfe0231a559 100644 (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;
+               }
+       }
+}
index 39ede5bf2842d1611143728790bdf66a05dc5b4b..ed9c09d7e5cea245813776400996f75ad3ab7c1c 100644 (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);
index 5b5f4835edadf57423743bf44e8a6f1bd4998963..34761b55184f1659c86680985e6274b622634563 100644 (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