0) // clear temp log. Needed to find out if new log-messages were added $_SESSION['temp_log'] = $_SESSION['log']; if (!isset($config['language'])) { // some server limit the number of vars that can be saved in a session die('Incomplete session in restore_ajax.php'); } $restore['restore_in_progress'] = 1; $timeElapsed = 0; $commandsFound = 0; try { $dbo->setConnectionCharset($restore['dump_encoding']); $dbo->selectDb($config['db_actual'], true); } catch (Exception $e) { die($lang['L_DB_SELECT_ERROR'] . $config['db_actual'] . $lang['L_DB_SELECT_ERROR2'] . '
' . $e->getMessage()); } // open backup file $file = $config['paths']['backup'] . $restore['filename']; if ($restore['compressed'] == 1) { $restore['filehandle'] = gzopen($file, 'r'); } else { $restore['filehandle'] = fopen($file, 'r'); } if (!$restore['filehandle']) { // fatal error: we couldn't open the backup file writeToErrorLog( '', '', $lang['L_FILE_OPEN_ERROR'] . ': ' . $config['paths']['backup'] . $restore['filename'], 0 ); die($lang['L_FILE_OPEN_ERROR'] . ': ' . $restore['filename']); } $filesize = filesize($config['paths']['backup'] . $restore['filename']); // move file pointer to the actual positon in the file if ($restore['compressed']) { gzseek($restore['filehandle'], $restore['offset']); } else { fseek($restore['filehandle'], $restore['offset']); } $log=new Log(); // Disable Keys of actual table (after page-refresh: again!) // to speed up restoring // but only if the table should be restored and if it already exists $existingTables = $dbo->getTables($config['db_actual']); $actualTable = $restore['actual_table']; if (in_array($actualTable, $existingTables)) { if ($restore['tables_to_restore']) { if (in_array($actualTable, $restore['tables_to_restore'])) { Sql::disableKeys($dbo, $restore['actual_table']); } } elseif ($actualTable > '' && $actualTable != 'unbekannt') { Sql::disableKeys($dbo, $restore['actual_table']); } } WHILE ($commandsFound < $restore['speed'] && $timeElapsed < $restore['max_zeit'] && !$restore['fileEOF'] && !$restore['EOB']) { $sqlCommand = getQueryFromFile(); $commandsFound++; if ($sqlCommand > '') { //$log->write(Log::PHP, $sqlCommand); try { $res = $dbo->query($sqlCommand, MsdDbFactory::SIMPLE); // get nr of affected rows $command = strtoupper(substr($sqlCommand, 0, 7)); if ($command == 'INSERT ' || $command == 'REPLACE') { $rowsAffected = $dbo->getAffectedRows(); $restore['records_inserted'] += $rowsAffected; if (!isset( $restore['records_inserted_table'][$restore['actual_table']]) ) { $restore['records_inserted_table'][$restore['actual_table']] = 0; } $restore['records_inserted_table'][$restore['actual_table']] += $rowsAffected; } } catch (Exception $e) { // we've got a mysql error $sqlError = $e->getMessage(); if ($sqlError != '') { if (strtolower(substr($sqlError, 0, 15)) == 'duplicate entry') { writeToErrorLog( $config['db_actual'], $sqlCommand, $sqlError, 1 ); $restore['notices']++; } else { if ($config['stop_with_error'] == 0) { // according to the config we continue restoring // but log the error writeToErrorLog( $config['db_actual'], $sqlCommand, $sqlError, 0 ); $restore['errors']++; } else { // we should die if errors occur -> print error message writeToErrorLog( $config['db_actual'], $sqlCommand, 'Fatal error, restore failed: ' . $sqlError, 0 ); SQLError($sqlCommand, $sqlError); $restore['restore_in_progress'] = 0; die(); // TODO clean end of process - last message is not // logged on restore screen and // not sent back to client. Flag missing here that // should be handled via JSON } } } } } $timeElapsed = time() - $restore['page_start_time']; } if ($restore['compressed']) { $restore['offset'] = gztell($restore['filehandle']); gzclose($restore['filehandle']); } else { $restore['offset'] = ftell($restore['filehandle']); fclose($restore['filehandle']); } $restore['page_refreshs']++; // progress of actual file if ($restore['compressed']) { // compressed backup - there is no way to get the exact file offset, // because gztell delivers uncompressed bytes // so we assume the average packing factor is 11 and will divide the file // offset by it $restore['progress_file_percent'] = $restore['offset'] / 11 * 100 / $filesize; if ($restore['progress_file_percent'] > 100) $restore['progress_file_percent'] = 100; } else { // uncompressed backup -> get percentage from file offset $restore['progress_file_percent'] = 0; if ($filesize > 0) { $restore['progress_file_percent'] = ($restore['offset'] * 100) / $filesize; } } // Overall progress if ($restore['records_total'] > 0) { // it's a backup of MySQLDumper (the number of total records is known) -> // calculate on count of records $restore['progress_overall_percent'] = $restore['records_inserted'] * 100 / $restore['records_total']; } else { // backup from another script. We don't know how many records will follow $restore['progress_overall_percent'] = 0; } // tables to create if ((int) $restore['tables_total'] > 0) { // MSD-Backup // tables to go $tablesToDo = $restore['tables_total']; // selected tables should be restored? Overwrite value if (is_array($restore['tables_to_restore'])) $tablesToDo = count($restore['tables_to_restore']); $tablesToCreate = sprintf( $lang['L_RESTORE_TABLES_COMPLETED'], $restore['table_ready'], $tablesToDo ); $recordsDone = sprintf( $lang['L_ACTUALLY_INSERTED_RECORDS_OF'], String::formatNumber($restore['records_inserted']), String::formatNumber($restore['records_total']) ); } else { // not a MSD-Backup $tablesToCreate = sprintf( $lang['L_RESTORE_TABLES_COMPLETED'], $restore['table_ready'], $lang['L_UNKNOWN'] ); $recordsDone = sprintf( $lang['L_ACTUALLY_INSERTED_RECORDS'], String::formatNumber($restore['records_inserted']), $lang['L_UNKNOWN'] ); } // calculate speed for next page call if ($timeElapsed < $restore['max_zeit']) { // wenn wir mehr als die Haelfte der Zeit noch haetten nutzen koennen: // Anzahl direkt um fast das Doppelte erhoehen if ($timeElapsed < $restore['max_zeit'] / 2) $restore['speed'] = $restore['speed'] * 1.8; else $restore['speed'] = $restore['speed'] * $config['tuning_add']; if ($restore['speed'] > $config['maxspeed']) $restore['speed'] = $config['maxspeed']; } else { $restore['speed'] = $restore['speed'] * $config['tuning_sub']; if ($restore['speed'] < $config['minspeed']) $restore['speed'] = $config['minspeed']; } if ($restore['fileEOF'] && $restore['part'] == 0) $restore['EOB'] = true; //part is >0 if we have a Multipart backup if ($restore['EOB']) { // Done $time = getTimeFormat(time() - $restore['restore_start_time']); $log->write( Log::PHP, sprintf( $lang['L_RESTORE_DB_COMPLETE_IN'], $config['db_actual'], $time ) ); $restore['restore_in_progress'] = 0; } else { if ($restore['fileEOF']) { // let's get the next Multipart file $restore['fileEOF'] = false; $nextfile = getNextPart($restore['filename'], 0, true); // there is more to do -> process the next Multipart file if (!file_exists($config['paths']['backup'] . $nextfile)) { writeToErrorLog( $config['db_actual'], '', sprintf($lang['L_ERROR_MULTIPART_RESTORE'], $nextfile) ); $restore['restore_in_progress'] = 0; } else { $restore['filename'] = $nextfile; $restore['offset'] = 0; $restore['part']++; $log->write( Log::PHP, sprintf( $lang['L_CONTINUE_MULTIPART_RESTORE'], $restore['filename'] ) ); } } } // collect values to return to client $r = array(); $json = new Services_JSON(); $r['restore_in_progress'] = $restore['restore_in_progress']; if ($restore['page_refreshs'] == 1) { // Only send on first page call because values won't change $r['speed_min'] = String::formatNumber($config['minspeed']); $r['speed_max'] = String::formatNumber($config['maxspeed']); $r['dump_encoding'] = $restore['dump_encoding']; } // if restore is finished and file is gzipped, the file pointer // might not be accurate if ($restore['restore_in_progress'] == 0) { // correct percentage of file to now known exact value $restore['progress_file_percent'] = 100; $restore['speed'] = 0; } $r['filename'] = $restore['filename']; $r['nr_of_errors'] = String::formatNumber($restore['errors']); $r['nr_of_notices'] = String::formatNumber($restore['notices']); $r['progress_file_percent'] = String::formatNumber( $restore['progress_file_percent'], 2 ); $r['progress_file_bar_width'] = round($restore['progress_file_percent'] * 3, 0); if ($restore['progress_overall_percent'] > 0) { $r['progress_overall_percent'] = String::formatNumber( $restore['progress_overall_percent'], 2 ); $r['progress_overall_bar_width'] = round( $restore['progress_overall_percent'] * 3, 0 ); } else { $r['progress_overall_percent'] = $lang['L_UNKNOWN']; $r['progress_overall_bar_width'] = 0; } if ($restore['part'] > 0) { $r['part'] = $restore['part']; } $r['tables_to_create'] = $tablesToCreate; $r['records_done'] = $recordsDone; $r['actual_table'] = sprintf( $lang['L_ANALYZING_TABLE'], $restore['actual_table'] ); $r['speed'] = String::formatNumber($restore['speed']); $r['speedbar_width'] = round( $restore['speed'] * 100 / $config['maxspeed'] * 3, 0 ); $r['page_refreshs'] = String::formatNumber($restore['page_refreshs']); $elapsed = time() - $restore['restore_start_time']; $r['elapsed_time'] = getTimeFormat($elapsed); // if we restore a MySQLDumper-Backup we know the nr of records and can // calculate the estimated time from it // if we restore a backup from another program we need to rely on the filesize //which is not accurate // when the file is gzipped, but we can't help it because there is no way to // get the exact file pointer position in a gzipped file. // So we give our best to guess the corect position (see line 117 above) if ($restore['progress_overall_percent'] > 0) { $percentageDone = $restore['progress_overall_percent']; } else { $percentageDone = $restore['progress_file_percent']; } $estimatedTime = 0; if ($percentageDone > 0) { $estimatedTime = (100 - $percentageDone) * ($elapsed / $percentageDone); $r['estimated_end'] = getTimeFormat($estimatedTime); } else { $r['estimated_end'] = $lang['L_UNKNOWN']; } // check if new log-messages have been added $messages = getArrayDiffAssocRecursive($_SESSION['log'], $_SESSION['temp_log']); if (isset($messages['actions']) && is_array($messages['actions'])) $r['actions'] = implode('
', $messages['actions']); if (isset($messages['errors']) && is_array($messages['errors'])) $r['errors'] = implode('
', $messages['errors']); $_SESSION['log'] = $_SESSION['log'] + $_SESSION['temp_log']; // save actual values to session $_SESSION['restore'] = $restore; echo $json->encode($r); obend(true);