summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2012-11-18 16:29:41 +0000
committerChris Wilson <chris+github@qwirx.com>2012-11-18 16:29:41 +0000
commit6af3a67ae549913692a4cee69fabb50988a61fe9 (patch)
tree918fe6350d522acb4c608bb77ee93cade767ad7c
parent3db7d944f5849db8ea8098de54ad45bbb0bf6b86 (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.cpp91
-rw-r--r--lib/backupstore/BackupStoreAccounts.cpp40
-rw-r--r--lib/backupstore/BackupStoreAccounts.h2
-rw-r--r--lib/backupstore/BackupStoreCheck.cpp34
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)
{