From 08c9524181c53855e7d86df391388cab2c2b9ef0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Feb 2014 20:22:51 +0000 Subject: Rename BackupStoreContext.GetStoreRoot() to GetAccountRoot(). More accurate name for this variable. --- lib/backupstore/BackupCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 318ce55a..8f113a41 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -388,7 +388,7 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt // Choose a temporary filename for the result of the combination std::ostringstream fs; - fs << rContext.GetStoreRoot() << ".recombinetemp." << p; + fs << rContext.GetAccountRoot() << ".recombinetemp." << p; std::string tempFn = RaidFileController::DiscSetPathToFileSystemPath( rContext.GetStoreDiscSet(), fs.str(), -- cgit v1.2.3 From be018ca83afdc71a44c3a33b45d1bba5e611ec69 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Feb 2014 21:15:27 +0000 Subject: Don't need to protect InvisibleTempFileStream against exceptions. By definition, it will be cleared up by the OS automatically. Also we don't need to support gcc 2.x any more. It was replaced by gcc3 in 2001, 12 years ago. --- lib/backupstore/BackupCommands.cpp | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 8f113a41..fb1d1e45 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -395,26 +395,10 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt p + 16); // Open the temporary file - std::auto_ptr combined; - try - { - { - // Write nastily to allow this to work with gcc 2.x - std::auto_ptr t( - new InvisibleTempFileStream( - tempFn.c_str(), - O_RDWR | O_CREAT | - O_EXCL | O_BINARY | - O_TRUNC)); - combined = t; - } - } - catch(...) - { - // Make sure it goes - ::unlink(tempFn.c_str()); - throw; - } + std::auto_ptr combined( + new InvisibleTempFileStream( + tempFn, O_RDWR | O_CREAT | O_EXCL | + O_BINARY | O_TRUNC)); // Do the combining BackupStoreFile::CombineFile(*diff, *diff2, *from, *combined); -- cgit v1.2.3 From d5e7ceb505ba693781904d3197f034e8ef896538 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Feb 2014 21:54:28 +0000 Subject: Move the comment to somewhere more useful. --- lib/backupstore/BackupCommands.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index fb1d1e45..d2326869 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -164,6 +164,8 @@ std::auto_ptr BackupProtocolLogin::DoCommand(BackupProtoc // -------------------------------------------------------------------------- std::auto_ptr BackupProtocolFinished::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const { + // can be called in any phase + BOX_NOTICE("Session finished for Client ID " << BOX_FORMAT_ACCOUNT(rContext.GetClientID()) << " " "(name=" << rContext.GetAccountName() << ")"); @@ -171,7 +173,6 @@ std::auto_ptr BackupProtocolFinished::DoCommand(BackupPro // Let the context know about it rContext.ReceivedFinishCommand(); - // can be called in any phase return std::auto_ptr(new BackupProtocolFinished); } -- cgit v1.2.3 From eb8f880803ee6577263d53c75442b55fe399a8a6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Feb 2014 22:06:23 +0000 Subject: Add an AccountUsage2 command to backup protocol. Allows us to get information about the account that's not available using the old AccountUsage command. Currently only used in tests. --- lib/backupstore/BackupCommands.cpp | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index d2326869..471ed56a 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -953,3 +953,49 @@ std::auto_ptr BackupProtocolGetIsAlive::DoCommand(BackupP // return std::auto_ptr(new BackupProtocolIsAlive()); } + +// -------------------------------------------------------------------------- +// +// Function +// Name: BackupProtocolGetAccountUsage2::DoCommand(BackupProtocolReplyable &, BackupStoreContext &) +// Purpose: Return the amount of disc space used +// Created: 26/12/13 +// +// -------------------------------------------------------------------------- +std::auto_ptr BackupProtocolGetAccountUsage2::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +{ + CHECK_PHASE(Phase_Commands) + + // Get store info from context + const BackupStoreInfo &info(rContext.GetBackupStoreInfo()); + + // Find block size + RaidFileController &rcontroller(RaidFileController::GetController()); + RaidFileDiscSet &rdiscSet(rcontroller.GetDiscSet(info.GetDiscSetNumber())); + + // Return info + BackupProtocolAccountUsage2* usage = new BackupProtocolAccountUsage2(); + std::auto_ptr reply(usage); + #define COPY(name) usage->Set ## name (info.Get ## name ()) + COPY(AccountName); + usage->SetAccountEnabled(info.IsAccountEnabled()); + COPY(ClientStoreMarker); + usage->SetBlockSize(rdiscSet.GetBlockSize()); + COPY(LastObjectIDUsed); + COPY(BlocksUsed); + COPY(BlocksInCurrentFiles); + COPY(BlocksInOldFiles); + COPY(BlocksInDeletedFiles); + COPY(BlocksInDirectories); + COPY(BlocksSoftLimit); + COPY(BlocksHardLimit); + COPY(NumCurrentFiles); + COPY(NumOldFiles); + COPY(NumDeletedFiles); + COPY(NumDirectories); + #undef COPY + + return reply; +} + -- cgit v1.2.3 From b8d2733b33c1dd2491c60fe9f68f612e6de503e4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Feb 2014 22:28:45 +0000 Subject: Fix compile error. Caused by premature switch from GetNumFiles to GetNumCurrentFiles. --- lib/backupstore/BackupCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 471ed56a..43f7c4a2 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -990,7 +990,7 @@ std::auto_ptr BackupProtocolGetAccountUsage2::DoCommand( COPY(BlocksInDirectories); COPY(BlocksSoftLimit); COPY(BlocksHardLimit); - COPY(NumCurrentFiles); + usage->SetNumCurrentFiles(info.GetNumFiles()); COPY(NumOldFiles); COPY(NumDeletedFiles); COPY(NumDirectories); -- cgit v1.2.3 From c7d7ad5dd7d158866da84edce1b2adb4a77d517c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 9 Feb 2014 16:39:40 +0000 Subject: Rename BackupStoreInfo variable NumFiles to NumCurrentFiles. Will hopefully prevent future confusion about the meaning of this info variable. --- lib/backupstore/BackupCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 43f7c4a2..471ed56a 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -990,7 +990,7 @@ std::auto_ptr BackupProtocolGetAccountUsage2::DoCommand( COPY(BlocksInDirectories); COPY(BlocksSoftLimit); COPY(BlocksHardLimit); - usage->SetNumCurrentFiles(info.GetNumFiles()); + COPY(NumCurrentFiles); COPY(NumOldFiles); COPY(NumDeletedFiles); COPY(NumDirectories); -- cgit v1.2.3 From e0470bd4b13806d8b4274d1ecaa08514af955074 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 2 Mar 2014 08:58:02 +0000 Subject: Add QueryCreateDirectory2 command. Allows creating a directory with a specified modtime (in the parent directory entry). Tests to come shortly. --- lib/backupstore/BackupCommands.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 471ed56a..468b2253 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -468,7 +468,27 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt // Created: 2003/09/04 // // -------------------------------------------------------------------------- -std::auto_ptr BackupProtocolCreateDirectory::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +std::auto_ptr BackupProtocolCreateDirectory::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +{ + return BackupProtocolCreateDirectory2(mContainingDirectoryID, + mAttributesModTime, 0 /* ModificationTime */, + mDirectoryName).DoCommand(rProtocol, rContext); +} + + + +// -------------------------------------------------------------------------- +// +// Function +// Name: BackupProtocolCreateDirectory2::DoCommand(Protocol &, BackupStoreContext &) +// Purpose: Create directory command, with a specific +// modification time. +// Created: 2014/02/11 +// +// -------------------------------------------------------------------------- +std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION -- cgit v1.2.3 From 3552ccc25938288775d56adf70b8bf0dc8b63563 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 2 Mar 2014 08:58:18 +0000 Subject: Adding a directory when over limit returns an error instead of crashing. Just like adding a file does. --- lib/backupstore/BackupCommands.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 468b2253..a0788f32 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -508,8 +508,26 @@ std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( } bool alreadyExists = false; - int64_t id = rContext.AddDirectory(mContainingDirectoryID, mDirectoryName, attr, mAttributesModTime, alreadyExists); - + 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; + } + } + if(alreadyExists) { return PROTOCOL_ERROR(Err_DirectoryAlreadyExists); -- cgit v1.2.3 From c30a30907d26fb25f449fb3f03274418f935b0a7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 2 Mar 2014 08:59:39 +0000 Subject: Always flush any incoming stream on server side. Otherwise the protocol might be broken and can't be used any more, even if we made an effort to return an Error reply instead of throwing an exception. This used to not be a problem because an Error reply would terminate the connection anyway, but it no longer does. So if the client also didn't terminate, but tried to handle the exception and keep using the connection, then it might find that its next command fails because the protocol is broken. --- lib/backupstore/BackupCommands.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index a0788f32..2d927358 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -227,7 +227,9 @@ std::auto_ptr BackupProtocolListDirectory::DoCommand(Back // Created: 2003/09/02 // // -------------------------------------------------------------------------- -std::auto_ptr BackupProtocolStoreFile::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +std::auto_ptr BackupProtocolStoreFile::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext, + IOStream& rDataStream) const { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION @@ -249,14 +251,11 @@ std::auto_ptr BackupProtocolStoreFile::DoCommand(BackupPr } } - // A stream follows, which contains the file - std::auto_ptr filestream(rProtocol.ReceiveStream()); - // Ask the context to store it int64_t id = 0; try { - id = rContext.AddFile(*filestream, mDirectoryObjectID, + id = rContext.AddFile(rDataStream, mDirectoryObjectID, mModificationTime, mAttributesHash, mDiffFromFileID, mFilename, true /* mark files with same name as old versions */); @@ -469,11 +468,12 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt // // -------------------------------------------------------------------------- std::auto_ptr BackupProtocolCreateDirectory::DoCommand( - BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext, + IOStream& rDataStream) const { return BackupProtocolCreateDirectory2(mContainingDirectoryID, mAttributesModTime, 0 /* ModificationTime */, - mDirectoryName).DoCommand(rProtocol, rContext); + mDirectoryName).DoCommand(rProtocol, rContext, rDataStream); } @@ -488,17 +488,16 @@ std::auto_ptr BackupProtocolCreateDirectory::DoCommand( // // -------------------------------------------------------------------------- std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( - BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext, + IOStream& rDataStream) const { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - // Get the stream containing the attributes - std::auto_ptr attrstream(rProtocol.ReceiveStream()); // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; - attr.Set(*attrstream, rProtocol.GetTimeout()); + attr.Set(rDataStream, rProtocol.GetTimeout()); // Check to see if the hard limit has been exceeded if(rContext.HardLimitExceeded()) @@ -547,17 +546,17 @@ std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( // Created: 2003/09/06 // // -------------------------------------------------------------------------- -std::auto_ptr BackupProtocolChangeDirAttributes::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +std::auto_ptr BackupProtocolChangeDirAttributes::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext, + IOStream& rDataStream) const { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - // Get the stream containing the attributes - std::auto_ptr attrstream(rProtocol.ReceiveStream()); // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; - attr.Set(*attrstream, rProtocol.GetTimeout()); + attr.Set(rDataStream, rProtocol.GetTimeout()); // Get the context to do it's magic rContext.ChangeDirAttributes(mObjectID, attr, mAttributesModTime); @@ -575,17 +574,18 @@ std::auto_ptr BackupProtocolChangeDirAttributes::DoComman // Created: 2003/09/06 // // -------------------------------------------------------------------------- -std::auto_ptr BackupProtocolSetReplacementFileAttributes::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const +std::auto_ptr +BackupProtocolSetReplacementFileAttributes::DoCommand( + BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext, + IOStream& rDataStream) const { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - // Get the stream containing the attributes - std::auto_ptr attrstream(rProtocol.ReceiveStream()); // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; - attr.Set(*attrstream, rProtocol.GetTimeout()); + attr.Set(rDataStream, rProtocol.GetTimeout()); // Get the context to do it's magic int64_t objectID = 0; -- cgit v1.2.3 From e0d11ae476981fd56229b4ccffdd30166361548b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 Apr 2014 22:15:25 +0000 Subject: Remove the global logging level. It's incompatible with having a logger that logs everything, regardless of the global log level. --- lib/backupstore/BackupCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 2d927358..8b485d0c 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -298,7 +298,7 @@ std::auto_ptr BackupProtocolGetObject::DoCommand(BackupPr // Check the object exists if(!rContext.ObjectExists(mObjectID)) { - return std::auto_ptr(new BackupProtocolSuccess(NoObject)); + return PROTOCOL_ERROR(Err_DoesNotExist); } // Open the object -- cgit v1.2.3 From 6d52b312e556356030edd6ec5904faa63f5b9778 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Oct 2014 22:09:34 +0000 Subject: Whitespace, comment and readability fixes --- lib/backupstore/BackupCommands.cpp | 126 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 64 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index 8b485d0c..c32987fe 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -93,7 +93,7 @@ std::auto_ptr BackupProtocolLogin::DoCommand(BackupProtoc // and that the client actually has an account on this machine if(mClientID != rContext.GetClientID()) { - BOX_WARNING("Failed login from client ID " << + BOX_WARNING("Failed login from client ID " << BOX_FORMAT_ACCOUNT(mClientID) << ": " "wrong certificate for this account"); return PROTOCOL_ERROR(Err_BadLogin); @@ -101,7 +101,7 @@ std::auto_ptr BackupProtocolLogin::DoCommand(BackupProtoc if(!rContext.GetClientHasAccount()) { - BOX_WARNING("Failed login from client ID " << + BOX_WARNING("Failed login from client ID " << BOX_FORMAT_ACCOUNT(mClientID) << ": " "no such account on this server"); return PROTOCOL_ERROR(Err_BadLogin); @@ -117,17 +117,17 @@ std::auto_ptr BackupProtocolLogin::DoCommand(BackupProtoc BOX_FORMAT_ACCOUNT(mClientID)); return PROTOCOL_ERROR(Err_CannotLockStoreForWriting); } - + // Debug: check we got the lock ASSERT(!rContext.SessionIsReadOnly()); } - + // Load the store info rContext.LoadStoreInfo(); if(!rContext.GetBackupStoreInfo().IsAccountEnabled()) { - BOX_WARNING("Refused login from disabled client ID " << + BOX_WARNING("Refused login from disabled client ID " << BOX_FORMAT_ACCOUNT(mClientID)); return PROTOCOL_ERROR(Err_DisabledAccount); } @@ -137,9 +137,9 @@ std::auto_ptr BackupProtocolLogin::DoCommand(BackupProtoc // Mark the next phase rContext.SetPhase(BackupStoreContext::Phase_Commands); - + // Log login - BOX_NOTICE("Login from Client ID " << + BOX_NOTICE("Login from Client ID " << BOX_FORMAT_ACCOUNT(mClientID) << " " "(name=" << rContext.GetAccountName() << "): " << (((mFlags & Flags_ReadOnly) != Flags_ReadOnly) @@ -166,7 +166,7 @@ std::auto_ptr BackupProtocolFinished::DoCommand(BackupPro { // can be called in any phase - BOX_NOTICE("Session finished for Client ID " << + BOX_NOTICE("Session finished for Client ID " << BOX_FORMAT_ACCOUNT(rContext.GetClientID()) << " " "(name=" << rContext.GetAccountName() << ")"); @@ -197,11 +197,11 @@ std::auto_ptr BackupProtocolListDirectory::DoCommand(Back // Ask the context for a directory const BackupStoreDirectory &rdir( rContext.GetDirectory(mObjectID)); - rdir.WriteToStream(*stream, mFlagsMustBeSet, + rdir.WriteToStream(*stream, mFlagsMustBeSet, mFlagsNotToBeSet, mSendAttributes, false /* never send dependency info to the client */); } - catch (RaidFileException &e) + catch(RaidFileException &e) { if (e.GetSubType() == RaidFileException::RaidFileDoesntExist) { @@ -211,7 +211,7 @@ std::auto_ptr BackupProtocolListDirectory::DoCommand(Back } stream->SetForReading(); - + // Get the protocol to send the stream rProtocol.SendStreamAfterCommand(static_cast< std::auto_ptr > (stream)); @@ -240,7 +240,7 @@ std::auto_ptr BackupProtocolStoreFile::DoCommand( { return hookResult; } - + // Check that the diff from file actually exists, if it's specified if(mDiffFromFileID != 0) { @@ -250,7 +250,7 @@ std::auto_ptr BackupProtocolStoreFile::DoCommand( return PROTOCOL_ERROR(Err_DiffFromFileDoesNotExist); } } - + // Ask the context to store it int64_t id = 0; try @@ -275,7 +275,7 @@ std::auto_ptr BackupProtocolStoreFile::DoCommand( throw; } } - + // Tell the caller what the file ID was return std::auto_ptr(new BackupProtocolSuccess(id)); } @@ -315,7 +315,7 @@ std::auto_ptr BackupProtocolGetObject::DoCommand(BackupPr // // Function // Name: BackupProtocolGetFile::DoCommand(Protocol &, BackupStoreContext &) -// Purpose: Command to get an file object from the server -- may have to do a bit of +// Purpose: Command to get an file object from the server -- may have to do a bit of // work to get the object. // Created: 2003/09/03 // @@ -357,13 +357,13 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt en = rdir.FindEntryByID(id); if(en == 0) { - BOX_ERROR("Object " << + BOX_ERROR("Object " << BOX_FORMAT_OBJECTID(mObjectID) << - " in dir " << + " in dir " << BOX_FORMAT_OBJECTID(mInDirectory) << " for account " << BOX_FORMAT_ACCOUNT(rContext.GetClientID()) << - " references object " << + " references object " << BOX_FORMAT_OBJECTID(id) << " which does not exist in dir"); return PROTOCOL_ERROR(Err_PatchConsistencyError); @@ -371,73 +371,73 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt id = en->GetDependsNewer(); } while(en != 0 && id != 0); - + // OK! The last entry in the chain is the full file, the others are patches back from it. // Open the last one, which is the current from file std::auto_ptr from(rContext.OpenObject(patchChain[patchChain.size() - 1])); - + // Then, for each patch in the chain, do a combine for(int p = ((int)patchChain.size()) - 2; p >= 0; --p) { // ID of patch int64_t patchID = patchChain[p]; - + // Open it a couple of times std::auto_ptr diff(rContext.OpenObject(patchID)); std::auto_ptr diff2(rContext.OpenObject(patchID)); - + // Choose a temporary filename for the result of the combination std::ostringstream fs; fs << rContext.GetAccountRoot() << ".recombinetemp." << p; - std::string tempFn = + std::string tempFn = RaidFileController::DiscSetPathToFileSystemPath( rContext.GetStoreDiscSet(), fs.str(), p + 16); - + // Open the temporary file std::auto_ptr combined( new InvisibleTempFileStream( tempFn, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_TRUNC)); - + // Do the combining BackupStoreFile::CombineFile(*diff, *diff2, *from, *combined); - + // Move to the beginning of the combined file combined->Seek(0, IOStream::SeekType_Absolute); - + // Then shuffle round for the next go if (from.get()) from->Close(); from = combined; } - + // Now, from contains a nice file to send to the client. Reorder it { // Write nastily to allow this to work with gcc 2.x std::auto_ptr t(BackupStoreFile::ReorderFileToStreamOrder(from.get(), true /* take ownership */)); stream = t; } - + // Release from file to avoid double deletion from.release(); } else { // Simple case: file already exists on disc ready to go - + // Open the object std::auto_ptr object(rContext.OpenObject(mObjectID)); BufferedStream buf(*object); - + // Verify it if(!BackupStoreFile::VerifyEncodedFileFormat(buf)) { return PROTOCOL_ERROR(Err_FileDoesNotVerify); } - + // Reset stream -- seek to beginning object->Seek(0, IOStream::SeekType_Absolute); - + // Reorder the stream/file into stream order { // Write nastily to allow this to work with gcc 2.x @@ -445,15 +445,15 @@ std::auto_ptr BackupProtocolGetFile::DoCommand(BackupProt stream = t; } - // Object will be deleted when the stream is deleted, - // so can release the object auto_ptr here to avoid + // Object will be deleted when the stream is deleted, + // so can release the object auto_ptr here to avoid // premature deletion object.release(); } // Stream the reordered stream to the peer rProtocol.SendStreamAfterCommand(stream); - + // Tell the caller what the file was return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); } @@ -493,12 +493,12 @@ std::auto_ptr BackupProtocolCreateDirectory2::DoCommand( { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - - // Collect the attributes -- do this now so no matter what the outcome, + + // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; attr.Set(rDataStream, rProtocol.GetTimeout()); - + // Check to see if the hard limit has been exceeded if(rContext.HardLimitExceeded()) { @@ -553,7 +553,7 @@ std::auto_ptr BackupProtocolChangeDirAttributes::DoComman CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - // Collect the attributes -- do this now so no matter what the outcome, + // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; attr.Set(rDataStream, rProtocol.GetTimeout()); @@ -582,7 +582,7 @@ BackupProtocolSetReplacementFileAttributes::DoCommand( CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - // Collect the attributes -- do this now so no matter what the outcome, + // Collect the attributes -- do this now so no matter what the outcome, // the data has been absorbed. StreamableMemBlock attr; attr.Set(rDataStream, rProtocol.GetTimeout()); @@ -600,7 +600,6 @@ BackupProtocolSetReplacementFileAttributes::DoCommand( } - // -------------------------------------------------------------------------- // // Function @@ -671,7 +670,7 @@ std::auto_ptr BackupProtocolDeleteDirectory::DoCommand(Ba { rContext.DeleteDirectory(mObjectID); } - catch (BackupStoreException &e) + catch(BackupStoreException &e) { if(e.GetSubType() == BackupStoreException::MultiplyReferencedObject) { @@ -745,7 +744,7 @@ std::auto_ptr BackupProtocolMoveObject::DoCommand(BackupP { CHECK_PHASE(Phase_Commands) CHECK_WRITEABLE_SESSION - + // Let context do this, but modify error reporting on exceptions... try { @@ -785,21 +784,21 @@ std::auto_ptr BackupProtocolMoveObject::DoCommand(BackupP std::auto_ptr BackupProtocolGetObjectName::DoCommand(BackupProtocolReplyable &rProtocol, BackupStoreContext &rContext) const { CHECK_PHASE(Phase_Commands) - + // Create a stream for the list of filenames std::auto_ptr stream(new CollectInBufferStream); // Object and directory IDs int64_t objectID = mObjectID; int64_t dirID = mContainingDirectoryID; - + // Data to return in the reply int32_t numNameElements = 0; int16_t objectFlags = 0; int64_t modTime = 0; uint64_t attrModHash = 0; bool haveModTimes = false; - + do { // Check the directory really exists @@ -822,13 +821,13 @@ std::auto_ptr BackupProtocolGetObjectName::DoCommand(Back // Abort! return std::auto_ptr(new BackupProtocolObjectName(BackupProtocolObjectName::NumNameElements_ObjectDoesntExist, 0, 0, 0)); } - + // Store flags? if(objectFlags == 0) { objectFlags = en->GetFlags(); } - + // Store modification times? if(!haveModTimes) { @@ -836,14 +835,14 @@ std::auto_ptr BackupProtocolGetObjectName::DoCommand(Back attrModHash = en->GetAttributesHash(); haveModTimes = true; } - + // Store the name in the stream en->GetName().WriteToStream(*stream); - + // Count of name elements ++numNameElements; } - + // Setup for next time round objectID = dirID; dirID = rdir.GetContainerID(); @@ -854,7 +853,7 @@ std::auto_ptr BackupProtocolGetObjectName::DoCommand(Back if(numNameElements > 0) { // Get the stream ready to go - stream->SetForReading(); + stream->SetForReading(); // Tell the protocol to send the stream rProtocol.SendStreamAfterCommand(static_cast< std::auto_ptr >(stream)); } @@ -879,10 +878,10 @@ std::auto_ptr BackupProtocolGetBlockIndexByID::DoCommand( // Open the file std::auto_ptr stream(rContext.OpenObject(mObjectID)); - + // Move the file pointer to the block index BackupStoreFile::MoveStreamPositionToBlockIndex(*stream); - + // Return the stream to the client rProtocol.SendStreamAfterCommand(stream); @@ -905,7 +904,7 @@ std::auto_ptr BackupProtocolGetBlockIndexByName::DoComman // Get the directory const BackupStoreDirectory &dir(rContext.GetDirectory(mInDirectory)); - + // Find the latest object ID within it which has the same name int64_t objectID = 0; BackupStoreDirectory::Iterator i(dir); @@ -921,7 +920,7 @@ std::auto_ptr BackupProtocolGetBlockIndexByName::DoComman } } } - + // Found anything? if(objectID == 0) { @@ -931,10 +930,10 @@ std::auto_ptr BackupProtocolGetBlockIndexByName::DoComman // Open the file std::auto_ptr stream(rContext.OpenObject(objectID)); - + // Move the file pointer to the block index BackupStoreFile::MoveStreamPositionToBlockIndex(*stream); - + // Return the stream to the client rProtocol.SendStreamAfterCommand(stream); @@ -957,11 +956,11 @@ std::auto_ptr BackupProtocolGetAccountUsage::DoCommand(Ba // Get store info from context const BackupStoreInfo &rinfo(rContext.GetBackupStoreInfo()); - + // Find block size RaidFileController &rcontroller(RaidFileController::GetController()); RaidFileDiscSet &rdiscSet(rcontroller.GetDiscSet(rinfo.GetDiscSetNumber())); - + // Return info return std::auto_ptr(new BackupProtocolAccountUsage( rinfo.GetBlocksUsed(), @@ -1007,11 +1006,11 @@ std::auto_ptr BackupProtocolGetAccountUsage2::DoCommand( // Get store info from context const BackupStoreInfo &info(rContext.GetBackupStoreInfo()); - + // Find block size RaidFileController &rcontroller(RaidFileController::GetController()); RaidFileDiscSet &rdiscSet(rcontroller.GetDiscSet(info.GetDiscSetNumber())); - + // Return info BackupProtocolAccountUsage2* usage = new BackupProtocolAccountUsage2(); std::auto_ptr reply(usage); @@ -1036,4 +1035,3 @@ std::auto_ptr BackupProtocolGetAccountUsage2::DoCommand( return reply; } - -- cgit v1.2.3 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 From feade829d345bd6e34f39dfc32498696e6f588a1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 15 Aug 2015 10:57:59 +0000 Subject: Improve exception handling on backup store side. Add a new exception code to represent an object being completely missing (not found on the store at all), separate from not being found in a particular directory. Improve mapping of server-side exceptions to protocol error messages returned to the client. Add handling for missing exceptions, such as BackupStoreException::PatchChainInfoBadInDirectory, and the new BackupStoreException::ObjectDoesNotExist. Fix mapping for BackupStoreException::CouldNotFindEntryInDirectory to make it distinguistable from BackupStoreException::ObjectDoesNotExist. --- lib/backupstore/BackupCommands.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'lib/backupstore/BackupCommands.cpp') diff --git a/lib/backupstore/BackupCommands.cpp b/lib/backupstore/BackupCommands.cpp index ab0dc4b8..22ef0215 100644 --- a/lib/backupstore/BackupCommands.cpp +++ b/lib/backupstore/BackupCommands.cpp @@ -85,12 +85,20 @@ std::auto_ptr BackupProtocolReplyable::HandleException(Bo } else if(e.GetSubType() == BackupStoreException::CouldNotFindEntryInDirectory) { - return PROTOCOL_ERROR(Err_DoesNotExist); + return PROTOCOL_ERROR(Err_DoesNotExistInDirectory); } else if(e.GetSubType() == BackupStoreException::NameAlreadyExistsInDirectory) { return PROTOCOL_ERROR(Err_TargetNameExists); } + else if(e.GetSubType() == BackupStoreException::ObjectDoesNotExist) + { + return PROTOCOL_ERROR(Err_DoesNotExist); + } + else if(e.GetSubType() == BackupStoreException::PatchChainInfoBadInDirectory) + { + return PROTOCOL_ERROR(Err_PatchConsistencyError); + } } throw; @@ -779,7 +787,28 @@ std::auto_ptr BackupProtocolGetObjectName::DoCommand(Back } // Load up the directory - const BackupStoreDirectory &rdir(rContext.GetDirectory(dirID)); + const BackupStoreDirectory *pDir; + + try + { + pDir = &rContext.GetDirectory(dirID); + } + catch(BackupStoreException &e) + { + if(e.GetSubType() == BackupStoreException::ObjectDoesNotExist) + { + // If this can't be found, then there is a problem... + // tell the caller it can't be found. + return std::auto_ptr( + new BackupProtocolObjectName( + BackupProtocolObjectName::NumNameElements_ObjectDoesntExist, + 0, 0, 0)); + } + + throw; + } + + const BackupStoreDirectory& rdir(*pDir); // Find the element in this directory and store it's name if(objectID != ObjectID_DirectoryOnly) -- cgit v1.2.3