From e8efeb785c158581be729aa1dee122f50789ac86 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Oct 2014 22:09:42 +0000 Subject: Refactor handling of exceptions in protocol server command executors. Add a standard method to Replyable that will be called if a recoverable exception (a BoxException) occurs, and can return a protocol Message to be sent to the client, such as an error code for various standard errors, or rethrow the exception. If you want something different, catch exceptions and return the desired reply yourself, or you'll get the default handling. --- lib/backupstore/BackupCommands.cpp | 161 +++++++++++++++---------------------- 1 file changed, 66 insertions(+), 95 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index c32987fe..ab0dc4b8 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -52,11 +52,58 @@ return PROTOCOL_ERROR(Err_SessionReadOnly); \ } + // -------------------------------------------------------------------------- // // Function -// Name: BackupProtocolVersion::DoCommand(Protocol &, BackupStoreContext &) -// Purpose: Return the current version, or an error if the requested version isn't allowed +// Name: BackupProtocolMessage::HandleException(BoxException& e) +// Purpose: Return an error message appropriate to the passed-in +// exception, or rethrow it. +// Created: 2014/09/14 +// +// -------------------------------------------------------------------------- +std::auto_ptr BackupProtocolReplyable::HandleException(BoxException& e) const +{ + if(e.GetType() == RaidFileException::ExceptionType && + e.GetSubType() == RaidFileException::RaidFileDoesntExist) + { + return PROTOCOL_ERROR(Err_DoesNotExist); + } + else if (e.GetType() == BackupStoreException::ExceptionType) + { + if(e.GetSubType() == BackupStoreException::AddedFileDoesNotVerify) + { + return PROTOCOL_ERROR(Err_FileDoesNotVerify); + } + else if(e.GetSubType() == BackupStoreException::AddedFileExceedsStorageLimit) + { + return PROTOCOL_ERROR(Err_StorageLimitExceeded); + } + else if(e.GetSubType() == BackupStoreException::MultiplyReferencedObject) + { + return PROTOCOL_ERROR(Err_MultiplyReferencedObject); + } + else if(e.GetSubType() == BackupStoreException::CouldNotFindEntryInDirectory) + { + return PROTOCOL_ERROR(Err_DoesNotExist); + } + else if(e.GetSubType() == BackupStoreException::NameAlreadyExistsInDirectory) + { + return PROTOCOL_ERROR(Err_TargetNameExists); + } + } + + throw; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: BackupProtocolVersion::DoCommand(Protocol &, +// BackupStoreContext &) +// Purpose: Return the current version, or an error if the +// requested version isn't allowed // Created: 2003/08/20 // // -------------------------------------------------------------------------- @@ -192,23 +239,12 @@ std::auto_ptr BackupProtocolListDirectory::DoCommand(Back // Store the listing to a stream std::auto_ptr stream(new CollectInBufferStream); - try - { - // Ask the context for a directory - const BackupStoreDirectory &rdir( - rContext.GetDirectory(mObjectID)); - rdir.WriteToStream(*stream, mFlagsMustBeSet, - mFlagsNotToBeSet, mSendAttributes, - false /* never send dependency info to the client */); - } - catch(RaidFileException &e) - { - if (e.GetSubType() == RaidFileException::RaidFileDoesntExist) - { - return PROTOCOL_ERROR(Err_DoesNotExist); - } - throw; - } + // Ask the context for a directory + const BackupStoreDirectory &rdir( + rContext.GetDirectory(mObjectID)); + rdir.WriteToStream(*stream, mFlagsMustBeSet, + mFlagsNotToBeSet, mSendAttributes, + false /* never send dependency info to the client */); stream->SetForReading(); @@ -252,29 +288,10 @@ std::auto_ptr BackupProtocolStoreFile::DoCommand( } // Ask the context to store it - int64_t id = 0; - try - { - id = rContext.AddFile(rDataStream, mDirectoryObjectID, - mModificationTime, mAttributesHash, mDiffFromFileID, - mFilename, - true /* mark files with same name as old versions */); - } - catch(BackupStoreException &e) - { - if(e.GetSubType() == BackupStoreException::AddedFileDoesNotVerify) - { - return PROTOCOL_ERROR(Err_FileDoesNotVerify); - } - else if(e.GetSubType() == BackupStoreException::AddedFileExceedsStorageLimit) - { - return PROTOCOL_ERROR(Err_StorageLimitExceeded); - } - else - { - throw; - } - } + int64_t id = rContext.AddFile(rDataStream, mDirectoryObjectID, + mModificationTime, mAttributesHash, mDiffFromFileID, + mFilename, + true /* mark files with same name as old versions */); // Tell the caller what the file ID was return std::auto_ptr(new BackupProtocolSuccess(id)); @@ -507,25 +524,9 @@ std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( } bool alreadyExists = false; - int64_t id; - - try - { - id = rContext.AddDirectory(mContainingDirectoryID, - mDirectoryName, attr, mAttributesModTime, mModificationTime, - alreadyExists); - } - catch(BackupStoreException &e) - { - if(e.GetSubType() == BackupStoreException::AddedFileExceedsStorageLimit) - { - return PROTOCOL_ERROR(Err_StorageLimitExceeded); - } - else - { - throw; - } - } + int64_t id = rContext.AddDirectory(mContainingDirectoryID, + mDirectoryName, attr, mAttributesModTime, mModificationTime, + alreadyExists); if(alreadyExists) { @@ -666,19 +667,7 @@ std::auto_ptr BackupProtocolDeleteDirectory::DoCommand(Ba } // Context handles this - try - { - rContext.DeleteDirectory(mObjectID); - } - catch(BackupStoreException &e) - { - if(e.GetSubType() == BackupStoreException::MultiplyReferencedObject) - { - return PROTOCOL_ERROR(Err_MultiplyReferencedObject); - } - - throw; - } + rContext.DeleteDirectory(mObjectID); // return the object ID return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); @@ -746,27 +735,9 @@ std::auto_ptr BackupProtocolMoveObject::DoCommand(BackupP CHECK_WRITEABLE_SESSION // Let context do this, but modify error reporting on exceptions... - try - { - rContext.MoveObject(mObjectID, mMoveFromDirectory, mMoveToDirectory, - mNewFilename, (mFlags & Flags_MoveAllWithSameName) == Flags_MoveAllWithSameName, - (mFlags & Flags_AllowMoveOverDeletedObject) == Flags_AllowMoveOverDeletedObject); - } - catch(BackupStoreException &e) - { - if(e.GetSubType() == BackupStoreException::CouldNotFindEntryInDirectory) - { - return PROTOCOL_ERROR(Err_DoesNotExist); - } - else if(e.GetSubType() == BackupStoreException::NameAlreadyExistsInDirectory) - { - return PROTOCOL_ERROR(Err_TargetNameExists); - } - else - { - throw; - } - } + rContext.MoveObject(mObjectID, mMoveFromDirectory, mMoveToDirectory, + mNewFilename, (mFlags & Flags_MoveAllWithSameName) == Flags_MoveAllWithSameName, + (mFlags & Flags_AllowMoveOverDeletedObject) == Flags_AllowMoveOverDeletedObject); // Return the object ID return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); -- cgit v1.2.3