dataRoot = getenv("TEMP").'/duparchivetester'; $this->scanFilepath = "{$this->dataRoot}/scan.json"; $this->processLockFilepath = "{$this->dataRoot}/lock.bin"; if ($isSmallArchive) { $this->dataDirectory = "{$this->dataRoot}/smalldata"; $this->archiveFilepath = "{$this->dataRoot}/archivesmall.daf"; } else { $this->dataDirectory = "{$this->dataRoot}/data"; $this->archiveFilepath = "{$this->dataRoot}/archive.daf"; } $this->restoreDirectory = "{$this->dataRoot}/restore"; $this->tempDirectory = "{$this->dataRoot}/temp"; $this->logFilepath = "{$this->dataRoot}/tester.log"; if (!file_exists($this->dataRoot)) { @mkdir($this->dataRoot); } if (!file_exists($this->dataDirectory)) { @mkdir($this->dataDirectory); } if (!file_exists($this->restoreDirectory)) { @mkdir($this->restoreDirectory); } if (!file_exists($this->tempDirectory)) { @mkdir($this->tempDirectory); } } } class DaTesterParams { public $compress = true; public $isSmallArchive = true; public $action; public $p1 = null; public $workerTime = 10; public $throttleDelayInUs = 100000; function __construct() { if (isset($_REQUEST['worker_time'])) { $this->workerTime = (int) $_REQUEST['worker_time']; } if (isset($_REQUEST['small_archive'])) { $this->isSmallArchive = ($_REQUEST['small_archive'] == 1); } if (isset($_REQUEST['compress'])) { $this->compress = ($_REQUEST['compress'] == 1); } if (isset($_REQUEST['action'])) { $this->action = $_REQUEST['action']; } else { $this->action = 'get_archive_info'; } if (isset($_REQUEST['p1'])) { $this->p1 = $_REQUEST['p1']; } } public function getQueryStringData() { $qsa = array(); $qsa['worker_time'] = $this->workerTime; $qsa['small_archive'] = ($this->isSmallArchive ? 1 : 0); $qsa['compress'] = ($this->compress ? 1 : 0); $qsa['action'] = $this->action; if ($this->p1 != null) { $qsa['p1'] = $this->p1; } return $qsa; } } class DaTester { private $paths; private $params; private $lockHandle; private $logger; public function __construct() { $this->params = new DaTesterParams(); $this->paths = new DaTesterPaths($this->params->isSmallArchive); } public function processRequest() { try { $this->lockHandle = DupLiteSnapLibIOU::fopen($this->paths->processLockFilepath, 'c+'); DupLiteSnapLibIOU::flock($this->lockHandle, LOCK_EX); $this->logger = new DaTesterLogging($this->paths->logFilepath); $this->logger->log("incoming request"); DupArchiveEngine::init($this->logger); $this->logger->log("Got file lock"); $this->logger->log("Action set to {$this->params->action}"); $initializeState = false; if ($this->params->action == 'start_create_test') { $initializeState = true; $this->params->action = 'create_test'; } else if ($this->params->action == 'start_expand_test') { $initializeState = true; $this->params->action = 'expand_test'; } else if ($this->params->action == 'start_validate_test') { $initializeState = true; $this->params->action = 'validate_test'; } $this->logger->log("incoming request after lock"); $spawnAnotherThread = false; echo "action={$this->params->action}
"; if ($this->params->action == 'get_status') { $this->get_status(); } else if ($this->params->action == 'create_test') { /* @var $daTesterCreateState DaTesterCreateState */ $daTesterCreateState = DaTesterCreateState::getInstance($initializeState); $daTesterState = &$daTesterCreateState; if ($initializeState) { $this->logger->log("Clearing files"); $this->clearCreateFiles(); DupArchiveEngine::createArchive($this->paths->archiveFilepath, $this->params->compress); $daTesterCreateState->archivePath = $this->paths->archiveFilepath; $daTesterCreateState->archiveOffset = DupLiteSnapLibIOU::filesize($this->paths->archiveFilepath); $daTesterCreateState->working = true; $daTesterCreateState->timeSliceInSecs = $this->params->workerTime; $daTesterCreateState->basePath = $this->paths->dataDirectory; $daTesterCreateState->isCompressed = $this->params->compress; $daTesterCreateState->throttleDelayInUs = $this->params->throttleDelayInUs; // $daTesterCreateState->globSize = self::GLOB_SIZE; $daTesterCreateState->save(); $this->logger->log("Cleared files"); $scan = DupArchiveScanUtil::createScan($this->paths->scanFilepath, $this->paths->dataDirectory); } else { $scan = DupArchiveScanUtil::getScan($this->paths->scanFilepath); } $this->logger->logObject("createstate", $daTesterCreateState); DupArchiveEngine::addItemsToArchive($daTesterCreateState, $scan); $spawnAnotherThread = $daTesterCreateState->working; if (!$spawnAnotherThread) { $this->logger->logObject("Done. Failures:", $daTesterCreateState->failures, true); } } else if ($this->params->action == 'start_add_file_test') { //DupArchiveUtil::writeToPLog("Start add file test"); $this->logger->clearLog(); $tmpname = tempnam($this->paths->dataDirectory, 'tmp'); $this->logger->log("tempname $tmpname"); file_put_contents($tmpname, 'test'); DupArchiveEngine::addFileToArchiveUsingBaseDirST($this->paths->archiveFilepath, $this->paths->dataDirectory, $tmpname); echo "$tmpname added"; unlink($tmpname); exit(1); } else if ($this->params->action == 'mini_expand_test') { $this->logger->log("Clearing files"); $this->clearExpandFiles(); $this->logger->log("Cleared files"); try { DupArchiveMiniExpander::init("$this->logger->log"); DupArchiveMiniExpander::expandDirectory($this->paths->archiveFilepath, 'dup-installer', $this->paths->restoreDirectory); } catch (Exception $ex) { $message = $ex->getMessage(); echo "Exception: {$ex} ".$ex->getTraceAsString(); } echo "Mini-extract done.
"; exit(1); } else if ($this->params->action == 'expand_test') { /* @var $daTesterExpandState DaTesterExpandState */ $daTesterExpandState = DaTesterExpandState::getInstance($initializeState); $daTesterState = &$daTesterExpandState; if ($initializeState) { $this->logger->log("Clearing files"); $this->clearExpandFiles(); $this->logger->log("Cleared files"); $daTesterExpandState->archivePath = $this->paths->archiveFilepath; $daTesterExpandState->working = true; $daTesterExpandState->timeSliceInSecs = $this->params->workerTime; $daTesterExpandState->basePath = $this->paths->restoreDirectory; $daTesterExpandState->working = true; $daTesterExpandState->throttleDelayInUs = $this->params->throttleDelayInUs;; $daTesterExpandState->save(); } DupArchiveEngine::expandArchive($daTesterExpandState); $spawnAnotherThread = $daTesterExpandState->working; if (!$spawnAnotherThread) { if (count($daTesterExpandState->failures) > 0) { $this->logger->log('Errors detected'); echo 'Expanson done, but errors detected!'; echo '

'; foreach ($daTesterExpandState->failures as $failure) { $this->logger->log($failure->description); echo $failure->description; echo '

'; } } else { echo 'Expansion done, archive checks out!'; $this->logger->log('Expansion done, archive checks out!'); } } } else if ($this->params->action == 'validate_test') { $validationType = DupArchiveValidationTypes::Full; if ($this->params->p1 != null) { if ($this->params->p1 == 's') { $validationType = DupArchiveValidationTypes::Standard; } } /* @var $daTesterExpandState DaTesterExpandState */ $daTesterExpandState = DaTesterExpandState::getInstance($initializeState); $daTesterState = &$daTesterExpandState; if ($initializeState) { $this->logger->log("Clearing files"); $this->clearExpandFiles(); $this->logger->log("Cleared files"); $this->logger->log("Validation Type:" . (($validationType == DupArchiveValidationTypes::Full) ? 'Full' : 'Quick')); $scan = DupArchiveScanUtil::getScan($this->paths->scanFilepath); $daTesterExpandState->archivePath = $this->paths->archiveFilepath; $daTesterExpandState->working = true; $daTesterExpandState->timeSliceInSecs = $this->params->workerTime; $daTesterExpandState->basePath = $this->paths->tempDirectory; $daTesterExpandState->validateOnly = true; $daTesterExpandState->validationType = $validationType; $daTesterExpandState->working = true; $daTesterExpandState->expectedDirectoryCount = count($scan->Dirs); $daTesterExpandState->expectedFileCount = count($scan->Files); $daTesterExpandState->save(); } DupArchiveEngine::expandArchive($daTesterExpandState); $spawnAnotherThread = $daTesterExpandState->working; if (!$spawnAnotherThread) { if (count($daTesterExpandState->failures) > 0) { echo 'Errors detected!'; echo '

'; foreach ($daTesterExpandState->failures as $failure) { echo esc_html($failure->description); echo '

'; } } else { echo 'Archive checks out!'; } } } else if ($this->params->action == 'get_archive_info') { $this->logger->log("get_archive_info()"); $this->logger->clearLog(); $archiveInfo = DupArchiveEngine::getArchiveInfo($this->paths->archiveFilepath); $sizeInArchive = 0; foreach($archiveInfo->fileHeaders as $fileHeader) { $sizeInArchive += $fileHeader->fileSize; } $archiveSize = filesize($this->paths->archiveFilepath); echo "Version: {$archiveInfo->archiveHeader->version}"; echo '
'; echo "IsCompressed: ".DupArchiveUtil::boolToString($archiveInfo->archiveHeader->isCompressed); echo '
'; // echo "Expected Directory Count: {$archiveInfo->archiveHeader->directoryCount}"; // echo '
'; echo "Total file size: {$sizeInArchive} bytes"; echo '
'; echo "Archive size: {$archiveSize} bytes"; echo '
'; $directoryCount = count($archiveInfo->directoryHeaders); echo "Actual Directory Count: {$directoryCount}"; echo '
'; // echo "Expected File Count: {$archiveInfo->archiveHeader->fileCount}"; // echo '
'; $fileCount = count($archiveInfo->fileHeaders); echo "Actual File Count: {$fileCount}"; echo '
'; echo '
'; echo 'DIRECTORIES'; echo '
'; $c = 1; //print_r($archiveInfo); foreach ($archiveInfo->directoryHeaders as $directoryHeader) { /* @var $directoryHeader DupArchiveDirectoryHeader */ echo "{$c}:{$directoryHeader->relativePath} P:{$directoryHeader->permissions}
"; $c++; } echo '
'; echo 'FILES'; echo '
'; $c = 1; //print_r($archiveInfo); foreach ($archiveInfo->fileHeaders as $fileHeader) { /* @var $fileHeader DupArchiveFileHeader */ echo "{$c}:{$fileHeader->relativePath} ({$fileHeader->fileSize} bytes)
"; $c++; } exit(1); } else { echo 'unknown command.'; exit(1); } DupLiteSnapLibIOU::flock($this->lockHandle, LOCK_UN); $this->logger->log("Unlocked file"); session_write_close(); if ($spawnAnotherThread) { $url = "http://$_SERVER[HTTP_HOST]".strtok($_SERVER["REQUEST_URI"], '?'); $data = $this->params->getQueryStringData(); $this->logger->logObject("SPAWNING CUSTOM WORKER AT $url FOR ACTION {$this->params->action}", $data); DupLiteSnapLibNetU::postWithoutWait($url, $data); $this->logger->log('After post without wait'); } else { $this->logger->log("start timestamp {$daTesterState->startTimestamp}"); $deltaTime = time() - $daTesterState->startTimestamp; $this->logger->log("###### Processing ended. Seconds taken:$deltaTime"); $this->logger->logObject("##### FAILURES:", $daTesterState->failures); } } catch (Exception $ex) { $error_message = "Error Encountered:".$ex->getMessage().'
'.$ex->getTraceAsString(); $this->logger->log($error_message); echo $error_message; } } // Returns json // { // status: 0|-1 (success, failure) // data : true|false (for working) || {failure message} // } function get_status() { $error_message = null; $ret_val = new stdClass(); try { $build_state = CompressExtractState::getInstance(); $ret_val->status = 0; $ret_val->data = $build_state; } catch (Exception $ex) { $ret_val->status = -1; $ret_val->data = $error_message; } echo json_encode($ret_val); // JSON_U::customEncode($ret_val); } private function clearCreateFiles() { if (file_exists($this->paths->scanFilepath)) { @unlink($this->paths->scanFilepath); } $handle = DupLiteSnapLibIOU::fopen($this->paths->archiveFilepath, 'w'); DupLiteSnapLibIOU::fclose($handle); //$this->logger->clearLog(); } private function clearExpandFiles() { if (file_exists($this->paths->restoreDirectory)) { DupLiteSnapLibIOU::rrmdir($this->paths->restoreDirectory); } if (file_exists($this->paths->tempDirectory)) { DupLiteSnapLibIOU::rrmdir($this->paths->tempDirectory); } mkdir($this->paths->restoreDirectory); // $this->logger->clearLog(); } // private function fake_crash($worker_string, $next_scan_index, $next_file_offset) // { // $url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; // $data = array('action' => $worker_string, 'next_scan_index' => $next_scan_index, // 'next_file_offset' => $next_file_offset); // // $this->logger->log("spawning new custom worker at $url"); // $this->post_without_wait($url, $data); // // exit(); // } // private function try_crash($source_filepath, $next_file_offset) // { // $should_crash = (self::CRASH_PROBABILITY >= rand(1, 100)); // // $should_crash = false; // // if ($should_crash) { // $this->logger->log("##### Crashing for $source_filepath at $next_file_offset"); // // $this->fake_crash('compress', $next_scan_index, $next_file_offset); // } // } } function generateCallTrace() { $e = new Exception(); $trace = explode("\n", $e->getTraceAsString()); // reverse array to make steps line up chronologically $trace = array_reverse($trace); array_shift($trace); // remove {main} array_pop($trace); // remove call to this method $length = count($trace); $result = array(); for ($i = 0; $i < $length; $i++) { $result[] = ($i + 1).')'.substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering } return "\t".implode("\n\t", $result); } function terminate_missing_variables($errno, $errstr, $errfile, $errline) { echo "
ERROR: $errstr $errfile $errline
"; // if (($errno == E_NOTICE) and ( strstr($errstr, "Undefined variable"))) die("$errstr in $errfile line $errline"); $logfilepath = getenv("TEMP").'/duparchivetester'; $logfilepath = "{$logfilepath}/tester2.log"; $logger = new DaTesterLogging($this->paths->logFilepath); $logger->log("ERROR $errno, $errstr, {$errfile}:{$errline}"); $logger->log(generateCallTrace()); // $this->logger->clearLog(); exit(1); //return false; // Let the PHP error handler handle all the rest } $daTester = new DaTester(); $daTester->processRequest();