Skip to content

Commit

Permalink
Refactor BackupAccountControl to use BackupFileSystem
Browse files Browse the repository at this point in the history
  • Loading branch information
qris committed Oct 7, 2017
1 parent d9f32eb commit 807c950
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 125 deletions.
159 changes: 72 additions & 87 deletions lib/backupstore/BackupAccountControl.cpp
Expand Up @@ -48,6 +48,7 @@
throw; \
}


void BackupAccountControl::CheckSoftHardLimits(int64_t SoftLimit, int64_t HardLimit)
{
if(SoftLimit > HardLimit)
Expand All @@ -64,6 +65,7 @@ void BackupAccountControl::CheckSoftHardLimits(int64_t SoftLimit, int64_t HardLi
}
}


int64_t BackupAccountControl::SizeStringToBlocks(const char *string, int blockSize)
{
// Get number
Expand Down Expand Up @@ -105,12 +107,14 @@ int64_t BackupAccountControl::SizeStringToBlocks(const char *string, int blockSi
}
}


std::string BackupAccountControl::BlockSizeToString(int64_t Blocks, int64_t MaxBlocks, int BlockSize)
{
return FormatUsageBar(Blocks, Blocks * BlockSize, MaxBlocks * BlockSize,
mMachineReadableOutput);
}


int BackupStoreAccountControl::BlockSizeOfDiscSet(int discSetNum)
{
// Get controller, check disc set number
Expand All @@ -125,52 +129,48 @@ int BackupStoreAccountControl::BlockSizeOfDiscSet(int discSetNum)
return controller.GetDiscSet(discSetNum).GetBlockSize();
}

int BackupStoreAccountControl::SetLimit(const char *SoftLimitStr,

int BackupAccountControl::SetLimit(const char *SoftLimitStr,
const char *HardLimitStr)
{
OPEN_ACCOUNT(true); // readWrite
int64_t softlimit = SizeStringToBlocks(SoftLimitStr, GetBlockSize());
int64_t hardlimit = SizeStringToBlocks(HardLimitStr, GetBlockSize());
return BackupAccountControl::SetLimit(softlimit, hardlimit);
}

// Load the info
std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(mAccountID, mRootDir,
mDiscSetNum, false /* Read/Write */));

// Change the limits
int blocksize = GetBlockSize();
int64_t softlimit = SizeStringToBlocks(SoftLimitStr, blocksize);
int64_t hardlimit = SizeStringToBlocks(HardLimitStr, blocksize);
int BackupAccountControl::SetLimit(int64_t softlimit, int64_t hardlimit)
{
CheckSoftHardLimits(softlimit, hardlimit);
info->ChangeLimits(softlimit, hardlimit);

// Save
info->Save();
// Change the limits
OPEN_ACCOUNT(true); // readWrite
BackupStoreInfo &info(mapFileSystem->GetBackupStoreInfo(false)); // !ReadOnly
info.ChangeLimits(softlimit, hardlimit);
mapFileSystem->PutBackupStoreInfo(info);

BOX_NOTICE("Limits on account " << BOX_FORMAT_ACCOUNT(mAccountID) <<
" changed to " << softlimit << " soft, " <<
hardlimit << " hard.");
BOX_NOTICE("Limits on account " << mapFileSystem->GetAccountIdentifier() << " "
"changed to " << softlimit << " blocks soft, " << hardlimit << " hard.");

return 0;
}

int BackupStoreAccountControl::SetAccountName(const std::string& rNewAccountName)

int BackupAccountControl::SetAccountName(const std::string& rNewAccountName)
{
OPEN_ACCOUNT(true); // readWrite
BackupStoreInfo &info(mapFileSystem->GetBackupStoreInfo(false)); // !ReadOnly
info.SetAccountName(rNewAccountName);
mapFileSystem->PutBackupStoreInfo(info);

// Load the info
std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(mAccountID,
mRootDir, mDiscSetNum, false /* Read/Write */));

info->SetAccountName(rNewAccountName);

// Save
info->Save();

BOX_NOTICE("Account " << BOX_FORMAT_ACCOUNT(mAccountID) <<
" name changed to " << rNewAccountName);
BOX_NOTICE("Name of account " << mapFileSystem->GetAccountIdentifier() << " "
"changed to " << rNewAccountName);

return 0;
}

int BackupStoreAccountControl::PrintAccountInfo()

int BackupAccountControl::PrintAccountInfo()
{
OPEN_ACCOUNT(false); // !readWrite

Expand Down Expand Up @@ -222,25 +222,28 @@ int BackupStoreAccountControl::PrintAccountInfo()
return 0;
}

int BackupStoreAccountControl::SetAccountEnabled(bool enabled)

int BackupAccountControl::SetAccountEnabled(bool enabled)
{
OPEN_ACCOUNT(true); // readWrite
BackupStoreInfo &info(mapFileSystem->GetBackupStoreInfo(false)); // !ReadOnly
info.SetAccountEnabled(enabled);
mapFileSystem->PutBackupStoreInfo(info);

BOX_NOTICE("Account " << mapFileSystem->GetAccountIdentifier() << " is now " <<
(enabled ? "enabled" : "disabled"));

// Load it in
std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(mAccountID,
mRootDir, mDiscSetNum, false /* ReadOnly */));
info->SetAccountEnabled(enabled);
info->Save();
return 0;
}


int BackupAccountControl::CreateAccount(int32_t AccountID, int32_t SoftLimit,
int32_t HardLimit, const std::string& AccountName)
{
OPEN_ACCOUNT(true); // readWrite
// We definitely need a lock to do something this destructive!
mapFileSystem->GetLock();

BackupStoreInfo& info(mapFileSystem->GetBackupStoreInfo(false)); // !ReadOnly
BackupStoreInfo info(AccountID, SoftLimit, HardLimit);
info.SetAccountName(AccountName);

// And an empty directory
Expand Down Expand Up @@ -271,8 +274,10 @@ int BackupAccountControl::CreateAccount(int32_t AccountID, int32_t SoftLimit,
return 0;
}


int BackupStoreAccountControl::DeleteAccount(bool AskForConfirmation)
{
// Obtain a write lock, as the daemon user
// We definitely need a lock to do something this destructive!
OPEN_ACCOUNT(true); // readWrite

Expand Down Expand Up @@ -377,6 +382,7 @@ int BackupStoreAccountControl::DeleteAccount(bool AskForConfirmation)
return retcode;
}


void BackupStoreAccountControl::OpenAccount(bool readWrite)
{
if(mapFileSystem.get())
Expand Down Expand Up @@ -436,6 +442,7 @@ void BackupStoreAccountControl::OpenAccount(bool readWrite)
}
}


int BackupStoreAccountControl::CheckAccount(bool FixErrors, bool Quiet,
bool ReturnNumErrorsFound)
{
Expand All @@ -456,9 +463,12 @@ int BackupStoreAccountControl::CheckAccount(bool FixErrors, bool Quiet,
}
}

int BackupStoreAccountControl::CreateAccount(int32_t DiscNumber,
int32_t SoftLimit, int32_t HardLimit)

int BackupStoreAccountControl::CreateAccount(int32_t DiscNumber, int32_t SoftLimit,
int32_t HardLimit)
{
CheckSoftHardLimits(SoftLimit, HardLimit);

// Load in the account database
std::auto_ptr<BackupStoreAccountDatabase> db(
BackupStoreAccountDatabase::Read(
Expand Down Expand Up @@ -504,8 +514,6 @@ int BackupStoreAccountControl::CreateAccount(int32_t DiscNumber,
RaidFileWrite::CreateDirectory(mDiscSetNum, mRootDir, true /* recursive */);

// Create the BackupStoreInfo and BackupStoreRefCountDatabase files:
BackupStoreInfo::CreateNew(mAccountID, mRootDir, mDiscSetNum, SoftLimit, HardLimit);

mapFileSystem.reset(new RaidBackupFileSystem(mAccountID, mRootDir, mDiscSetNum));
BackupAccountControl::CreateAccount(mAccountID, SoftLimit, HardLimit, "");

Expand Down Expand Up @@ -538,6 +546,7 @@ int BackupStoreAccountControl::HousekeepAccountNow()
}
}


S3BackupAccountControl::S3BackupAccountControl(const Configuration& config,
bool machineReadableOutput)
: BackupAccountControl(config, machineReadableOutput)
Expand Down Expand Up @@ -578,65 +587,41 @@ S3BackupAccountControl::S3BackupAccountControl(const Configuration& config,
*mapS3Client));
}

std::string S3BackupAccountControl::GetFullURL(const std::string ObjectPath) const
{
const Configuration s3config = mConfig.GetSubConfiguration("S3Store");
return std::string("http://") + s3config.GetKeyValue("HostName") + ":" +
s3config.GetKeyValue("Port") + GetFullPath(ObjectPath);
}

int S3BackupAccountControl::CreateAccount(const std::string& name, int32_t SoftLimit,
int32_t HardLimit)
{
// Try getting the info file. If we get a 200 response then it already
// exists, and we should bail out. If we get a 404 then it's safe to
// continue. Otherwise something else is wrong and we should bail out.
std::string info_url = GetFullURL(S3_INFO_FILE_NAME);

HTTPResponse response = GetObject(S3_INFO_FILE_NAME);
if(response.GetResponseCode() == HTTPResponse::Code_OK)
S3BackupFileSystem& s3fs(*(S3BackupFileSystem *)(mapFileSystem.get()));
try
{
THROW_EXCEPTION_MESSAGE(BackupStoreException, AccountAlreadyExists,
"The BackupStoreInfo file already exists at this URL: " <<
info_url);
// We expect this to throw a FileNotFound HTTPException.
HideSpecificExceptionGuard guard(HTTPException::ExceptionType,
HTTPException::FileNotFound);
s3fs.GetBackupStoreInfoUncached();

// If it doesn't, then the file already exists, which is bad.
BOX_FATAL("The BackupStoreInfo file already exists at this URL: " <<
s3fs.GetObjectURL(s3fs.GetMetadataURI(S3_INFO_FILE_NAME)));
return 1;
}

if(response.GetResponseCode() != HTTPResponse::Code_NotFound)
catch(HTTPException &e)
{
mapS3Client->CheckResponse(response, std::string("Failed to check for an "
"existing BackupStoreInfo file at this URL: ") + info_url);
if(EXCEPTION_IS_TYPE(e, HTTPException, FileNotFound))
{
// This is what we want to see, so don't do anything rash.
}
else
{
// This is not what we wanted to see, so reraise the exception.
throw;
}
}

BackupStoreInfo info(0, // fake AccountID for S3 stores
info_url, // FileName,
SoftLimit, HardLimit);
info.SetAccountName(name);

// And an empty directory
BackupStoreDirectory rootDir(BACKUPSTORE_ROOT_DIRECTORY_ID, BACKUPSTORE_ROOT_DIRECTORY_ID);
mapFileSystem->PutDirectory(rootDir);
int64_t rootDirSize = rootDir.GetUserInfo1_SizeInBlocks();

// Update the store info to reflect the size of the root directory
info.ChangeBlocksUsed(rootDirSize);
info.ChangeBlocksInDirectories(rootDirSize);
info.AdjustNumDirectories(1);
int64_t id = info.AllocateObjectID();
ASSERT(id == BACKUPSTORE_ROOT_DIRECTORY_ID);

CollectInBufferStream out;
info.Save(out);
out.SetForReading();

response = PutObject(S3_INFO_FILE_NAME, out);
mapS3Client->CheckResponse(response, std::string("Failed to upload the new BackupStoreInfo "
"file to this URL: ") + info_url);

// Now get the file again, to check that it really worked.
response = GetObject(S3_INFO_FILE_NAME);
mapS3Client->CheckResponse(response, std::string("Failed to download the new BackupStoreInfo "
"file that we just created: ") + info_url);
// Create the BackupStoreInfo and BackupStoreRefCountDatabase files:
BackupAccountControl::CreateAccount(S3_FAKE_ACCOUNT_ID, SoftLimit, HardLimit, name);

return 0;
}

28 changes: 9 additions & 19 deletions lib/backupstore/BackupAccountControl.h
Expand Up @@ -35,6 +35,7 @@ class BackupAccountControl
{
return mapFileSystem->GetBlockSize();
}
virtual int SetLimit(int64_t softlimit, int64_t hardlimit);

public:
BackupAccountControl(const Configuration& config,
Expand All @@ -46,7 +47,10 @@ class BackupAccountControl
void CheckSoftHardLimits(int64_t SoftLimit, int64_t HardLimit);
int64_t SizeStringToBlocks(const char *string, int BlockSize);
std::string BlockSizeToString(int64_t Blocks, int64_t MaxBlocks, int BlockSize);
int PrintAccountInfo(const BackupStoreInfo& info, int BlockSize);
virtual int SetLimit(const char *SoftLimitStr, const char *HardLimitStr);
virtual int SetAccountName(const std::string& rNewAccountName);
virtual int PrintAccountInfo();
virtual int SetAccountEnabled(bool enabled);
int CreateAccount(int32_t AccountID, int32_t SoftLimit, int32_t HardLimit,
const std::string& AccountName);
};
Expand Down Expand Up @@ -74,11 +78,6 @@ class BackupStoreAccountControl : public BackupAccountControl
return BlockSizeOfDiscSet(mDiscSetNum);
}
int BlockSizeOfDiscSet(int discSetNum);
int SetLimit(const char *SoftLimitStr,
const char *HardLimitStr);
int SetAccountName(const std::string& rNewAccountName);
int PrintAccountInfo();
int SetAccountEnabled(bool enabled);
int DeleteAccount(bool AskForConfirmation);
int CheckAccount(bool FixErrors, bool Quiet,
bool ReturnNumErrorsFound = false);
Expand All @@ -98,23 +97,14 @@ class S3BackupAccountControl : public BackupAccountControl
public:
S3BackupAccountControl(const Configuration& config,
bool machineReadableOutput = false);
std::string GetFullPath(const std::string ObjectPath) const
virtual ~S3BackupAccountControl()
{
return mBasePath + ObjectPath;
// Destroy mapFileSystem before mapS3Client, because it may need it
// for cleanup.
mapFileSystem.reset();
}
std::string GetFullURL(const std::string ObjectPath) const;
int CreateAccount(const std::string& name, int32_t SoftLimit, int32_t HardLimit);
int GetBlockSize() { return 4096; }
HTTPResponse GetObject(const std::string& name)
{
return mapS3Client->GetObject(GetFullPath(name));
}
HTTPResponse PutObject(const std::string& name, IOStream& rStreamToSend,
const char* pContentType = NULL)
{
return mapS3Client->PutObject(GetFullPath(name), rStreamToSend,
pContentType);
}
};

// max size of soft limit as percent of hard limit
Expand Down
14 changes: 11 additions & 3 deletions lib/backupstore/BackupFileSystem.cpp
Expand Up @@ -1168,6 +1168,7 @@ std::string S3BackupFileSystem::GetObjectURL(const std::string& ObjectPath) cons
s3config.GetKeyValue("Port") + ObjectPath;
}


int64_t S3BackupFileSystem::GetRevisionID(const std::string& uri,
HTTPResponse& response) const
{
Expand Down Expand Up @@ -1207,7 +1208,7 @@ std::auto_ptr<BackupStoreInfo> S3BackupFileSystem::GetBackupStoreInfoInternal(bo
{
std::string info_uri = GetMetadataURI(S3_INFO_FILE_NAME);
std::string info_url = GetObjectURL(info_uri);
HTTPResponse response = mrClient.GetObject(info_url);
HTTPResponse response = mrClient.GetObject(info_uri);
mrClient.CheckResponse(response, std::string("No BackupStoreInfo file exists "
"at this URL: ") + info_url);

Expand All @@ -1227,13 +1228,20 @@ std::auto_ptr<BackupStoreInfo> S3BackupFileSystem::GetBackupStoreInfoInternal(bo

void S3BackupFileSystem::PutBackupStoreInfo(BackupStoreInfo& rInfo)
{
if(rInfo.IsReadOnly())
{
THROW_EXCEPTION_MESSAGE(BackupStoreException, StoreInfoIsReadOnly,
"Tried to save BackupStoreInfo when configured as read-only");
}

CollectInBufferStream out;
rInfo.Save(out);
out.SetForReading();

HTTPResponse response = mrClient.PutObject(S3_INFO_FILE_NAME, out);
std::string info_uri = GetMetadataURI(S3_INFO_FILE_NAME);
HTTPResponse response = mrClient.PutObject(info_uri, out);

std::string info_url = GetObjectURL(S3_INFO_FILE_NAME);
std::string info_url = GetObjectURL(info_uri);
mrClient.CheckResponse(response, std::string("Failed to upload the new "
"BackupStoreInfo file to this URL: ") + info_url);
}
Expand Down

0 comments on commit 807c950

Please sign in to comment.