Topic: Repairing tables

Theres been quite alot of people with errors which could be fixed automatically by PunBB attempting to repair the table on specific error messages, what do you think?

Re: Repairing tables

What, you mean in the error function if it's a corrupted table PunBB attempts to repair it?

Re: Repairing tables

precisely

4 (edited by Smartys 2006-01-07 17:40)

Re: Repairing tables

Connor basically dared me to write this tongue
The idea is basically to send the error and then repair the table in the background

//
// Display a simple error message
//
function error($message, $file, $line, $db_error = false)
{
    global $pun_config;

    // Set a default title if the script failed before $pun_config could be populated
    if (empty($pun_config))
        $pun_config['o_board_title'] = 'PunBB';

    // Empty output buffer and stop buffering
    @ob_end_clean();

    // Add the Connection: close header
    header("Connection: close");

    // "Restart" output buffering if we are using ob_gzhandler (since the gzip header is already sent)
    if (!empty($pun_config['o_gzip']) && extension_loaded('zlib') && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== false))
        ob_start('ob_gzhandler');
    else
        ob_start();

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><?php echo pun_htmlspecialchars($pun_config['o_board_title']) ?> / Error</title>
<style type="text/css">
<!--
BODY {MARGIN: 10% 20% auto 20%; font: 10px Verdana, Arial, Helvetica, sans-serif}
#errorbox {BORDER: 1px solid #B84623}
H2 {MARGIN: 0; COLOR: #FFFFFF; BACKGROUND-COLOR: #B84623; FONT-SIZE: 1.1em; PADDING: 5px 4px}
#errorbox DIV {PADDING: 6px 5px; BACKGROUND-COLOR: #F1F1F1}
-->
</style>
</head>
<body>

<div id="errorbox">
    <h2>An error was encountered</h2>
    <div>
<?php

    if (defined('PUN_DEBUG'))
    {
        echo "\t\t".'<strong>File:</strong> '.$file.'<br />'."\n\t\t".'<strong>Line:</strong> '.$line.'<br /><br />'."\n\t\t".'<strong>PunBB reported</strong>: '.$message."\n";

        if ($db_error)
        {
            echo "\t\t".'<br /><br /><strong>Database reported:</strong> '.pun_htmlspecialchars($db_error['error_msg']).(($db_error['error_no']) ? ' (Errno: '.$db_error['error_no'].')' : '')."\n";

            if ($db_error['error_sql'] != '')
                echo "\t\t".'<br /><br /><strong>Failed query:</strong> '.pun_htmlspecialchars($db_error['error_sql'])."\n";
        }
    }
    else
        echo "\t\t".'Error: <strong>'.$message.'.</strong>'."\n";
?>
    </div>
</div>

</body>
</html>
<?php
    // We output the size so that the browser knows when to not look for any more text
    $size = ob_get_length();
    header('Content-Length: '.$size);

    // Now, lets see if we need to run a repair
    if ($db_error['error_no'] == 145)
    {
        We remove "Can't open file: '" and ".MYD'" and are left with the tablename
        $table = substr($db_error['error_msg'], 18, strlen($db_error['error_msg']) - 23);

        $GLOBALS['db']->query('REPAIR TABLE '.$table);
    }

    // If a database connection was established (before this error) we close it
    if ($db_error)
        $GLOBALS['db']->close();

    exit;
}

Completely untested and probably there's something very wrong with it (aside from my fun use of substr tongue) but that's how I see it working (in theory)
Edit: found one error: I'm pretty sure I'd have to use ob_flush before running the table repair

And I figured out why you get those ob_start errors when gzip is enabled: ob_end_clean() only removes one buffer (in most cases, the one for <pun_main> without gzip). Doing it again would ensure that the possibly gzipped ob_start was removed as well.

One issue with this would be: what if multiple people start running repair at once?

Re: Repairing tables

I was thinking about more than one person doing at at once, but how does mysql handle this? REPAIR can't use the same locks as normal queries since the lock could be the problem surely. I'd guess mysql would handle it though, probably doesn't matter.

Oh and of course you need to flush content thats the whole point of closing the connection tongue