binDir = IsWindows() ? $MG_BIN_DIR_WINDOWS : $MG_BIN_DIR_LINUX; if (!$this->ParseArguments($arguments)) { $this->DisplayUsage(); exit(); } } private function ParseArguments($arguments) { include 'RepositoryAdminConstants.inc'; $size = count($arguments); if ($size < $MG_MIN_ARGS || $size > $MG_MAX_ARGS) { return FALSE; } for ($i = 2; $i < $size; $i += 2) { $argName = trim($arguments[$i-1]); $argValue = trim($arguments[$i]); switch ($argName) { case $MG_ARGN_COMMAND: $this->command = $argValue; break; case $MG_ARGN_INCREMENTAL_LEVEL: $this->incrementalLevel = $argValue; break; case $MG_ARGN_INPUT_PATH: $this->inputPath = $argValue; break; case $MG_ARGN_OUTPUT_PATH: $this->outputRoot = $argValue; break; default: return FALSE; } } return TRUE; } public function DisplayUsage() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; $usage = $IDS_PROGRAM_SYNTAX.$IDS_PROGRAM_OPTIONS.$IDS_EXAMPLE_BACK_UP_OFFLINE_REPOSITORIES.$IDS_EXAMPLE_BACK_UP_ONLINE_REPOSITORIES.$IDS_EXAMPLE_RESTORE_COLD_BACKUP_REPOSITORIES.$IDS_EXAMPLE_RESTORE_HOT_BACKUP_REPOSITORIES; if (IsWindows()) { $usage = str_replace($MG_ARGV_PHP_LINUX, $MG_ARGV_PHP_WINDOWS, $usage); } echo $usage; } protected function GetCurrentTimestamp() { include 'RepositoryAdminConstants.inc'; $currTimestamp = date($MG_FORMAT_TIMESTAMP); if (empty($currTimestamp)) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_DATE_TIME); } return $currTimestamp; } protected function & GetDatabaseFiles($homeDir) { $program = $this->binDir.'db_archive -sv -h "'.$homeDir.'"'; try { $output =& ExecuteProgram($program); } catch (Exception $e) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_UNABLE_TO_RETRIEVE_DATABASE_FILES); } return $output; } protected function & GetLogFiles($homeDir, $includeUnusedFilesOnly = FALSE) { if ($includeUnusedFilesOnly) { $program = $this->binDir.'db_archive -v -h "'.$homeDir.'"'; } else // all log files { $program = $this->binDir.'db_archive -lv -h "'.$homeDir.'"'; } try { $output =& ExecuteProgram($program); } catch (Exception $e) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_UNABLE_TO_RETRIEVE_LOG_FILES); } return $output; } private function TransferFile($fileName, $moveFile = FALSE) { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; $srcFile = $this->inputPath.$fileName; $dstFile = $this->outputPath.$fileName; if ($MG_ARGV_BACKUP == $this->command) { echo sprintf($IDS_PROGRESS_ARCHIVING_FILE, $fileName); } else if ($MG_ARGV_RESTORE == $this->command) { echo sprintf($IDS_PROGRESS_RECOVERING_FILE, $fileName); } else { throw new Exception($IDS_ERR_INVALID_OPERATION); } if ($moveFile) { MoveFile($srcFile, $dstFile); } else { CopyFile($srcFile, $dstFile); } } private function TransferFiles($fileNames, $index = 0, $moveFile = FALSE) { $size = count($fileNames); if (($size - $index) <= 0) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_DATABASE_OR_LOG_FILE_NOT_FOUND); } for ($i = $index; $i < $size; ++$i) { $this->TransferFile($fileNames[$i], $moveFile); } } protected function PerformCheckpoint($homeDir) { // TODO: db_checkpoint does not work as expected. /* $program = $this->binDir.'db_checkpoint -1v -h "'.$homeDir.'"'; try { $output =& ExecuteProgram($program); } catch (Exception $e) { // Checkpoint may harmlessly fail if no environment file exists. // include 'RepositoryAdminResources.inc'; // throw new Exception($IDS_ERR_UNABLE_TO_PERFORM_CHECKPOINT); } */ } protected function TransferDatabaseFiles() { $databaseFiles = $this->GetDatabaseFiles($this->inputPath); $this->TransferFiles($databaseFiles); } protected function TransferLogFiles() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; if ($MG_ARGV_BACKUP == $this->command) { $unusedFiles = $this->GetLogFiles($this->inputPath, TRUE); $logFiles = $this->GetLogFiles($this->inputPath, FALSE); $numUnusedFiles = count($unusedFiles); if ($MG_MIN_INCREMENTAL_LEVEL != $this->incrementalLevel && $numUnusedFiles > 0) { $this->TransferFiles($unusedFiles, 0, TRUE); } } else if ($MG_ARGV_RESTORE == $this->command) { $logFiles = $this->GetLogFiles($this->inputPath, FALSE); $numUnusedFiles = 0; } else { throw new Exception($IDS_ERR_INVALID_OPERATION); } $this->TransferFiles($logFiles, $numUnusedFiles, FALSE); } protected function CleanUpLogFiles($homeDir) { $program = $this->binDir.'db_archive -dv -h "'.$homeDir.'"'; try { $output =& ExecuteProgram($program); } catch (Exception $e) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_UNABLE_TO_CLEAN_UP_LOG_FILES); } } protected function PerformRecovery($homeDir) { $program = $this->binDir.'db_recover -cv -h "'.$homeDir.'"'; try { $output =& ExecuteProgram($program); } catch (Exception $e) { include 'RepositoryAdminResources.inc'; throw new Exception($IDS_ERR_UNABLE_TO_PERFORM_RECOVERY); } } protected function BackupOfflineRepositories() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; echo $IDS_PROGRESS_BACKING_UP_OFFLINE_REPOSITORY; $this->outputPath = $this->outputRoot.$MG_COLD_BACKUP_DIR_NAME; AppendSlashToEndOfPath($this->outputPath); if (is_dir($this->outputPath)) { $modTimestamp = date($MG_FORMAT_TIMESTAMP, filemtime($this->outputPath)); $lastBackupDir = $this->outputRoot.$MG_PREFIX_COLD_BACKUP.$modTimestamp; AppendSlashToEndOfPath($lastBackupDir); RenameDirectory($this->outputPath, $lastBackupDir); } CreateDirectory($this->outputPath); $this->PerformCheckpoint($this->inputPath); $this->TransferDatabaseFiles(); $this->TransferLogFiles(); } protected function BackupOnlineRepositories() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; echo $IDS_PROGRESS_BACKING_UP_ONLINE_REPOSITORY; $this->outputPath = $this->outputRoot.$MG_HOT_BACKUP_DIR_NAME; AppendSlashToEndOfPath($this->outputPath); $fullSnapShot = TRUE; if (is_dir($this->outputPath)) { $databaseFiles = $this->GetDatabaseFiles($this->outputPath); $logFiles = $this->GetLogFiles($this->outputPath, FALSE); $numDatabaseFiles = count($databaseFiles); $numLogFiles = count($logFiles); if (($numDatabaseFiles == 0 && $numLogFiles != 0) || ($numDatabaseFiles != 0 && $numLogFiles == 0)) { $badBackupDir = $this->outputRoot.$MG_PREFIX_BAD_BACKUP.$this->GetCurrentTimestamp(); AppendSlashToEndOfPath($badBackupDir); RenameDirectory($this->outputPath, $badBackupDir); } else { $unusedFiles = $this->GetLogFiles($this->outputPath, TRUE); $numUnusedFiles = count($unusedFiles); $numActiveFiles = $numLogFiles - $numUnusedFiles; if ($numActiveFiles > $this->incrementalLevel) { $modTimestamp = date($MG_FORMAT_TIMESTAMP, filemtime($this->outputPath)); $lastBackupDir = $this->outputRoot.$MG_PREFIX_HOT_BACKUP.$modTimestamp; AppendSlashToEndOfPath($lastBackupDir); RenameDirectory($this->outputPath, $lastBackupDir); } else { $fullSnapShot = FALSE; } } } if ($fullSnapShot) { CreateDirectory($this->outputPath); $this->TransferDatabaseFiles(); } $this->TransferLogFiles(); } protected function RestoreRepositories() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; echo $IDS_PROGRESS_RESTORING_BACKUP_REPOSITORY; $this->outputPath = $this->outputRoot; if (!IsDirectoryEmpty($this->outputPath, TRUE, FALSE)) { $tempBackupDir = $this->outputRoot.$MG_PREFIX_TEMP_BACKUP.$this->GetCurrentTimestamp(); AppendSlashToEndOfPath($tempBackupDir); CreateDirectory($tempBackupDir); MoveFiles($this->outputPath, $tempBackupDir); } $this->TransferDatabaseFiles(); $this->TransferLogFiles(); $this->PerformRecovery($this->outputPath); $this->CleanUpLogFiles($this->outputPath); } public function Run() { include 'RepositoryAdminConstants.inc'; include 'RepositoryAdminResources.inc'; CheckDirectory($this->inputPath); CheckDirectory($this->outputRoot); AppendSlashToEndOfPath($this->inputPath); AppendSlashToEndOfPath($this->outputRoot); try { switch ($this->command) { case $MG_ARGV_BACKUP: if ($MG_MIN_INCREMENTAL_LEVEL == $this->incrementalLevel) { $this->BackupOfflineRepositories(); } else if ($this->incrementalLevel > $MG_MIN_INCREMENTAL_LEVEL && $this->incrementalLevel <= $MG_MAX_INCREMENTAL_LEVEL) { $this->BackupOnlineRepositories(); } else { throw new Exception(sprintf($IDS_ERR_ARGUMENT_OUT_OF_RANGE, $this->incrementalLevel)); } break; case $MG_ARGV_RESTORE: $this->RestoreRepositories(); break; default: throw new Exception(sprintf($IDS_ERR_INVALID_ARGUMENT, $this->command)); } } catch (Exception $e) { if ($this->outputPath != $this->outputRoot && is_dir($this->outputPath)) { DeleteDirectory($this->outputPath); } throw $e; } } } ?>