/** * Runs a restoration step and returns an array to be used in the response. * * @return array * * @throws \Exception */ public function stepRestoration() { $parts = $this->getParam('parts', 1); $this->openFile(); $this->lineNumber = $this->start; $this->totalSizeRead = 0; $this->queries = 0; while ($this->timer->getTimeLeft() > 0) { $query = ''; // Get the next query line try { $query = $this->readNextLine(); } catch (\Exception $exc) { if ($exc->getCode() == 200) { break; } elseif ($exc->getCode() == 201) { continue; } } if (empty($query)) { continue; } // Update variables $this->totalSizeRead += strlen($query); $this->totalQueries++; $this->queries++; $this->lineNumber++; // Process the query line, running drop/rename queries as necessary $this->processQueryLine($query); } // Get the current file position $current_foffset = ftell($this->file); if ($current_foffset === false) { if (is_resource($this->file)) { @fclose($this->file); } throw new \Exception(Text::_('AWF_RESTORE_ERROR_CANTREADPOINTER')); } else { if (is_null($this->fileOffset)) { $this->fileOffset = 0; } $bytes_in_step = $current_foffset - $this->fileOffset; $this->runSize = (is_null($this->runSize) ? 0 : $this->runSize) + $bytes_in_step; $this->fileOffset = $current_foffset; } // Return statistics $bytes_togo = $this->totalSize - $this->runSize; // Check for global EOF if ($this->currentPart >= $parts - 1 && feof($this->file)) { $bytes_togo = 0; } // Save variables in storage $this->setToStorage('start', $this->start); $this->setToStorage('foffset', $this->fileOffset); $this->setToStorage('totalqueries', $this->totalQueries); $this->setToStorage('runsize', $this->runSize); if ($bytes_togo == 0) { // Clear stored variables if we're finished $this->removeInformationFromStorage(); } // Calculate estimated time $bytesPerSecond = $bytes_in_step / $this->timer->getRunningTime(); if ($bytesPerSecond <= 0.01) { $remainingSeconds = 120; } else { $remainingSeconds = round($bytes_togo / $bytesPerSecond, 0); } // Return meaningful data return array('percent' => round(100 * ($this->runSize / $this->totalSize), 1), 'restored' => $this->sizeformat($this->runSize), 'total' => $this->sizeformat($this->totalSize), 'queries_restored' => $this->totalQueries, 'current_line' => $this->lineNumber, 'current_part' => $this->currentPart, 'total_parts' => $parts, 'eta' => $this->etaformat($remainingSeconds), 'error' => '', 'done' => $bytes_togo == 0 ? '1' : '0'); }
/** * Performs the staggered download of file. * * @param array $params A parameters array, as sent by the user interface * * @return array A return status array */ public function importFromURL($params) { $this->params = $params; // Fetch data $filename = $this->getParam('file'); $frag = $this->getParam('frag', -1); $totalSize = $this->getParam('totalSize', -1); $doneSize = $this->getParam('doneSize', -1); $maxExecTime = $this->getParam('maxExecTime', 5); $runTimeBias = $this->getParam('runTimeBias', 75); $minExecTime = $this->getParam('minExecTime', 1); $localFilename = 'download.zip'; $tmpDir = Application::getInstance()->getContainer()->temporaryPath; $tmpDir = rtrim($tmpDir, '/\\'); $localFilename = $this->getParam('localFilename', $localFilename); // Init retArray $retArray = array("status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => 0); try { $timer = new Timer($minExecTime, $runTimeBias); $start = $timer->getRunningTime(); // Mark the start of this download $break = false; // Don't break the step // Figure out where on Earth to put that file $local_file = $tmpDir . '/' . $localFilename; //debugMsg("- Importing from $filename"); while ($timer->getTimeLeft() > 0 && !$break) { // Do we have to initialize the file? if ($frag == -1) { //debugMsg("-- First frag, killing local file"); // Currently downloaded size $doneSize = 0; if (@file_exists($local_file)) { @unlink($local_file); } // Delete and touch the output file $fp = @fopen($local_file, 'wb'); if ($fp !== false) { @fclose($fp); } // Init $frag = 0; //debugMsg("-- First frag, getting the file size"); $retArray['totalSize'] = $this->adapter->getFileSize($filename); $totalSize = $retArray['totalSize']; } // Calculate from and length $length = 1048576; $from = $frag * $length; $to = $length + $from - 1; // Try to download the first frag $required_time = 1.0; //debugMsg("-- Importing frag $frag, byte position from/to: $from / $to"); try { $result = $this->adapter->downloadAndReturn($filename, $from, $to); if ($result === false) { throw new \Exception(Text::sprintf('AWF_DOWNLOAD_ERR_LIB_COULDNOTDOWNLOADFROMURL', $filename), 500); } } catch (\Exception $e) { $result = false; $error = $e->getMessage(); } if ($result === false) { // Failed download if ($frag == 0) { // Failure to download first frag = failure to download. Period. $retArray['status'] = false; $retArray['error'] = $error; //debugMsg("-- Download FAILED"); return $retArray; } else { // Since this is a staggered download, consider this normal and finish $frag = -1; //debugMsg("-- Import complete"); $totalSize = $doneSize; $break = true; } } // Add the currently downloaded frag to the total size of downloaded files if ($result) { $filesize = strlen($result); //debugMsg("-- Successful download of $filesize bytes"); $doneSize += $filesize; // Append the file $fp = @fopen($local_file, 'ab'); if ($fp === false) { //debugMsg("-- Can't open local file $local_file for writing"); // Can't open the file for writing $retArray['status'] = false; $retArray['error'] = Text::sprintf('AWF_DOWNLOAD_ERR_LIB_COULDNOTWRITELOCALFILE', $local_file); return $retArray; } fwrite($fp, $result); fclose($fp); //debugMsg("-- Appended data to local file $local_file"); $frag++; //debugMsg("-- Proceeding to next fragment, frag $frag"); if ($filesize < $length || $filesize > $length) { // A partial download or a download larger than the frag size means we are done $frag = -1; //debugMsg("-- Import complete (partial download of last frag)"); $totalSize = $doneSize; $break = true; } } // Advance the frag pointer and mark the end $end = $timer->getRunningTime(); // Do we predict that we have enough time? $required_time = max(1.1 * ($end - $start), $required_time); if ($required_time > 10 - $end + $start) { $break = true; } $start = $end; } if ($frag == -1) { $percent = 100; } elseif ($doneSize <= 0) { $percent = 0; } else { if ($totalSize > 0) { $percent = 100 * ($doneSize / $totalSize); } else { $percent = 0; } } // Update $retArray $retArray = array("status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => $percent); } catch (\Exception $e) { //debugMsg("EXCEPTION RAISED:"); //debugMsg($e->getMessage()); $retArray['status'] = false; $retArray['error'] = $e->getMessage(); } return $retArray; }