diff options
-rw-r--r-- | lib/backupstore/BackupCommands.cpp | 161 | ||||
-rw-r--r-- | lib/backupstore/BackupProtocol.h | 2 | ||||
-rwxr-xr-x | lib/server/makeprotocol.pl.in | 51 | ||||
-rw-r--r-- | test/basicserver/TestCommands.cpp | 5 |
4 files changed, 108 insertions, 111 deletions
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<BackupProtocolMessage> 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<BackupProtocolMessage> BackupProtocolListDirectory::DoCommand(Back // Store the listing to a stream std::auto_ptr<CollectInBufferStream> 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<BackupProtocolMessage> 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<BackupProtocolMessage>(new BackupProtocolSuccess(id)); @@ -507,25 +524,9 @@ std::auto_ptr<BackupProtocolMessage> 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<BackupProtocolMessage> 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<BackupProtocolMessage>(new BackupProtocolSuccess(mObjectID)); @@ -746,27 +735,9 @@ std::auto_ptr<BackupProtocolMessage> 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<BackupProtocolMessage>(new BackupProtocolSuccess(mObjectID)); diff --git a/lib/backupstore/BackupProtocol.h b/lib/backupstore/BackupProtocol.h index 0e0988f7..d9070c73 100644 --- a/lib/backupstore/BackupProtocol.h +++ b/lib/backupstore/BackupProtocol.h @@ -19,7 +19,7 @@ // Class // Name: BackupProtocolLocal2 // Purpose: BackupProtocolLocal with a few more IQ points -// Created: 2003/08/21 +// Created: 2014/09/20 // // -------------------------------------------------------------------------- class BackupProtocolLocal2 : public BackupProtocolLocal diff --git a/lib/server/makeprotocol.pl.in b/lib/server/makeprotocol.pl.in index 65d1f3a9..d61a14d0 100755 --- a/lib/server/makeprotocol.pl.in +++ b/lib/server/makeprotocol.pl.in @@ -604,10 +604,11 @@ public: virtual int GetTimeout() = 0; void SendStreamAfterCommand(std::auto_ptr<IOStream> apStream); - + protected: std::list<IOStream*> mStreamsToSend; void DeleteStreamsToSend(); + virtual std::auto_ptr<$message_base_class> HandleException(BoxException& e) const; private: $replyable_base_class(const $replyable_base_class &rToCopy); /* do not call */ @@ -1077,24 +1078,31 @@ void $server_or_client_class\::DoServer($context_class &rContext) // Run the command try { - if(pobj->HasStreamWithCommand()) + try { - std::auto_ptr<IOStream> apDataStream = ReceiveStream(); - SelfFlushingStream autoflush(*apDataStream); - preply = pobj->DoCommand(*this, rContext, *apDataStream); + if(pobj->HasStreamWithCommand()) + { + std::auto_ptr<IOStream> apDataStream = ReceiveStream(); + SelfFlushingStream autoflush(*apDataStream); + preply = pobj->DoCommand(*this, rContext, *apDataStream); + } + else + { + preply = pobj->DoCommand(*this, rContext); + } } - else + catch(BoxException &e) { - preply = pobj->DoCommand(*this, rContext); + // First try a the built-in exception handler + preply = HandleException(e); } } - catch (std::exception &e) - { - Send($cmd_classes{$error_message}()); - throw; - } catch (...) { + // Fallback in case the exception isn't a BoxException + // or the exception handler fails as well. This path + // throws the exception upwards, killing the process + // that handles the current client. Send($cmd_classes{$error_message}()); throw; } @@ -1183,19 +1191,32 @@ __E } elsif($writing_local) { + print CPP <<__E; + std::auto_ptr<$message_base_class> apReply; + try + { +__E if($has_stream) { print CPP <<__E; - std::auto_ptr<$message_base_class> apReply = rQuery.DoCommand(*this, - mrContext, *apDataStream); + apReply = rQuery.DoCommand(*this, mrContext, *apDataStream); __E } else { print CPP <<__E; - std::auto_ptr<$message_base_class> apReply = rQuery.DoCommand(*this, mrContext); + apReply = rQuery.DoCommand(*this, mrContext); __E } + + print CPP <<__E; + } + catch(BoxException &e) + { + // First try a the built-in exception handler + apReply = HandleException(e); + } +__E } # Common to both client and local diff --git a/test/basicserver/TestCommands.cpp b/test/basicserver/TestCommands.cpp index 63425f48..bdbdffeb 100644 --- a/test/basicserver/TestCommands.cpp +++ b/test/basicserver/TestCommands.cpp @@ -11,6 +11,11 @@ #include "MemLeakFindOn.h" +std::auto_ptr<TestProtocolMessage> TestProtocolReplyable::HandleException(BoxException& e) const +{ + throw; +} + std::auto_ptr<TestProtocolMessage> TestProtocolHello::DoCommand(TestProtocolReplyable &rProtocol, TestContext &rContext) const { if(mNumber32 != 41 || mNumber16 != 87 || mNumber8 != 11 || mText != "pingu") |