summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2008-05-05 14:44:38 +0000
committerChris Wilson <chris+github@qwirx.com>2008-05-05 14:44:38 +0000
commit7eba897f6da8b1a993f0d40251af1748b5c793ea (patch)
treef1d09e475ba58ba38a8cf85424c45afb9578f6dc
parent55c0054c6aeab12365ec30cd448a919f2ba19bd4 (diff)
Add restore -f option to force restore to continue after an error.
-rw-r--r--bin/bbackupquery/BackupQueries.cpp18
-rw-r--r--bin/bbackupquery/documentation.txt3
-rw-r--r--lib/backupclient/BackupClientRestore.cpp152
-rw-r--r--lib/backupclient/BackupClientRestore.h19
4 files changed, 162 insertions, 30 deletions
diff --git a/bin/bbackupquery/BackupQueries.cpp b/bin/bbackupquery/BackupQueries.cpp
index 61b7e85b..7a7eb5cc 100644
--- a/bin/bbackupquery/BackupQueries.cpp
+++ b/bin/bbackupquery/BackupQueries.cpp
@@ -217,7 +217,7 @@ void BackupQueries::DoCommand(const char *Command, bool isFromCommandLine)
{ "getobject", "" },
{ "get", "i" },
{ "compare", "alcqAEQ" },
- { "restore", "dri" },
+ { "restore", "drif" },
{ "help", "" },
{ "usage", "" },
{ "undelete", "" },
@@ -1966,7 +1966,7 @@ void BackupQueries::CommandRestore(const std::vector<std::string> &args, const b
// Check arguments
if(args.size() != 2)
{
- BOX_ERROR("Incorrect usage. restore [-d] [-r] [-i] <remote-name> <local-name>");
+ BOX_ERROR("Incorrect usage. restore [-drif] <remote-name> <local-name>");
return;
}
@@ -2029,7 +2029,8 @@ void BackupQueries::CommandRestore(const std::vector<std::string> &args, const b
localName.c_str(),
true /* print progress dots */, restoreDeleted,
false /* don't undelete after restore! */,
- opts['r'] /* resume? */);
+ opts['r'] /* resume? */,
+ opts['f'] /* force continue after errors */);
}
catch(std::exception &e)
{
@@ -2050,13 +2051,20 @@ void BackupQueries::CommandRestore(const std::vector<std::string> &args, const b
BOX_INFO("Restore complete.");
break;
+ case Restore_CompleteWithErrors:
+ BOX_WARNING("Restore complete, but some files could not be "
+ "restored.");
+ break;
+
case Restore_ResumePossible:
- BOX_ERROR("Resume possible -- repeat command with -r flag to resume");
+ BOX_ERROR("Resume possible -- repeat command with -r flag "
+ "to resume.");
SetReturnCode(COMMAND_RETURN_ERROR);
break;
case Restore_TargetExists:
- BOX_ERROR("The target directory exists. You cannot restore over an existing directory.");
+ BOX_ERROR("The target directory exists. You cannot restore "
+ "over an existing directory.");
SetReturnCode(COMMAND_RETURN_ERROR);
break;
diff --git a/bin/bbackupquery/documentation.txt b/bin/bbackupquery/documentation.txt
index 42217edc..84126bee 100644
--- a/bin/bbackupquery/documentation.txt
+++ b/bin/bbackupquery/documentation.txt
@@ -116,7 +116,7 @@ compare <store-dir-name> <local-dir-name>
This can be used for automated tests.
<
-> restore [-d] [-r] [-i] <directory-name> <local-directory-name>
+> restore [-drif] <directory-name> <local-directory-name>
Restores a directory to the local disc. The local directory specified
must not exist (unless a previous restore is being restarted).
@@ -126,6 +126,7 @@ compare <store-dir-name> <local-dir-name>
-d -- restore a deleted directory or deleted files inside
-r -- resume an interrupted restoration
-i -- directory name is actually an ID
+ -f -- force restore to continue if errors are encountered
If a restore operation is interrupted for any reason, it can be restarted
using the -r switch. Restore progress information is saved in a file at
diff --git a/lib/backupclient/BackupClientRestore.cpp b/lib/backupclient/BackupClientRestore.cpp
index 336952be..605fe30a 100644
--- a/lib/backupclient/BackupClientRestore.cpp
+++ b/lib/backupclient/BackupClientRestore.cpp
@@ -193,6 +193,8 @@ typedef struct
{
bool PrintDots;
bool RestoreDeleted;
+ bool ContinueAfterErrors;
+ bool ContinuedAfterError;
std::string mRestoreResumeInfoFilename;
RestoreResumeInfo mResumeInfo;
} RestoreParams;
@@ -387,7 +389,15 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
{
BOX_LOG_SYS_ERROR("Failed to create directory '" <<
rLocalDirectoryName << "'");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
// Save the restore info, in case it's needed later
@@ -400,14 +410,30 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
BOX_ERROR("Failed to save resume info file '" <<
Params.mRestoreResumeInfoFilename << "': " <<
e.what());
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
BOX_ERROR("Failed to save resume info file '" <<
Params.mRestoreResumeInfoFilename <<
"': unknown error");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
// Fetch the directory listing from the server -- getting a
@@ -435,13 +461,29 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
{
BOX_ERROR("Failed to restore attributes for '" <<
rLocalDirectoryName << "': " << e.what());
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
BOX_ERROR("Failed to restore attributes for '" <<
rLocalDirectoryName << "': unknown error");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
int64_t bytesWrittenSinceLastRestoreInfoSave = 0;
@@ -473,7 +515,15 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
BOX_LOG_SYS_ERROR("Failed to delete "
"file '" << localFilename <<
"'");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
// Request it from the store
@@ -507,14 +557,30 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
BOX_ERROR("Failed to restore file '" <<
localFilename << "': " <<
e.what());
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
BOX_ERROR("Failed to restore file '" <<
localFilename <<
"': unknown error");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
// Progress display?
@@ -545,7 +611,15 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
"whether file exists: '" <<
localFilename << "': " <<
e.what());
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
@@ -553,7 +627,15 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
"whether file exists: '" <<
localFilename << "': "
"unknown error");
- return Restore_UnknownError;
+
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
if(exists)
@@ -606,14 +688,28 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
BOX_ERROR("Failed to save resume info file '" <<
Params.mRestoreResumeInfoFilename << "': " <<
e.what());
- return Restore_UnknownError;
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
BOX_ERROR("Failed to save resume info file '" <<
Params.mRestoreResumeInfoFilename <<
"': unknown error");
- return Restore_UnknownError;
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
bytesWrittenSinceLastRestoreInfoSave = 0;
@@ -670,13 +766,27 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
{
BOX_ERROR("Failed to restore attributes for '" <<
rLocalDirectoryName << "': " << e.what());
- return Restore_UnknownError;
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
catch(...)
{
BOX_ERROR("Failed to restore attributes for '" <<
rLocalDirectoryName << "': unknown error");
- return Restore_UnknownError;
+ if (Params.ContinueAfterErrors)
+ {
+ Params.ContinuedAfterError = true;
+ }
+ else
+ {
+ return Restore_UnknownError;
+ }
}
return Restore_Complete;
@@ -687,7 +797,7 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
//
// Function
// Name: BackupClientRestore(BackupProtocolClient &, int64_t,
-// const char *, bool, bool)
+// const char *, bool, bool, bool, bool, bool)
// Purpose: Restore a directory on the server to a local
// directory on the disc. The local directory must not
// already exist.
@@ -707,19 +817,24 @@ static int BackupClientRestoreDir(BackupProtocolClient &rConnection,
// (Won't attempt to overwrite things.)
//
// Returns Restore_Complete on success. (Exceptions
-// on error.)
+// on error, unless ContinueAfterError is true and
+// the error is recoverable, in which case it returns
+// Restore_CompleteWithErrors)
// Created: 23/11/03
//
// --------------------------------------------------------------------------
int BackupClientRestore(BackupProtocolClient &rConnection,
int64_t DirectoryID, const char *LocalDirectoryName,
bool PrintDots, bool RestoreDeleted,
- bool UndeleteAfterRestoreDeleted, bool Resume)
+ bool UndeleteAfterRestoreDeleted, bool Resume,
+ bool ContinueAfterErrors)
{
// Parameter block
RestoreParams params;
params.PrintDots = PrintDots;
params.RestoreDeleted = RestoreDeleted;
+ params.ContinueAfterErrors = ContinueAfterErrors;
+ params.ContinuedAfterError = false;
params.mRestoreResumeInfoFilename = LocalDirectoryName;
params.mRestoreResumeInfoFilename += ".boxbackupresume";
@@ -782,6 +897,7 @@ int BackupClientRestore(BackupProtocolClient &rConnection,
// Delete the resume information file
::unlink(params.mRestoreResumeInfoFilename.c_str());
- return Restore_Complete;
+ return params.ContinuedAfterError ? Restore_CompleteWithErrors
+ : Restore_Complete;
}
diff --git a/lib/backupclient/BackupClientRestore.h b/lib/backupclient/BackupClientRestore.h
index f7724030..7e492238 100644
--- a/lib/backupclient/BackupClientRestore.h
+++ b/lib/backupclient/BackupClientRestore.h
@@ -15,14 +15,21 @@ class BackupProtocolClient;
enum
{
Restore_Complete = 0,
- Restore_ResumePossible = 1,
- Restore_TargetExists = 2,
- Restore_TargetPathNotFound = 3,
- Restore_UnknownError = 4,
+ Restore_ResumePossible,
+ Restore_TargetExists,
+ Restore_TargetPathNotFound,
+ Restore_UnknownError,
+ Restore_CompleteWithErrors,
};
-int BackupClientRestore(BackupProtocolClient &rConnection, int64_t DirectoryID, const char *LocalDirectoryName,
- bool PrintDots = false, bool RestoreDeleted = false, bool UndeleteAfterRestoreDeleted = false, bool Resume = false);
+int BackupClientRestore(BackupProtocolClient &rConnection,
+ int64_t DirectoryID,
+ const char *LocalDirectoryName,
+ bool PrintDots = false,
+ bool RestoreDeleted = false,
+ bool UndeleteAfterRestoreDeleted = false,
+ bool Resume = false,
+ bool ContinueAfterErrors = false);
#endif // BACKUPSCLIENTRESTORE__H