Skip to content

Commit

Permalink
Refactor all RaidFile code out of BackupStoreContext and BackupCommands.
Browse files Browse the repository at this point in the history
Add a RaidBackupFileSystem implementation and use it instead.
  • Loading branch information
qris committed Oct 17, 2015
1 parent fa6e3a1 commit cd49635
Show file tree
Hide file tree
Showing 6 changed files with 725 additions and 450 deletions.
14 changes: 12 additions & 2 deletions lib/backupstore/BackupAccountControl.cpp
Expand Up @@ -20,7 +20,6 @@
#include "BackupStoreInfo.h"
#include "Configuration.h"
#include "HTTPResponse.h"
#include "Utils.h"

#include "MemLeakFindOn.h"

Expand Down Expand Up @@ -181,8 +180,19 @@ int S3BackupAccountControl::CreateAccount(const std::string& name, int32_t SoftL
// continue. Otherwise something else is wrong and we should bail out.
std::string info_url = mapFileSystem->GetObjectURL(S3_INFO_FILE_NAME);
HTTPResponse response = mapFileSystem->GetObject(S3_INFO_FILE_NAME);
if(response.GetResponseCode() != HTTPResponse::Code_NotFound)
if(response.GetResponseCode() == HTTPResponse::Code_OK)
{
THROW_EXCEPTION_MESSAGE(BackupStoreException, AccountAlreadyExists,
"The BackupStoreInfo file already exists at this URL: " <<
info_url);
}
else if(response.GetResponseCode() == HTTPResponse::Code_NotFound)
{
// 404 not found is exactly what we want here.
}
else
{
// This should report an error in a consistent way.
mapS3Client->CheckResponse(response, std::string("The BackupStoreInfo file already "
"exists at this URL: ") + info_url);
}
Expand Down
137 changes: 4 additions & 133 deletions lib/backupstore/BackupCommands.cpp
Expand Up @@ -21,11 +21,7 @@
#include "BackupStoreException.h"
#include "BackupStoreFile.h"
#include "BackupStoreInfo.h"
#include "BufferedStream.h"
#include "CollectInBufferStream.h"
#include "FileStream.h"
#include "InvisibleTempFileStream.h"
#include "RaidFileController.h"
#include "StreamableMemBlock.h"

#include "MemLeakFindOn.h"
Expand Down Expand Up @@ -356,125 +352,8 @@ std::auto_ptr<BackupProtocolMessage> BackupProtocolGetFile::DoCommand(BackupProt
return PROTOCOL_ERROR(Err_DoesNotExist);
}

// Get the directory it's in
const BackupStoreDirectory &rdir(rContext.GetDirectory(mInDirectory));

// Find the object within the directory
BackupStoreDirectory::Entry *pfileEntry = rdir.FindEntryByID(mObjectID);
if(pfileEntry == 0)
{
return PROTOCOL_ERROR(Err_DoesNotExistInDirectory);
}

// The result
std::auto_ptr<IOStream> stream;

// Does this depend on anything?
if(pfileEntry->GetDependsNewer() != 0)
{
// File exists, but is a patch from a new version. Generate the older version.
std::vector<int64_t> patchChain;
int64_t id = mObjectID;
BackupStoreDirectory::Entry *en = 0;
do
{
patchChain.push_back(id);
en = rdir.FindEntryByID(id);
if(en == 0)
{
BOX_ERROR("Object " <<
BOX_FORMAT_OBJECTID(mObjectID) <<
" in dir " <<
BOX_FORMAT_OBJECTID(mInDirectory) <<
" for account " <<
BOX_FORMAT_ACCOUNT(rContext.GetClientID()) <<
" references object " <<
BOX_FORMAT_OBJECTID(id) <<
" which does not exist in dir");
return PROTOCOL_ERROR(Err_PatchConsistencyError);
}
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<IOStream> 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<IOStream> diff(rContext.OpenObject(patchID));
std::auto_ptr<IOStream> 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 =
RaidFileController::DiscSetPathToFileSystemPath(
rContext.GetStoreDiscSet(), fs.str(),
p + 16);

// Open the temporary file
std::auto_ptr<IOStream> 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<IOStream> 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<IOStream> 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
std::auto_ptr<IOStream> t(BackupStoreFile::ReorderFileToStreamOrder(object.get(), true /* take ownership */));
stream = t;
}

// Object will be deleted when the stream is deleted,
// so can release the object auto_ptr here to avoid
// premature deletion
object.release();
}
std::auto_ptr<IOStream> stream =
rContext.GetFile(mObjectID, mInDirectory);

// Stream the reordered stream to the peer
rProtocol.SendStreamAfterCommand(stream);
Expand Down Expand Up @@ -957,10 +836,6 @@ std::auto_ptr<BackupProtocolMessage> 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<BackupProtocolMessage>(new BackupProtocolAccountUsage(
rinfo.GetBlocksUsed(),
Expand All @@ -969,7 +844,7 @@ std::auto_ptr<BackupProtocolMessage> BackupProtocolGetAccountUsage::DoCommand(Ba
rinfo.GetBlocksInDirectories(),
rinfo.GetBlocksSoftLimit(),
rinfo.GetBlocksHardLimit(),
rdiscSet.GetBlockSize()
rContext.GetBlockSize()
));
}

Expand Down Expand Up @@ -1007,18 +882,14 @@ std::auto_ptr<BackupProtocolMessage> 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<BackupProtocolMessage> reply(usage);
#define COPY(name) usage->Set ## name (info.Get ## name ())
COPY(AccountName);
usage->SetAccountEnabled(info.IsAccountEnabled());
COPY(ClientStoreMarker);
usage->SetBlockSize(rdiscSet.GetBlockSize());
usage->SetBlockSize(rContext.GetBlockSize());
COPY(LastObjectIDUsed);
COPY(BlocksUsed);
COPY(BlocksInCurrentFiles);
Expand Down

0 comments on commit cd49635

Please sign in to comment.