diff options
author | Chris Wilson <chris+github@qwirx.com> | 2012-11-18 16:29:41 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2012-11-18 16:29:41 +0000 |
commit | 6af3a67ae549913692a4cee69fabb50988a61fe9 (patch) | |
tree | 918fe6350d522acb4c608bb77ee93cade767ad7c | |
parent | 3db7d944f5849db8ea8098de54ad45bbb0bf6b86 (diff) |
Add a helper in BackupStoreAccounts to get a write lock on an account.
Use it in two places to simplify code (not in BackupStoreContext yet,
because that wants to communicate with HK process as well).
-rw-r--r-- | bin/bbstoreaccounts/bbstoreaccounts.cpp | 91 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreAccounts.cpp | 40 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreAccounts.h | 2 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreCheck.cpp | 34 |
4 files changed, 67 insertions, 100 deletions
diff --git a/bin/bbstoreaccounts/bbstoreaccounts.cpp b/bin/bbstoreaccounts/bbstoreaccounts.cpp index 3f911b92..996a12fb 100644 --- a/bin/bbstoreaccounts/bbstoreaccounts.cpp +++ b/bin/bbstoreaccounts/bbstoreaccounts.cpp @@ -128,37 +128,8 @@ int64_t SizeStringToBlocks(const char *string, int discSetNum) } } -bool GetWriteLockOnAccount(NamedLock &rLock, const std::string rRootDir, - int discSetNum) -{ - std::string writeLockFilename; - StoreStructure::MakeWriteLockFilename(rRootDir, discSetNum, writeLockFilename); - - bool gotLock = false; - int triesLeft = 8; - do - { - gotLock = rLock.TryAndGetLock(writeLockFilename.c_str(), 0600 /* restrictive file permissions */); - - if(!gotLock) - { - --triesLeft; - ::sleep(1); - } - } while(!gotLock && triesLeft > 0); - - if(!gotLock) - { - // Couldn't lock the account -- just stop now - BOX_ERROR("Failed to lock the account, did not change limits. " - "Try again later."); - } - - return gotLock; -} - bool OpenAccount(Configuration &rConfig, int32_t ID, std::string &rRootDirOut, - int &rDiscSetOut, std::auto_ptr<UnixUser> apUser); + int &rDiscSetOut, std::auto_ptr<UnixUser> apUser, NamedLock* pLock); int SetLimit(Configuration &rConfig, int32_t ID, const char *SoftLimitStr, const char *HardLimitStr) @@ -166,22 +137,15 @@ int SetLimit(Configuration &rConfig, int32_t ID, const char *SoftLimitStr, std::string rootDir; int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return + NamedLock writeLock; - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, &writeLock)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " to change limits."); return 1; } - // Attempt to lock - NamedLock writeLock; - if(!GetWriteLockOnAccount(writeLock, rootDir, discSetNum)) - { - // Failed to get lock - return 1; - } - // Load the info std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(ID, rootDir, discSetNum, false /* Read/Write */)); @@ -208,22 +172,15 @@ int SetAccountName(Configuration &rConfig, int32_t ID, std::string rootDir; int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return + NamedLock writeLock; - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, &writeLock)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " to change name."); return 1; } - // Attempt to lock - NamedLock writeLock; - if(!GetWriteLockOnAccount(writeLock, rootDir, discSetNum)) - { - // Failed to get lock - return 1; - } - // Load the info std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(ID, rootDir, discSetNum, false /* Read/Write */)); @@ -245,7 +202,8 @@ int AccountInfo(Configuration &rConfig, int32_t ID) int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, + NULL /* no write lock needed for this read-only operation */)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " to display info."); @@ -306,8 +264,9 @@ int SetAccountEnabled(Configuration &rConfig, int32_t ID, bool enabled) std::string rootDir; int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return + NamedLock writeLock; - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, &writeLock)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " to change enabled flag."); @@ -327,8 +286,10 @@ int DeleteAccount(Configuration &rConfig, int32_t ID, bool AskForConfirmation) std::string rootDir; int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return + NamedLock writeLock; - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + // Obtain a write lock, as the daemon user + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, &writeLock)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " for deletion."); @@ -348,19 +309,8 @@ int DeleteAccount(Configuration &rConfig, int32_t ID, bool AskForConfirmation) } } - // Obtain a write lock, as the daemon user - NamedLock writeLock; - { - // Get a write lock - if(!GetWriteLockOnAccount(writeLock, rootDir, discSetNum)) - { - // Failed to get lock - return 1; - } - - // Back to original user, but write lock is maintained - user.reset(); - } + // Back to original user, but write lock is maintained + user.reset(); std::auto_ptr<BackupStoreAccountDatabase> db(BackupStoreAccountDatabase::Read(rConfig.GetKeyValue("AccountDatabase").c_str())); @@ -431,7 +381,7 @@ int DeleteAccount(Configuration &rConfig, int32_t ID, bool AskForConfirmation) } bool OpenAccount(Configuration &rConfig, int32_t ID, std::string &rRootDirOut, - int &rDiscSetOut, std::auto_ptr<UnixUser> apUser) + int &rDiscSetOut, std::auto_ptr<UnixUser> apUser, NamedLock* pLock) { // Load in the account database std::auto_ptr<BackupStoreAccountDatabase> db(BackupStoreAccountDatabase::Read(rConfig.GetKeyValue("AccountDatabase").c_str())); @@ -468,6 +418,11 @@ bool OpenAccount(Configuration &rConfig, int32_t ID, std::string &rRootDirOut, // in the caller. } + if(pLock) + { + acc.LockAccount(ID, *pLock); + } + return true; } @@ -476,8 +431,9 @@ int CheckAccount(Configuration &rConfig, int32_t ID, bool FixErrors, bool Quiet) std::string rootDir; int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return + NamedLock writeLock; - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, &writeLock)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " for checking."); @@ -530,7 +486,8 @@ int HousekeepAccountNow(Configuration &rConfig, int32_t ID) int discSetNum; std::auto_ptr<UnixUser> user; // used to reset uid when we return - if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user)) + if(!OpenAccount(rConfig, ID, rootDir, discSetNum, user, + NULL /* housekeeping locks the account itself */)) { BOX_ERROR("Failed to open account " << BOX_FORMAT_ACCOUNT(ID) << " for housekeeping."); diff --git a/lib/backupstore/BackupStoreAccounts.cpp b/lib/backupstore/BackupStoreAccounts.cpp index b7ef13ab..18500fc1 100644 --- a/lib/backupstore/BackupStoreAccounts.cpp +++ b/lib/backupstore/BackupStoreAccounts.cpp @@ -11,14 +11,16 @@ #include <stdio.h> -#include "BoxPortsAndFiles.h" #include "BackupStoreAccounts.h" #include "BackupStoreAccountDatabase.h" +#include "BackupStoreConstants.h" +#include "BackupStoreDirectory.h" +#include "BackupStoreException.h" +#include "BackupStoreInfo.h" #include "BackupStoreRefCountDatabase.h" +#include "BoxPortsAndFiles.h" #include "RaidFileWrite.h" -#include "BackupStoreInfo.h" -#include "BackupStoreDirectory.h" -#include "BackupStoreConstants.h" +#include "StoreStructure.h" #include "UnixUser.h" #include "MemLeakFindOn.h" @@ -168,4 +170,34 @@ bool BackupStoreAccounts::AccountExists(int32_t ID) return mrDatabase.EntryExists(ID); } +void BackupStoreAccounts::LockAccount(int32_t ID, NamedLock& rNamedLock) +{ + const BackupStoreAccountDatabase::Entry &en(mrDatabase.GetEntry(ID)); + std::string rootDir = MakeAccountRootDir(ID, en.GetDiscSet()); + int discSet = en.GetDiscSet(); + + std::string writeLockFilename; + StoreStructure::MakeWriteLockFilename(rootDir, discSet, writeLockFilename); + + bool gotLock = false; + int triesLeft = 8; + do + { + gotLock = rNamedLock.TryAndGetLock(writeLockFilename, + 0600 /* restrictive file permissions */); + + if(!gotLock) + { + --triesLeft; + ::sleep(1); + } + } + while (!gotLock && triesLeft > 0); + if (!gotLock) + { + THROW_EXCEPTION_MESSAGE(BackupStoreException, + CouldNotLockStoreAccount, "Failed to get exclusive " + "lock on account " << ID); + } +} diff --git a/lib/backupstore/BackupStoreAccounts.h b/lib/backupstore/BackupStoreAccounts.h index 109de701..3163f15c 100644 --- a/lib/backupstore/BackupStoreAccounts.h +++ b/lib/backupstore/BackupStoreAccounts.h @@ -13,6 +13,7 @@ #include <string> #include "BackupStoreAccountDatabase.h" +#include "NamedLock.h" // -------------------------------------------------------------------------- // @@ -41,6 +42,7 @@ public: { return MakeAccountRootDir(rEntry.GetID(), rEntry.GetDiscSet()); } + void LockAccount(int32_t ID, NamedLock& rNamedLock); private: static std::string MakeAccountRootDir(int32_t ID, int DiscSet); diff --git a/lib/backupstore/BackupStoreCheck.cpp b/lib/backupstore/BackupStoreCheck.cpp index 04f6a41c..4530b9dd 100644 --- a/lib/backupstore/BackupStoreCheck.cpp +++ b/lib/backupstore/BackupStoreCheck.cpp @@ -81,40 +81,16 @@ BackupStoreCheck::~BackupStoreCheck() // // Function // Name: BackupStoreCheck::Check() -// Purpose: Perform the check on the given account +// Purpose: Perform the check on the given account. You need to +// hold a lock on the account before calling this! // Created: 21/4/04 // // -------------------------------------------------------------------------- void BackupStoreCheck::Check() { - // Lock the account - { - std::string writeLockFilename; - StoreStructure::MakeWriteLockFilename(mStoreRoot, mDiscSetNumber, writeLockFilename); - - bool gotLock = false; - int triesLeft = 8; - do - { - gotLock = mAccountLock.TryAndGetLock(writeLockFilename.c_str(), 0600 /* restrictive file permissions */); - - if(!gotLock) - { - --triesLeft; - ::sleep(1); - } - } while(!gotLock && triesLeft > 0); - - if(!gotLock) - { - // Couldn't lock the account -- just stop now - if(!mQuiet) - { - BOX_ERROR("Failed to lock the account -- did not check.\nTry again later after the client has disconnected.\nAlternatively, forcibly kill the server."); - } - THROW_EXCEPTION(BackupStoreException, CouldNotLockStoreAccount) - } - } + std::string writeLockFilename; + StoreStructure::MakeWriteLockFilename(mStoreRoot, mDiscSetNumber, writeLockFilename); + ASSERT(FileExists(writeLockFilename)); if(!mQuiet && mFixErrors) { |