summaryrefslogtreecommitdiff
path: root/bin/bbstored
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbstored')
-rw-r--r--bin/bbstored/BBStoreDHousekeeping.cpp16
-rw-r--r--bin/bbstored/BackupCommands.cpp165
-rw-r--r--bin/bbstored/BackupConstants.h2
-rw-r--r--bin/bbstored/BackupStoreContext.cpp (renamed from bin/bbstored/BackupContext.cpp)211
-rw-r--r--bin/bbstored/BackupStoreContext.h (renamed from bin/bbstored/BackupContext.h)50
-rw-r--r--bin/bbstored/BackupStoreDaemon.cpp34
-rw-r--r--bin/bbstored/BackupStoreDaemon.h15
-rw-r--r--bin/bbstored/HousekeepStoreAccount.cpp274
-rw-r--r--bin/bbstored/HousekeepStoreAccount.h3
-rw-r--r--bin/bbstored/backupprotocol.txt8
-rwxr-xr-xbin/bbstored/bbstored-config.in4
-rw-r--r--bin/bbstored/bbstored.cpp2
12 files changed, 525 insertions, 259 deletions
diff --git a/bin/bbstored/BBStoreDHousekeeping.cpp b/bin/bbstored/BBStoreDHousekeeping.cpp
index 16a1432a..1c1767ca 100644
--- a/bin/bbstored/BBStoreDHousekeeping.cpp
+++ b/bin/bbstored/BBStoreDHousekeeping.cpp
@@ -46,6 +46,12 @@ void BackupStoreDaemon::HousekeepingProcess()
{
RunHousekeepingIfNeeded();
+ // Stop early?
+ if(StopRun())
+ {
+ break;
+ }
+
// Calculate how long should wait before doing the next
// housekeeping run
int64_t timeNow = GetCurrentBoxTime();
@@ -155,7 +161,11 @@ void BackupStoreDaemon::RunHousekeepingIfNeeded()
void BackupStoreDaemon::OnIdle()
{
- #ifdef WIN32
+ if (!IsSingleProcess())
+ {
+ return;
+ }
+
if (!mHousekeepingInited)
{
HousekeepingInit();
@@ -163,7 +173,6 @@ void BackupStoreDaemon::OnIdle()
}
RunHousekeepingIfNeeded();
- #endif
}
// --------------------------------------------------------------------------
@@ -193,7 +202,8 @@ bool BackupStoreDaemon::CheckForInterProcessMsg(int AccountNum, int MaximumWaitT
std::string line;
if(mInterProcessComms.GetLine(line, false /* no pre-processing */, MaximumWaitTime))
{
- TRACE1("Housekeeping received command '%s' over interprocess comms\n", line.c_str());
+ BOX_TRACE("Housekeeping received command '" << line <<
+ "' over interprocess comms");
int account = 0;
diff --git a/bin/bbstored/BackupCommands.cpp b/bin/bbstored/BackupCommands.cpp
index bca52c04..38cda234 100644
--- a/bin/bbstored/BackupCommands.cpp
+++ b/bin/bbstored/BackupCommands.cpp
@@ -13,25 +13,25 @@
#include <sstream>
#include "autogen_BackupProtocolServer.h"
+#include "autogen_RaidFileException.h"
#include "BackupConstants.h"
-#include "BackupContext.h"
-#include "CollectInBufferStream.h"
+#include "BackupStoreContext.h"
+#include "BackupStoreConstants.h"
#include "BackupStoreDirectory.h"
#include "BackupStoreException.h"
#include "BackupStoreFile.h"
-#include "StreamableMemBlock.h"
-#include "BackupStoreConstants.h"
-#include "RaidFileController.h"
#include "BackupStoreInfo.h"
-#include "RaidFileController.h"
+#include "BufferedStream.h"
+#include "CollectInBufferStream.h"
#include "FileStream.h"
#include "InvisibleTempFileStream.h"
-#include "BufferedStream.h"
+#include "RaidFileController.h"
+#include "StreamableMemBlock.h"
#include "MemLeakFindOn.h"
#define CHECK_PHASE(phase) \
- if(rContext.GetPhase() != BackupContext::phase) \
+ if(rContext.GetPhase() != BackupStoreContext::phase) \
{ \
return std::auto_ptr<ProtocolObject>(new BackupProtocolServerError( \
BackupProtocolServerError::ErrorType, BackupProtocolServerError::Err_NotInRightProtocolPhase)); \
@@ -47,12 +47,12 @@
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerVersion::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerVersion::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Return the current version, or an error if the requested version isn't allowed
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerVersion::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerVersion::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Version)
@@ -64,7 +64,7 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerVersion::DoCommand(BackupProto
}
// Mark the next phase
- rContext.SetPhase(BackupContext::Phase_Login);
+ rContext.SetPhase(BackupStoreContext::Phase_Login);
// Return our version
return std::auto_ptr<ProtocolObject>(new BackupProtocolServerVersion(BACKUP_STORE_SERVER_VERSION));
@@ -73,12 +73,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerVersion::DoCommand(BackupProto
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerLogin::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerLogin::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Return the current version, or an error if the requested version isn't allowed
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerLogin::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerLogin::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Login)
@@ -131,7 +131,7 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerLogin::DoCommand(BackupProtoco
int64_t clientStoreMarker = rContext.GetClientStoreMarker();
// Mark the next phase
- rContext.SetPhase(BackupContext::Phase_Commands);
+ rContext.SetPhase(BackupStoreContext::Phase_Commands);
// Log login
BOX_NOTICE("Login from Client ID " <<
@@ -151,12 +151,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerLogin::DoCommand(BackupProtoco
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerFinished::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerFinished::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Marks end of conversation (Protocol framework handles this)
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerFinished::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerFinished::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
BOX_NOTICE("Session finished for Client ID " <<
BOX_FORMAT_ACCOUNT(rContext.GetClientID()));
@@ -172,47 +172,72 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerFinished::DoCommand(BackupProt
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerListDirectory::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerListDirectory::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Command to list a directory
// Created: 2003/09/02
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerListDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerListDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
- // Ask the context for a directory
- const BackupStoreDirectory &rdir(rContext.GetDirectory(mObjectID));
-
// Store the listing to a stream
std::auto_ptr<CollectInBufferStream> stream(new CollectInBufferStream);
- rdir.WriteToStream(*stream, mFlagsMustBeSet, mFlagsNotToBeSet, mSendAttributes,
- false /* never send dependency info to the client */);
+
+ 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 std::auto_ptr<ProtocolObject>(
+ new BackupProtocolServerError(
+ BackupProtocolServerError::ErrorType,
+ BackupProtocolServerError::Err_DoesNotExist));
+ }
+ throw;
+ }
+
stream->SetForReading();
// Get the protocol to send the stream
rProtocol.SendStreamAfterCommand(stream.release());
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
+ return std::auto_ptr<ProtocolObject>(
+ new BackupProtocolServerSuccess(mObjectID));
}
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerStoreFile::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerStoreFile::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Command to store a file on the server
// Created: 2003/09/02
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerStoreFile::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerStoreFile::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
+
+ std::auto_ptr<ProtocolObject> hookResult =
+ rContext.StartCommandHook(*this);
+ if(hookResult.get())
+ {
+ return hookResult;
+ }
// Check that the diff from file actually exists, if it's specified
if(mDiffFromFileID != 0)
{
- if(!rContext.ObjectExists(mDiffFromFileID, BackupContext::ObjectExists_File))
+ if(!rContext.ObjectExists(mDiffFromFileID, BackupStoreContext::ObjectExists_File))
{
return std::auto_ptr<ProtocolObject>(new BackupProtocolServerError(
BackupProtocolServerError::ErrorType, BackupProtocolServerError::Err_DiffFromFileDoesNotExist));
@@ -257,12 +282,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerStoreFile::DoCommand(BackupPro
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetObject::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerGetObject::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Command to get an arbitary object from the server
// Created: 2003/09/03
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetObject::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetObject::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -285,13 +310,13 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetObject::DoCommand(BackupPro
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetFile::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerGetFile::DoCommand(Protocol &, BackupStoreContext &)
// 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
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetFile::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetFile::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -457,12 +482,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetFile::DoCommand(BackupProto
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerCreateDirectory::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerCreateDirectory::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Create directory command
// Created: 2003/09/04
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerCreateDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerCreateDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -500,12 +525,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerCreateDirectory::DoCommand(Bac
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerChangeDirAttributes::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerChangeDirAttributes::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Change attributes on directory
// Created: 2003/09/06
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerChangeDirAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerChangeDirAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -528,12 +553,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerChangeDirAttributes::DoCommand
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerSetReplacementFileAttributes::DoCommand(Protocol &, BackupContext &)
+// Name: BackupProtocolServerSetReplacementFileAttributes::DoCommand(Protocol &, BackupStoreContext &)
// Purpose: Change attributes on directory
// Created: 2003/09/06
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerSetReplacementFileAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerSetReplacementFileAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -563,12 +588,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerSetReplacementFileAttributes::
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Delete a file
// Created: 2003/10/21
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -585,12 +610,36 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteFile::DoCommand(BackupPr
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerDeleteDirectory::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerUndeleteFile::DoCommand(
+// BackupProtocolServer &, BackupStoreContext &)
+// Purpose: Undelete a file
+// Created: 2008-09-12
+//
+// --------------------------------------------------------------------------
+std::auto_ptr<ProtocolObject> BackupProtocolServerUndeleteFile::DoCommand(
+ BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
+{
+ CHECK_PHASE(Phase_Commands)
+ CHECK_WRITEABLE_SESSION
+
+ // Context handles this
+ bool result = rContext.UndeleteFile(mObjectID, mInDirectory);
+
+ // return the object ID or zero for not found
+ return std::auto_ptr<ProtocolObject>(
+ new BackupProtocolServerSuccess(result ? mObjectID : 0));
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupProtocolServerDeleteDirectory::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Delete a directory
// Created: 2003/10/21
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -613,12 +662,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteDirectory::DoCommand(Bac
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Undelete a directory
// Created: 23/11/03
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -640,12 +689,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerUndeleteDirectory::DoCommand(B
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerSetClientStoreMarker::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerSetClientStoreMarker::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Command to set the client's store marker
// Created: 2003/10/29
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerSetClientStoreMarker::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerSetClientStoreMarker::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -661,12 +710,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerSetClientStoreMarker::DoComman
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerMoveObject::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerMoveObject::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Command to move an object from one directory to another
// Created: 2003/11/12
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerMoveObject::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerMoveObject::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
CHECK_WRITEABLE_SESSION
@@ -704,12 +753,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerMoveObject::DoCommand(BackupPr
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetObjectName::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerGetObjectName::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Command to find the name of an object
// Created: 12/11/03
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetObjectName::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetObjectName::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -730,7 +779,7 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetObjectName::DoCommand(Backu
do
{
// Check the directory really exists
- if(!rContext.ObjectExists(dirID, BackupContext::ObjectExists_Directory))
+ if(!rContext.ObjectExists(dirID, BackupStoreContext::ObjectExists_Directory))
{
return std::auto_ptr<ProtocolObject>(new BackupProtocolServerObjectName(BackupProtocolServerObjectName::NumNameElements_ObjectDoesntExist, 0, 0, 0));
}
@@ -795,12 +844,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetObjectName::DoCommand(Backu
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetBlockIndexByID::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerGetBlockIndexByID::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Get the block index from a file, by ID
// Created: 19/1/04
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByID::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByID::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -821,12 +870,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByID::DoCommand(B
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetBlockIndexByName::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerGetBlockIndexByName::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Get the block index from a file, by name within a directory
// Created: 19/1/04
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByName::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByName::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -873,12 +922,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetBlockIndexByName::DoCommand
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetAccountUsage::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerGetAccountUsage::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Return the amount of disc space used
// Created: 19/4/04
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetAccountUsage::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetAccountUsage::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
@@ -904,12 +953,12 @@ std::auto_ptr<ProtocolObject> BackupProtocolServerGetAccountUsage::DoCommand(Bac
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupProtocolServerGetIsAlive::DoCommand(BackupProtocolServer &, BackupContext &)
+// Name: BackupProtocolServerGetIsAlive::DoCommand(BackupProtocolServer &, BackupStoreContext &)
// Purpose: Return the amount of disc space used
// Created: 19/4/04
//
// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerGetIsAlive::DoCommand(BackupProtocolServer &rProtocol, BackupContext &rContext)
+std::auto_ptr<ProtocolObject> BackupProtocolServerGetIsAlive::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
{
CHECK_PHASE(Phase_Commands)
diff --git a/bin/bbstored/BackupConstants.h b/bin/bbstored/BackupConstants.h
index 515b3bcd..19d06a15 100644
--- a/bin/bbstored/BackupConstants.h
+++ b/bin/bbstored/BackupConstants.h
@@ -10,8 +10,6 @@
#ifndef BACKUPCONSTANTS__H
#define BACKUPCONSTANTS__H
-#define BACKUP_STORE_DEFAULT_ACCOUNT_DATABASE_FILE "/etc/box/backupstoreaccounts"
-
// 15 minutes to timeout (milliseconds)
#define BACKUP_STORE_TIMEOUT (15*60*1000)
diff --git a/bin/bbstored/BackupContext.cpp b/bin/bbstored/BackupStoreContext.cpp
index 16388099..990be05d 100644
--- a/bin/bbstored/BackupContext.cpp
+++ b/bin/bbstored/BackupStoreContext.cpp
@@ -1,7 +1,7 @@
// --------------------------------------------------------------------------
//
// File
-// Name: BackupContext.cpp
+// Name: BackupStoreContext.cpp
// Purpose: Context for backup store server
// Created: 2003/08/20
//
@@ -11,7 +11,7 @@
#include <stdio.h>
-#include "BackupContext.h"
+#include "BackupStoreContext.h"
#include "RaidFileWrite.h"
#include "RaidFileRead.h"
#include "BackupStoreDirectory.h"
@@ -33,7 +33,7 @@
// Maximum number of directories to keep in the cache
// When the cache is bigger than this, everything gets
// deleted.
-#ifdef NDEBUG
+#ifdef BOX_RELEASE_BUILD
#define MAX_CACHE_SIZE 32
#else
#define MAX_CACHE_SIZE 2
@@ -48,31 +48,33 @@
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::BackupContext()
+// Name: BackupStoreContext::BackupStoreContext()
// Purpose: Constructor
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-BackupContext::BackupContext(int32_t ClientID, BackupStoreDaemon &rDaemon)
+BackupStoreContext::BackupStoreContext(int32_t ClientID,
+ HousekeepingInterface &rDaemon)
: mClientID(ClientID),
mrDaemon(rDaemon),
mProtocolPhase(Phase_START),
mClientHasAccount(false),
mStoreDiscSet(-1),
mReadOnly(true),
- mSaveStoreInfoDelay(STORE_INFO_SAVE_DELAY)
+ mSaveStoreInfoDelay(STORE_INFO_SAVE_DELAY),
+ mpTestHook(NULL)
{
}
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::~BackupContext()
+// Name: BackupStoreContext::~BackupStoreContext()
// Purpose: Destructor
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-BackupContext::~BackupContext()
+BackupStoreContext::~BackupStoreContext()
{
// Delete the objects in the cache
for(std::map<int64_t, BackupStoreDirectory*>::iterator i(mDirectoryCache.begin()); i != mDirectoryCache.end(); ++i)
@@ -85,12 +87,12 @@ BackupContext::~BackupContext()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::CleanUp()
+// Name: BackupStoreContext::CleanUp()
// Purpose: Clean up after a connection
// Created: 16/12/03
//
// --------------------------------------------------------------------------
-void BackupContext::CleanUp()
+void BackupStoreContext::CleanUp()
{
// Make sure the store info is saved, if it has been loaded, isn't read only and has been modified
if(mpStoreInfo.get() && !(mpStoreInfo->IsReadOnly()) && mpStoreInfo->IsModified())
@@ -102,12 +104,12 @@ void BackupContext::CleanUp()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::ReceivedFinishCommand()
+// Name: BackupStoreContext::ReceivedFinishCommand()
// Purpose: Called when the finish command is received by the protocol
// Created: 16/12/03
//
// --------------------------------------------------------------------------
-void BackupContext::ReceivedFinishCommand()
+void BackupStoreContext::ReceivedFinishCommand()
{
if(!mReadOnly && mpStoreInfo.get())
{
@@ -120,12 +122,12 @@ void BackupContext::ReceivedFinishCommand()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::AttemptToGetWriteLock()
+// Name: BackupStoreContext::AttemptToGetWriteLock()
// Purpose: Attempt to get a write lock for the store, and if so, unset the read only flags
// Created: 2003/09/02
//
// --------------------------------------------------------------------------
-bool BackupContext::AttemptToGetWriteLock()
+bool BackupStoreContext::AttemptToGetWriteLock()
{
// Make the filename of the write lock file
std::string writeLockFile;
@@ -166,12 +168,12 @@ bool BackupContext::AttemptToGetWriteLock()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::LoadStoreInfo()
+// Name: BackupStoreContext::LoadStoreInfo()
// Purpose: Load the store info from disc
// Created: 2003/09/03
//
// --------------------------------------------------------------------------
-void BackupContext::LoadStoreInfo()
+void BackupStoreContext::LoadStoreInfo()
{
if(mpStoreInfo.get() != 0)
{
@@ -195,12 +197,12 @@ void BackupContext::LoadStoreInfo()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::SaveStoreInfo(bool)
+// Name: BackupStoreContext::SaveStoreInfo(bool)
// Purpose: Potentially delayed saving of the store info
// Created: 16/12/03
//
// --------------------------------------------------------------------------
-void BackupContext::SaveStoreInfo(bool AllowDelay)
+void BackupStoreContext::SaveStoreInfo(bool AllowDelay)
{
if(mpStoreInfo.get() == 0)
{
@@ -233,13 +235,13 @@ void BackupContext::SaveStoreInfo(bool AllowDelay)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::MakeObjectFilename(int64_t, std::string &, bool)
+// Name: BackupStoreContext::MakeObjectFilename(int64_t, std::string &, bool)
// Purpose: Create the filename of an object in the store, optionally creating the
// containing directory if it doesn't already exist.
// Created: 2003/09/02
//
// --------------------------------------------------------------------------
-void BackupContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutput, bool EnsureDirectoryExists)
+void BackupStoreContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutput, bool EnsureDirectoryExists)
{
// Delegate to utility function
StoreStructure::MakeObjectFilename(ObjectID, mStoreRoot, mStoreDiscSet, rOutput, EnsureDirectoryExists);
@@ -249,7 +251,7 @@ void BackupContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutput, b
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::GetDirectoryInternal(int64_t)
+// Name: BackupStoreContext::GetDirectoryInternal(int64_t)
// Purpose: Return a reference to a directory. Valid only until the
// next time a function which affects directories is called.
// Mainly this funciton, and creation of files.
@@ -257,7 +259,7 @@ void BackupContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutput, b
// Created: 2003/09/02
//
// --------------------------------------------------------------------------
-BackupStoreDirectory &BackupContext::GetDirectoryInternal(int64_t ObjectID)
+BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID)
{
// Get the filename
std::string filename;
@@ -277,9 +279,17 @@ BackupStoreDirectory &BackupContext::GetDirectoryInternal(int64_t ObjectID)
if(revID == item->second->GetRevisionID())
{
// Looks good... return the cached object
+ BOX_TRACE("Returning object " <<
+ BOX_FORMAT_OBJECTID(ObjectID) <<
+ " from cache, modtime = " << revID);
return *(item->second);
}
+ BOX_TRACE("Refreshing object " <<
+ BOX_FORMAT_OBJECTID(ObjectID) <<
+ " in cache, modtime changed from " <<
+ item->second->GetRevisionID() << " to " << revID);
+
// Delete this cached object
delete item->second;
mDirectoryCache.erase(item);
@@ -335,12 +345,12 @@ BackupStoreDirectory &BackupContext::GetDirectoryInternal(int64_t ObjectID)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::AllocateObjectID()
+// Name: BackupStoreContext::AllocateObjectID()
// Purpose: Allocate a new object ID, tolerant of failures to save store info
// Created: 16/12/03
//
// --------------------------------------------------------------------------
-int64_t BackupContext::AllocateObjectID()
+int64_t BackupStoreContext::AllocateObjectID()
{
if(mpStoreInfo.get() == 0)
{
@@ -374,7 +384,8 @@ int64_t BackupContext::AllocateObjectID()
// Mark that the store info should be saved as soon as possible
mSaveStoreInfoDelay = 0;
- TRACE1("When allocating object ID, found that %lld is already in use\n", id);
+ BOX_WARNING("When allocating object ID, found that " <<
+ BOX_FORMAT_OBJECTID(id) << " is already in use");
}
THROW_EXCEPTION(BackupStoreException, CouldNotFindUnusedIDDuringAllocation)
@@ -384,13 +395,13 @@ int64_t BackupContext::AllocateObjectID()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::AddFile(IOStream &, int64_t, int64_t, int64_t, const BackupStoreFilename &, bool)
+// Name: BackupStoreContext::AddFile(IOStream &, int64_t, int64_t, int64_t, const BackupStoreFilename &, bool)
// Purpose: Add a file to the store, from a given stream, into a specified directory.
// Returns object ID of the new file.
// Created: 2003/09/03
//
// --------------------------------------------------------------------------
-int64_t BackupContext::AddFile(IOStream &rFile, int64_t InDirectory, int64_t ModificationTime,
+int64_t BackupStoreContext::AddFile(IOStream &rFile, int64_t InDirectory, int64_t ModificationTime,
int64_t AttributesHash, int64_t DiffFromFileID, const BackupStoreFilename &rFilename,
bool MarkFileWithSameNameAsOldVersions)
{
@@ -672,18 +683,19 @@ int64_t BackupContext::AddFile(IOStream &rFile, int64_t InDirectory, int64_t Mod
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::DeleteFile(const BackupStoreFilename &, int64_t, int64_t &)
+// Name: BackupStoreContext::DeleteFile(const BackupStoreFilename &, int64_t, int64_t &)
// Purpose: Deletes a file, returning true if the file existed. Object ID returned too, set to zero if not found.
// Created: 2003/10/21
//
// --------------------------------------------------------------------------
-bool BackupContext::DeleteFile(const BackupStoreFilename &rFilename, int64_t InDirectory, int64_t &rObjectIDOut)
+bool BackupStoreContext::DeleteFile(const BackupStoreFilename &rFilename, int64_t InDirectory, int64_t &rObjectIDOut)
{
// Essential checks!
if(mpStoreInfo.get() == 0)
{
THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
}
+
if(mReadOnly)
{
THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
@@ -748,23 +760,102 @@ bool BackupContext::DeleteFile(const BackupStoreFilename &rFilename, int64_t InD
RemoveDirectoryFromCache(InDirectory);
throw;
}
-
return fileExisted;
}
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupStoreContext::DeleteFile(const BackupStoreFilename &, int64_t, int64_t &)
+// Purpose: Deletes a file, returning true if the file existed. Object ID returned too, set to zero if not found.
+// Created: 2003/10/21
+//
+// --------------------------------------------------------------------------
+bool BackupStoreContext::UndeleteFile(int64_t ObjectID, int64_t InDirectory)
+{
+ // Essential checks!
+ if(mpStoreInfo.get() == 0)
+ {
+ THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
+ }
+
+ if(mReadOnly)
+ {
+ THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
+ }
+
+ // Find the directory the file is in (will exception if it fails)
+ BackupStoreDirectory &dir(GetDirectoryInternal(InDirectory));
+
+ // Setup flags
+ bool fileExisted = false;
+ bool madeChanges = false;
+
+ // Count of deleted blocks
+ int64_t blocksDel = 0;
+
+ try
+ {
+ // Iterate through directory, only looking at files which have been deleted
+ BackupStoreDirectory::Iterator i(dir);
+ BackupStoreDirectory::Entry *e = 0;
+ while((e = i.Next(BackupStoreDirectory::Entry::Flags_File |
+ BackupStoreDirectory::Entry::Flags_Deleted, 0)) != 0)
+ {
+ // Compare name
+ if(e->GetObjectID() == ObjectID)
+ {
+ // Check that it's definitely already deleted
+ ASSERT((e->GetFlags() & BackupStoreDirectory::Entry::Flags_Deleted) != 0);
+ // Clear deleted flag
+ e->RemoveFlags(BackupStoreDirectory::Entry::Flags_Deleted);
+ // Mark as made a change
+ madeChanges = true;
+ blocksDel -= e->GetSizeInBlocks();
+
+ // Is this the last version?
+ if((e->GetFlags() & BackupStoreDirectory::Entry::Flags_OldVersion) == 0)
+ {
+ // Yes. It's been found.
+ fileExisted = true;
+ }
+ }
+ }
+
+ // Save changes?
+ if(madeChanges)
+ {
+ // Save the directory back
+ SaveDirectory(dir, InDirectory);
+
+ // Modify the store info, and write
+ mpStoreInfo->ChangeBlocksInDeletedFiles(blocksDel);
+
+ // Maybe postponed save of store info
+ SaveStoreInfo();
+ }
+ }
+ catch(...)
+ {
+ RemoveDirectoryFromCache(InDirectory);
+ throw;
+ }
+
+ return fileExisted;
+}
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::RemoveDirectoryFromCache(int64_t)
+// Name: BackupStoreContext::RemoveDirectoryFromCache(int64_t)
// Purpose: Remove directory from cache
// Created: 2003/09/04
//
// --------------------------------------------------------------------------
-void BackupContext::RemoveDirectoryFromCache(int64_t ObjectID)
+void BackupStoreContext::RemoveDirectoryFromCache(int64_t ObjectID)
{
std::map<int64_t, BackupStoreDirectory*>::iterator item(mDirectoryCache.find(ObjectID));
if(item != mDirectoryCache.end())
@@ -780,12 +871,12 @@ void BackupContext::RemoveDirectoryFromCache(int64_t ObjectID)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::SaveDirectory(BackupStoreDirectory &, int64_t)
+// Name: BackupStoreContext::SaveDirectory(BackupStoreDirectory &, int64_t)
// Purpose: Save directory back to disc, update time in cache
// Created: 2003/09/04
//
// --------------------------------------------------------------------------
-void BackupContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID)
+void BackupStoreContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID)
{
if(mpStoreInfo.get() == 0)
{
@@ -842,12 +933,12 @@ void BackupContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::AddDirectory(int64_t, const BackupStoreFilename &, bool &)
+// Name: BackupStoreContext::AddDirectory(int64_t, const BackupStoreFilename &, bool &)
// Purpose: Creates a directory (or just returns the ID of an existing one). rAlreadyExists set appropraitely.
// Created: 2003/09/04
//
// --------------------------------------------------------------------------
-int64_t BackupContext::AddDirectory(int64_t InDirectory, const BackupStoreFilename &rFilename, const StreamableMemBlock &Attributes, int64_t AttributesModTime, bool &rAlreadyExists)
+int64_t BackupStoreContext::AddDirectory(int64_t InDirectory, const BackupStoreFilename &rFilename, const StreamableMemBlock &Attributes, int64_t AttributesModTime, bool &rAlreadyExists)
{
if(mpStoreInfo.get() == 0)
{
@@ -936,12 +1027,12 @@ int64_t BackupContext::AddDirectory(int64_t InDirectory, const BackupStoreFilena
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::DeleteFile(const BackupStoreFilename &, int64_t, int64_t &, bool)
+// Name: BackupStoreContext::DeleteFile(const BackupStoreFilename &, int64_t, int64_t &, bool)
// Purpose: Recusively deletes a directory (or undeletes if Undelete = true)
// Created: 2003/10/21
//
// --------------------------------------------------------------------------
-void BackupContext::DeleteDirectory(int64_t ObjectID, bool Undelete)
+void BackupStoreContext::DeleteDirectory(int64_t ObjectID, bool Undelete)
{
// Essential checks!
if(mpStoreInfo.get() == 0)
@@ -1018,12 +1109,12 @@ void BackupContext::DeleteDirectory(int64_t ObjectID, bool Undelete)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::DeleteDirectoryRecurse(BackupStoreDirectory &, int64_t)
+// Name: BackupStoreContext::DeleteDirectoryRecurse(BackupStoreDirectory &, int64_t)
// Purpose: Private. Deletes a directory depth-first recusively.
// Created: 2003/10/21
//
// --------------------------------------------------------------------------
-void BackupContext::DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDeletedOut, bool Undelete)
+void BackupStoreContext::DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDeletedOut, bool Undelete)
{
try
{
@@ -1120,12 +1211,12 @@ void BackupContext::DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDel
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::ChangeDirAttributes(int64_t, const StreamableMemBlock &, int64_t)
+// Name: BackupStoreContext::ChangeDirAttributes(int64_t, const StreamableMemBlock &, int64_t)
// Purpose: Change the attributes of a directory
// Created: 2003/09/06
//
// --------------------------------------------------------------------------
-void BackupContext::ChangeDirAttributes(int64_t Directory, const StreamableMemBlock &Attributes, int64_t AttributesModTime)
+void BackupStoreContext::ChangeDirAttributes(int64_t Directory, const StreamableMemBlock &Attributes, int64_t AttributesModTime)
{
if(mpStoreInfo.get() == 0)
{
@@ -1157,12 +1248,12 @@ void BackupContext::ChangeDirAttributes(int64_t Directory, const StreamableMemBl
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::ChangeFileAttributes(int64_t, int64_t, const StreamableMemBlock &, int64_t)
+// Name: BackupStoreContext::ChangeFileAttributes(int64_t, int64_t, const StreamableMemBlock &, int64_t)
// Purpose: Sets the attributes on a directory entry. Returns true if the object existed, false if it didn't.
// Created: 2003/09/06
//
// --------------------------------------------------------------------------
-bool BackupContext::ChangeFileAttributes(const BackupStoreFilename &rFilename, int64_t InDirectory, const StreamableMemBlock &Attributes, int64_t AttributesHash, int64_t &rObjectIDOut)
+bool BackupStoreContext::ChangeFileAttributes(const BackupStoreFilename &rFilename, int64_t InDirectory, const StreamableMemBlock &Attributes, int64_t AttributesHash, int64_t &rObjectIDOut)
{
if(mpStoreInfo.get() == 0)
{
@@ -1222,12 +1313,12 @@ bool BackupContext::ChangeFileAttributes(const BackupStoreFilename &rFilename, i
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::ObjectExists(int64_t)
+// Name: BackupStoreContext::ObjectExists(int64_t)
// Purpose: Test to see if an object of this ID exists in the store
// Created: 2003/09/03
//
// --------------------------------------------------------------------------
-bool BackupContext::ObjectExists(int64_t ObjectID, int MustBe)
+bool BackupStoreContext::ObjectExists(int64_t ObjectID, int MustBe)
{
if(mpStoreInfo.get() == 0)
{
@@ -1293,12 +1384,12 @@ bool BackupContext::ObjectExists(int64_t ObjectID, int MustBe)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::OpenObject(int64_t)
+// Name: BackupStoreContext::OpenObject(int64_t)
// Purpose: Opens an object
// Created: 2003/09/03
//
// --------------------------------------------------------------------------
-std::auto_ptr<IOStream> BackupContext::OpenObject(int64_t ObjectID)
+std::auto_ptr<IOStream> BackupStoreContext::OpenObject(int64_t ObjectID)
{
if(mpStoreInfo.get() == 0)
{
@@ -1315,12 +1406,12 @@ std::auto_ptr<IOStream> BackupContext::OpenObject(int64_t ObjectID)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::GetClientStoreMarker()
+// Name: BackupStoreContext::GetClientStoreMarker()
// Purpose: Retrieve the client store marker
// Created: 2003/10/29
//
// --------------------------------------------------------------------------
-int64_t BackupContext::GetClientStoreMarker()
+int64_t BackupStoreContext::GetClientStoreMarker()
{
if(mpStoreInfo.get() == 0)
{
@@ -1334,12 +1425,12 @@ int64_t BackupContext::GetClientStoreMarker()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::GetStoreDiscUsageInfo(int64_t &, int64_t &, int64_t &)
+// Name: BackupStoreContext::GetStoreDiscUsageInfo(int64_t &, int64_t &, int64_t &)
// Purpose: Get disc usage info from store info
// Created: 1/1/04
//
// --------------------------------------------------------------------------
-void BackupContext::GetStoreDiscUsageInfo(int64_t &rBlocksUsed, int64_t &rBlocksSoftLimit, int64_t &rBlocksHardLimit)
+void BackupStoreContext::GetStoreDiscUsageInfo(int64_t &rBlocksUsed, int64_t &rBlocksSoftLimit, int64_t &rBlocksHardLimit)
{
if(mpStoreInfo.get() == 0)
{
@@ -1355,12 +1446,12 @@ void BackupContext::GetStoreDiscUsageInfo(int64_t &rBlocksUsed, int64_t &rBlocks
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::HardLimitExceeded()
+// Name: BackupStoreContext::HardLimitExceeded()
// Purpose: Returns true if the hard limit has been exceeded
// Created: 1/1/04
//
// --------------------------------------------------------------------------
-bool BackupContext::HardLimitExceeded()
+bool BackupStoreContext::HardLimitExceeded()
{
if(mpStoreInfo.get() == 0)
{
@@ -1374,12 +1465,12 @@ bool BackupContext::HardLimitExceeded()
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::SetClientStoreMarker(int64_t)
+// Name: BackupStoreContext::SetClientStoreMarker(int64_t)
// Purpose: Sets the client store marker, and commits it to disc
// Created: 2003/10/29
//
// --------------------------------------------------------------------------
-void BackupContext::SetClientStoreMarker(int64_t ClientStoreMarker)
+void BackupStoreContext::SetClientStoreMarker(int64_t ClientStoreMarker)
{
if(mpStoreInfo.get() == 0)
{
@@ -1398,12 +1489,12 @@ void BackupContext::SetClientStoreMarker(int64_t ClientStoreMarker)
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::MoveObject(int64_t, int64_t, int64_t, const BackupStoreFilename &, bool)
+// Name: BackupStoreContext::MoveObject(int64_t, int64_t, int64_t, const BackupStoreFilename &, bool)
// Purpose: Move an object (and all objects with the same name) from one directory to another
// Created: 12/11/03
//
// --------------------------------------------------------------------------
-void BackupContext::MoveObject(int64_t ObjectID, int64_t MoveFromDirectory, int64_t MoveToDirectory, const BackupStoreFilename &rNewFilename, bool MoveAllWithSameName, bool AllowMoveOverDeletedObject)
+void BackupStoreContext::MoveObject(int64_t ObjectID, int64_t MoveFromDirectory, int64_t MoveToDirectory, const BackupStoreFilename &rNewFilename, bool MoveAllWithSameName, bool AllowMoveOverDeletedObject)
{
if(mReadOnly)
{
@@ -1643,12 +1734,12 @@ void BackupContext::MoveObject(int64_t ObjectID, int64_t MoveFromDirectory, int6
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupContext::GetBackupStoreInfo()
+// Name: BackupStoreContext::GetBackupStoreInfo()
// Purpose: Return the backup store info object, exception if it isn't loaded
// Created: 19/4/04
//
// --------------------------------------------------------------------------
-const BackupStoreInfo &BackupContext::GetBackupStoreInfo() const
+const BackupStoreInfo &BackupStoreContext::GetBackupStoreInfo() const
{
if(mpStoreInfo.get() == 0)
{
diff --git a/bin/bbstored/BackupContext.h b/bin/bbstored/BackupStoreContext.h
index 18f2f25c..4cfdb601 100644
--- a/bin/bbstored/BackupContext.h
+++ b/bin/bbstored/BackupStoreContext.h
@@ -1,7 +1,7 @@
// --------------------------------------------------------------------------
//
// File
-// Name: BackupContext.h
+// Name: BackupStoreContext.h
// Purpose: Context for backup store server
// Created: 2003/08/20
//
@@ -15,6 +15,7 @@
#include <memory>
#include "NamedLock.h"
+#include "ProtocolObject.h"
#include "Utils.h"
class BackupStoreDirectory;
@@ -22,23 +23,31 @@ class BackupStoreFilename;
class BackupStoreDaemon;
class BackupStoreInfo;
class IOStream;
+class BackupProtocolObject;
class StreamableMemBlock;
+class HousekeepingInterface
+{
+ public:
+ virtual ~HousekeepingInterface() { }
+ virtual void SendMessageToHousekeepingProcess(const void *Msg, int MsgLen) = 0;
+};
+
// --------------------------------------------------------------------------
//
// Class
-// Name: BackupContext
+// Name: BackupStoreContext
// Purpose: Context for backup store server
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-class BackupContext
+class BackupStoreContext
{
public:
- BackupContext(int32_t ClientID, BackupStoreDaemon &rDaemon);
- ~BackupContext();
+ BackupStoreContext(int32_t ClientID, HousekeepingInterface &rDaemon);
+ ~BackupStoreContext();
private:
- BackupContext(const BackupContext &rToCopy);
+ BackupStoreContext(const BackupStoreContext &rToCopy);
public:
void ReceivedFinishCommand();
@@ -83,7 +92,7 @@ public:
// --------------------------------------------------------------------------
//
// Function
- // Name: BackupContext::GetDirectory(int64_t)
+ // Name: BackupStoreContext::GetDirectory(int64_t)
// Purpose: Return a reference to a directory. Valid only until the
// next time a function which affects directories is called.
// Mainly this funciton, and creation of files.
@@ -103,6 +112,7 @@ public:
void ChangeDirAttributes(int64_t Directory, const StreamableMemBlock &Attributes, int64_t AttributesModTime);
bool ChangeFileAttributes(const BackupStoreFilename &rFilename, int64_t InDirectory, const StreamableMemBlock &Attributes, int64_t AttributesHash, int64_t &rObjectIDOut);
bool DeleteFile(const BackupStoreFilename &rFilename, int64_t InDirectory, int64_t &rObjectIDOut);
+ bool UndeleteFile(int64_t ObjectID, int64_t InDirectory);
void DeleteDirectory(int64_t ObjectID, bool Undelete = false);
void MoveObject(int64_t ObjectID, int64_t MoveFromDirectory, int64_t MoveToDirectory, const BackupStoreFilename &rNewFilename, bool MoveAllWithSameName, bool AllowMoveOverDeletedObject);
@@ -129,7 +139,7 @@ private:
private:
int32_t mClientID;
- BackupStoreDaemon &mrDaemon;
+ HousekeepingInterface &mrDaemon;
int mProtocolPhase;
bool mClientHasAccount;
std::string mStoreRoot; // has final directory separator
@@ -143,6 +153,30 @@ private:
// Directory cache
std::map<int64_t, BackupStoreDirectory*> mDirectoryCache;
+
+public:
+ class TestHook
+ {
+ public:
+ virtual std::auto_ptr<ProtocolObject> StartCommand(BackupProtocolObject&
+ rCommand) = 0;
+ virtual ~TestHook() { }
+ };
+ void SetTestHook(TestHook& rTestHook)
+ {
+ mpTestHook = &rTestHook;
+ }
+ std::auto_ptr<ProtocolObject> StartCommandHook(BackupProtocolObject& rCommand)
+ {
+ if(mpTestHook)
+ {
+ return mpTestHook->StartCommand(rCommand);
+ }
+ return std::auto_ptr<ProtocolObject>();
+ }
+
+private:
+ TestHook* mpTestHook;
};
#endif // BACKUPCONTEXT__H
diff --git a/bin/bbstored/BackupStoreDaemon.cpp b/bin/bbstored/BackupStoreDaemon.cpp
index 28e28176..4de0a078 100644
--- a/bin/bbstored/BackupStoreDaemon.cpp
+++ b/bin/bbstored/BackupStoreDaemon.cpp
@@ -17,7 +17,7 @@
#include <syslog.h>
#endif
-#include "BackupContext.h"
+#include "BackupStoreContext.h"
#include "BackupStoreDaemon.h"
#include "BackupStoreConfigVerify.h"
#include "autogen_BackupProtocolServer.h"
@@ -43,7 +43,8 @@ BackupStoreDaemon::BackupStoreDaemon()
mHaveForkedHousekeeping(false),
mIsHousekeepingProcess(false),
mHousekeepingInited(false),
- mInterProcessComms(mInterProcessCommsSocket)
+ mInterProcessComms(mInterProcessCommsSocket),
+ mpTestHook(NULL)
{
}
@@ -171,11 +172,12 @@ void BackupStoreDaemon::Run()
const Configuration &config(GetConfiguration());
mExtendedLogging = config.GetKeyValueBool("ExtendedLogging");
-#ifdef WIN32
- // Housekeeping runs synchronously on Win32
-#else
- // Fork off housekeeping daemon -- must only do this the first time Run() is called
- if(!mHaveForkedHousekeeping)
+ // Fork off housekeeping daemon -- must only do this the first
+ // time Run() is called. Housekeeping runs synchronously on Win32
+ // because IsSingleProcess() is always true
+
+#ifndef WIN32
+ if(!IsSingleProcess() && !mHaveForkedHousekeeping)
{
// Open a socket pair for communication
int sv[2] = {-1,-1};
@@ -205,7 +207,9 @@ void BackupStoreDaemon::Run()
// Log that housekeeping started
BOX_INFO("Housekeeping process started");
// Ignore term and hup
- // Parent will handle these and alert the child via the socket, don't want to randomly die
+ // Parent will handle these and alert the
+ // child via the socket, don't want to
+ // randomly die!
::signal(SIGHUP, SIG_IGN);
::signal(SIGTERM, SIG_IGN);
}
@@ -317,10 +321,18 @@ void BackupStoreDaemon::Connection2(SocketStreamTLS &rStream)
}
// Make ps listings clearer
- SetProcessTitle("client %08x", id);
+ std::ostringstream tag;
+ tag << "client=" << BOX_FORMAT_ACCOUNT(id);
+ SetProcessTitle(tag.str().c_str());
+ Logging::Tagger tagWithClientID(tag.str());
// Create a context, using this ID
- BackupContext context(id, *this);
+ BackupStoreContext context(id, *this);
+
+ if (mpTestHook)
+ {
+ context.SetTestHook(*mpTestHook);
+ }
// See if the client has an account?
if(mpAccounts && mpAccounts->AccountExists(id))
@@ -352,7 +364,7 @@ void BackupStoreDaemon::LogConnectionStats(const char *commonName,
const SocketStreamTLS &s)
{
// Log the amount of data transferred
- BOX_INFO("Connection statistics for " << commonName << ":"
+ BOX_NOTICE("Connection statistics for " << commonName << ":"
" IN=" << s.GetBytesRead() <<
" OUT=" << s.GetBytesWritten() <<
" TOTAL=" << (s.GetBytesRead() + s.GetBytesWritten()));
diff --git a/bin/bbstored/BackupStoreDaemon.h b/bin/bbstored/BackupStoreDaemon.h
index 387a1d5b..a5d216f4 100644
--- a/bin/bbstored/BackupStoreDaemon.h
+++ b/bin/bbstored/BackupStoreDaemon.h
@@ -13,6 +13,7 @@
#include "ServerTLS.h"
#include "BoxPortsAndFiles.h"
#include "BackupConstants.h"
+#include "BackupStoreContext.h"
#include "IOStreamGetLine.h"
class BackupStoreAccounts;
@@ -27,7 +28,8 @@ class HousekeepStoreAccount;
// Created: 2003/08/20
//
// --------------------------------------------------------------------------
-class BackupStoreDaemon : public ServerTLS<BOX_PORT_BBSTORED>
+class BackupStoreDaemon : public ServerTLS<BOX_PORT_BBSTORED>,
+ HousekeepingInterface
{
friend class HousekeepStoreAccount;
@@ -38,7 +40,7 @@ private:
BackupStoreDaemon(const BackupStoreDaemon &rToCopy);
public:
- // For BackupContext to communicate with housekeeping process
+ // For BackupStoreContext to communicate with housekeeping process
void SendMessageToHousekeepingProcess(const void *Msg, int MsgLen)
{
#ifndef WIN32
@@ -81,6 +83,15 @@ private:
void HousekeepingInit();
void RunHousekeepingIfNeeded();
int64_t mLastHousekeepingRun;
+
+public:
+ void SetTestHook(BackupStoreContext::TestHook& rTestHook)
+ {
+ mpTestHook = &rTestHook;
+ }
+
+private:
+ BackupStoreContext::TestHook* mpTestHook;
};
diff --git a/bin/bbstored/HousekeepStoreAccount.cpp b/bin/bbstored/HousekeepStoreAccount.cpp
index 9f4239e7..dbb9b544 100644
--- a/bin/bbstored/HousekeepStoreAccount.cpp
+++ b/bin/bbstored/HousekeepStoreAccount.cpp
@@ -85,16 +85,19 @@ void HousekeepStoreAccount::DoHousekeeping()
{
// Attempt to lock the account
std::string writeLockFilename;
- StoreStructure::MakeWriteLockFilename(mStoreRoot, mStoreDiscSet, writeLockFilename);
+ StoreStructure::MakeWriteLockFilename(mStoreRoot, mStoreDiscSet,
+ writeLockFilename);
NamedLock writeLock;
- if(!writeLock.TryAndGetLock(writeLockFilename.c_str(), 0600 /* restrictive file permissions */))
+ if(!writeLock.TryAndGetLock(writeLockFilename.c_str(),
+ 0600 /* restrictive file permissions */))
{
// Couldn't lock the account -- just stop now
return;
}
// Load the store info to find necessary info for the housekeeping
- std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(mAccountID, mStoreRoot, mStoreDiscSet, false /* Read/Write */));
+ std::auto_ptr<BackupStoreInfo> info(BackupStoreInfo::Load(mAccountID,
+ mStoreRoot, mStoreDiscSet, false /* Read/Write */));
// Calculate how much should be deleted
mDeletionSizeTarget = info->GetBlocksUsed() - info->GetBlocksSoftLimit();
@@ -104,14 +107,18 @@ void HousekeepStoreAccount::DoHousekeeping()
}
// Scan the directory for potential things to delete
- // This will also remove elegiable items marked with RemoveASAP
+ // This will also remove eligible items marked with RemoveASAP
bool continueHousekeeping = ScanDirectory(BACKUPSTORE_ROOT_DIRECTORY_ID);
- // If scan directory stopped for some reason, probably parent instructed to teminate, stop now.
+ // If scan directory stopped for some reason, probably parent
+ // instructed to terminate, stop now.
if(!continueHousekeeping)
{
- // If any files were marked "delete now", then update the size of the store.
- if(mBlocksUsedDelta != 0 || mBlocksInOldFilesDelta != 0 || mBlocksInDeletedFilesDelta != 0)
+ // If any files were marked "delete now", then update
+ // the size of the store.
+ if(mBlocksUsedDelta != 0 ||
+ mBlocksInOldFilesDelta != 0 ||
+ mBlocksInDeletedFilesDelta != 0)
{
info->ChangeBlocksUsed(mBlocksUsedDelta);
info->ChangeBlocksInOldFiles(mBlocksInOldFilesDelta);
@@ -124,8 +131,8 @@ void HousekeepStoreAccount::DoHousekeeping()
return;
}
- // Log any difference in opinion between the values recorded in the store info, and
- // the values just calculated for space usage.
+ // Log any difference in opinion between the values recorded in
+ // the store info, and the values just calculated for space usage.
// BLOCK
{
int64_t used = info->GetBlocksUsed();
@@ -133,9 +140,12 @@ void HousekeepStoreAccount::DoHousekeeping()
int64_t usedDeleted = info->GetBlocksInDeletedFiles();
int64_t usedDirectories = info->GetBlocksInDirectories();
- // If the counts were wrong, taking into account RemoveASAP items deleted, log a message
- if((used + mBlocksUsedDelta) != mBlocksUsed || (usedOld + mBlocksInOldFilesDelta) != mBlocksInOldFiles
- || (usedDeleted + mBlocksInDeletedFilesDelta) != mBlocksInDeletedFiles || usedDirectories != mBlocksInDirectories)
+ // If the counts were wrong, taking into account RemoveASAP
+ // items deleted, log a message
+ if((used + mBlocksUsedDelta) != mBlocksUsed
+ || (usedOld + mBlocksInOldFilesDelta) != mBlocksInOldFiles
+ || (usedDeleted + mBlocksInDeletedFilesDelta) != mBlocksInDeletedFiles
+ || usedDirectories != mBlocksInDirectories)
{
// Log this
BOX_ERROR("Housekeeping on account " <<
@@ -153,18 +163,25 @@ void HousekeepStoreAccount::DoHousekeeping()
}
// If the current values don't match, store them
- if(used != mBlocksUsed || usedOld != mBlocksInOldFiles
- || usedDeleted != mBlocksInDeletedFiles || usedDirectories != (mBlocksInDirectories + mBlocksInDirectoriesDelta))
+ if(used != mBlocksUsed
+ || usedOld != mBlocksInOldFiles
+ || usedDeleted != mBlocksInDeletedFiles
+ || usedDirectories != (mBlocksInDirectories + mBlocksInDirectoriesDelta))
{
// Set corrected values in store info
- info->CorrectAllUsedValues(mBlocksUsed, mBlocksInOldFiles, mBlocksInDeletedFiles, mBlocksInDirectories + mBlocksInDirectoriesDelta);
+ info->CorrectAllUsedValues(mBlocksUsed,
+ mBlocksInOldFiles, mBlocksInDeletedFiles,
+ mBlocksInDirectories + mBlocksInDirectoriesDelta);
info->Save();
}
}
- // Reset the delta counts for files, as they will include RemoveASAP flagged files deleted
- // during the initial scan.
- int64_t removeASAPBlocksUsedDelta = mBlocksUsedDelta; // keep for reporting
+ // Reset the delta counts for files, as they will include
+ // RemoveASAP flagged files deleted during the initial scan.
+
+ // keep for reporting
+ int64_t removeASAPBlocksUsedDelta = mBlocksUsedDelta;
+
mBlocksUsedDelta = 0;
mBlocksInOldFilesDelta = 0;
mBlocksInDeletedFilesDelta = 0;
@@ -172,7 +189,8 @@ void HousekeepStoreAccount::DoHousekeeping()
// Go and delete items from the accounts
bool deleteInterrupted = DeleteFiles();
- // If that wasn't interrupted, remove any empty directories which are also marked as deleted in their containing directory
+ // If that wasn't interrupted, remove any empty directories which
+ // are also marked as deleted in their containing directory
if(!deleteInterrupted)
{
deleteInterrupted = DeleteEmptyDirectories();
@@ -190,8 +208,9 @@ void HousekeepStoreAccount::DoHousekeeping()
(deleteInterrupted?" and was interrupted":""));
}
- // Make sure the delta's won't cause problems if the counts are really wrong, and
- // it wasn't fixed because the store was updated during the scan.
+ // Make sure the delta's won't cause problems if the counts are
+ // really wrong, and it wasn't fixed because the store was
+ // updated during the scan.
if(mBlocksUsedDelta < (0 - info->GetBlocksUsed()))
{
mBlocksUsedDelta = (0 - info->GetBlocksUsed());
@@ -218,7 +237,8 @@ void HousekeepStoreAccount::DoHousekeeping()
// Save the store info back
info->Save();
- // Explicity release the lock (would happen automatically on going out of scope, included for code clarity)
+ // Explicity release the lock (would happen automatically on
+ // going out of scope, included for code clarity)
writeLock.ReleaseLock();
}
@@ -243,8 +263,9 @@ void HousekeepStoreAccount::MakeObjectFilename(int64_t ObjectID, std::string &rF
//
// Function
// Name: HousekeepStoreAccount::ScanDirectory(int64_t)
-// Purpose: Private. Scan a directory for potenitally deleteable items, and
-// add them to the list. Returns true if the scan should continue.
+// Purpose: Private. Scan a directory for potentially deleteable
+// items, and add them to the list. Returns true if the
+// scan should continue.
// Created: 11/12/03
//
// --------------------------------------------------------------------------
@@ -253,9 +274,12 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
#ifndef WIN32
if((--mCountUntilNextInterprocessMsgCheck) <= 0)
{
- mCountUntilNextInterprocessMsgCheck = POLL_INTERPROCESS_MSG_CHECK_FREQUENCY;
+ mCountUntilNextInterprocessMsgCheck =
+ POLL_INTERPROCESS_MSG_CHECK_FREQUENCY;
+
// Check for having to stop
- if(mrDaemon.CheckForInterProcessMsg(mAccountID)) // include account ID here as the specified account is locked
+ // Include account ID here as the specified account is locked
+ if(mrDaemon.CheckForInterProcessMsg(mAccountID))
{
// Need to abort now
return false;
@@ -268,7 +292,8 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
MakeObjectFilename(ObjectID, objectFilename);
// Open it.
- std::auto_ptr<RaidFileRead> dirStream(RaidFileRead::Open(mStoreDiscSet, objectFilename));
+ std::auto_ptr<RaidFileRead> dirStream(RaidFileRead::Open(mStoreDiscSet,
+ objectFilename));
// Add the size of the directory on disc to the size being calculated
int64_t originalDirSizeInBlocks = dirStream->GetDiscUsageInBlocks();
@@ -290,8 +315,8 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
// BLOCK
{
- // Remove any files which are marked for removal as soon as they become old
- // or deleted.
+ // Remove any files which are marked for removal as soon
+ // as they become old or deleted.
bool deletedSomething = false;
do
{
@@ -324,7 +349,8 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
// Add files to the list of potential deletions
// map to count the distance from the mark
- std::map<std::pair<BackupStoreFilename, int32_t>, int32_t> markVersionAges;
+ typedef std::pair<std::string, int32_t> version_t;
+ std::map<version_t, int32_t> markVersionAges;
// map of pair (filename, mark number) -> version age
// NOTE: use a reverse iterator to allow the distance from mark stuff to work
@@ -342,7 +368,10 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
// Work out ages of this version from the last mark
int32_t enVersionAge = 0;
- std::map<std::pair<BackupStoreFilename, int32_t>, int32_t>::iterator enVersionAgeI(markVersionAges.find(std::pair<BackupStoreFilename, int32_t>(en->GetName(), en->GetMarkNumber())));
+ std::map<version_t, int32_t>::iterator enVersionAgeI(
+ markVersionAges.find(
+ version_t(en->GetName().GetEncodedFilename(),
+ en->GetMarkNumber())));
if(enVersionAgeI != markVersionAges.end())
{
enVersionAge = enVersionAgeI->second + 1;
@@ -350,7 +379,7 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
}
else
{
- markVersionAges[std::pair<BackupStoreFilename, int32_t>(en->GetName(), en->GetMarkNumber())] = enVersionAge;
+ markVersionAges[version_t(en->GetName().GetEncodedFilename(), en->GetMarkNumber())] = enVersionAge;
}
// enVersionAge is now the age of this version.
@@ -364,6 +393,9 @@ bool HousekeepStoreAccount::ScanDirectory(int64_t ObjectID)
d.mSizeInBlocks = en->GetSizeInBlocks();
d.mMarkNumber = en->GetMarkNumber();
d.mVersionAgeWithinMark = enVersionAge;
+ d.mIsFlagDeleted = (enFlags &
+ BackupStoreDirectory::Entry::Flags_Deleted)
+ ? true : false;
// Add it to the list
mPotentialDeletions.insert(d);
@@ -541,6 +573,10 @@ bool HousekeepStoreAccount::DeleteFiles()
// Delete the file
DeleteFile(i->mInDirectory, i->mObjectID, dir, dirFilename, dirSizeInBlocksOrig);
+ BOX_INFO("Housekeeping removed " <<
+ (i->mIsFlagDeleted ? "deleted" : "old") <<
+ " file " << BOX_FORMAT_OBJECTID(i->mObjectID) <<
+ " from dir " << BOX_FORMAT_OBJECTID(i->mInDirectory));
// Stop if the deletion target has been matched or exceeded
// (checking here rather than at the beginning will tend to reduce the
@@ -786,99 +822,115 @@ bool HousekeepStoreAccount::DeleteEmptyDirectories()
continue;
}
- // Load up the directory to potentially delete
- std::string dirFilename;
- BackupStoreDirectory dir;
- int64_t dirSizeInBlocks = 0;
- {
- MakeObjectFilename(*i, dirFilename);
- // Check it actually exists (just in case it gets added twice to the list)
- if(!RaidFileRead::FileExists(mStoreDiscSet, dirFilename))
- {
- // doesn't exist, next!
- continue;
- }
- // load
- std::auto_ptr<RaidFileRead> dirStream(RaidFileRead::Open(mStoreDiscSet, dirFilename));
- dirSizeInBlocks = dirStream->GetDiscUsageInBlocks();
- dir.ReadFromStream(*dirStream, IOStream::TimeOutInfinite);
- }
+ DeleteEmptyDirectory(*i, toExamine);
+ }
- // Make sure this directory is actually empty
- if(dir.GetNumberOfEntries() != 0)
- {
- // Not actually empty, try next one
- continue;
- }
+ // Remove contents of empty directories
+ mEmptyDirectories.clear();
+ // Swap in new, so it's examined next time round
+ mEmptyDirectories.swap(toExamine);
+ }
+
+ // Not interrupted
+ return false;
+}
- // Candiate for deletion... open containing directory
- std::string containingDirFilename;
- BackupStoreDirectory containingDir;
- int64_t containingDirSizeInBlocksOrig = 0;
- {
- MakeObjectFilename(dir.GetContainerID(), containingDirFilename);
- std::auto_ptr<RaidFileRead> containingDirStream(RaidFileRead::Open(mStoreDiscSet, containingDirFilename));
- containingDirSizeInBlocksOrig = containingDirStream->GetDiscUsageInBlocks();
- containingDir.ReadFromStream(*containingDirStream, IOStream::TimeOutInfinite);
- }
+void HousekeepStoreAccount::DeleteEmptyDirectory(int64_t dirId,
+ std::vector<int64_t>& rToExamine)
+{
+ // Load up the directory to potentially delete
+ std::string dirFilename;
+ BackupStoreDirectory dir;
+ int64_t dirSizeInBlocks = 0;
- // Find the entry
- BackupStoreDirectory::Entry *pdirentry = containingDir.FindEntryByID(dir.GetObjectID());
- if((pdirentry != 0) && ((pdirentry->GetFlags() & BackupStoreDirectory::Entry::Flags_Deleted) != 0))
- {
- // Should be deleted
- containingDir.DeleteEntry(dir.GetObjectID());
+ // BLOCK
+ {
+ MakeObjectFilename(dirId, dirFilename);
+ // Check it actually exists (just in case it gets
+ // added twice to the list)
+ if(!RaidFileRead::FileExists(mStoreDiscSet, dirFilename))
+ {
+ // doesn't exist, next!
+ return;
+ }
+ // load
+ std::auto_ptr<RaidFileRead> dirStream(
+ RaidFileRead::Open(mStoreDiscSet, dirFilename));
+ dirSizeInBlocks = dirStream->GetDiscUsageInBlocks();
+ dir.ReadFromStream(*dirStream, IOStream::TimeOutInfinite);
+ }
- // Is the containing dir now a candidate for deletion?
- if(containingDir.GetNumberOfEntries() == 0)
- {
- toExamine.push_back(containingDir.GetObjectID());
- }
+ // Make sure this directory is actually empty
+ if(dir.GetNumberOfEntries() != 0)
+ {
+ // Not actually empty, try next one
+ return;
+ }
- // Write revised parent directory
- RaidFileWrite writeDir(mStoreDiscSet, containingDirFilename);
- writeDir.Open(true /* allow overwriting */);
- containingDir.WriteToStream(writeDir);
+ // Candidate for deletion... open containing directory
+ std::string containingDirFilename;
+ BackupStoreDirectory containingDir;
+ int64_t containingDirSizeInBlocksOrig = 0;
+ {
+ MakeObjectFilename(dir.GetContainerID(), containingDirFilename);
+ std::auto_ptr<RaidFileRead> containingDirStream(
+ RaidFileRead::Open(mStoreDiscSet,
+ containingDirFilename));
+ containingDirSizeInBlocksOrig =
+ containingDirStream->GetDiscUsageInBlocks();
+ containingDir.ReadFromStream(*containingDirStream,
+ IOStream::TimeOutInfinite);
+ }
- // get the disc usage (must do this before commiting it)
- int64_t dirSize = writeDir.GetDiscUsageInBlocks();
+ // Find the entry
+ BackupStoreDirectory::Entry *pdirentry =
+ containingDir.FindEntryByID(dir.GetObjectID());
+ if((pdirentry != 0) && ((pdirentry->GetFlags() & BackupStoreDirectory::Entry::Flags_Deleted) != 0))
+ {
+ // Should be deleted
+ containingDir.DeleteEntry(dir.GetObjectID());
- // Commit directory
- writeDir.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
+ // Is the containing dir now a candidate for deletion?
+ if(containingDir.GetNumberOfEntries() == 0)
+ {
+ rToExamine.push_back(containingDir.GetObjectID());
+ }
- // adjust usage counts for this directory
- if(dirSize > 0)
- {
- int64_t adjust = dirSize - containingDirSizeInBlocksOrig;
- mBlocksUsedDelta += adjust;
- mBlocksInDirectoriesDelta += adjust;
- }
+ // Write revised parent directory
+ RaidFileWrite writeDir(mStoreDiscSet, containingDirFilename);
+ writeDir.Open(true /* allow overwriting */);
+ containingDir.WriteToStream(writeDir);
- // Delete the directory itself
- {
- RaidFileWrite del(mStoreDiscSet, dirFilename);
- del.Delete();
- }
+ // get the disc usage (must do this before commiting it)
+ int64_t dirSize = writeDir.GetDiscUsageInBlocks();
- // And adjust usage counts for the directory that's just been deleted
- mBlocksUsedDelta -= dirSizeInBlocks;
- mBlocksInDirectoriesDelta -= dirSizeInBlocks;
+ // Commit directory
+ writeDir.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
- // Update count
- ++mEmptyDirectoriesDeleted;
- }
+ // adjust usage counts for this directory
+ if(dirSize > 0)
+ {
+ int64_t adjust = dirSize - containingDirSizeInBlocksOrig;
+ mBlocksUsedDelta += adjust;
+ mBlocksInDirectoriesDelta += adjust;
}
- // Remove contents of empty directories
- mEmptyDirectories.clear();
- // Swap in new, so it's examined next time round
- mEmptyDirectories.swap(toExamine);
- }
-
- // Not interrupted
- return false;
-}
+ // Delete the directory itself
+ {
+ RaidFileWrite del(mStoreDiscSet, dirFilename);
+ del.Delete();
+ }
+ BOX_INFO("Housekeeping removed empty deleted dir " <<
+ BOX_FORMAT_OBJECTID(dirId));
+ // And adjust usage counts for the directory that's
+ // just been deleted
+ mBlocksUsedDelta -= dirSizeInBlocks;
+ mBlocksInDirectoriesDelta -= dirSizeInBlocks;
+ // Update count
+ ++mEmptyDirectoriesDeleted;
+ }
+}
diff --git a/bin/bbstored/HousekeepStoreAccount.h b/bin/bbstored/HousekeepStoreAccount.h
index 6c8f251d..5c2a9885 100644
--- a/bin/bbstored/HousekeepStoreAccount.h
+++ b/bin/bbstored/HousekeepStoreAccount.h
@@ -42,6 +42,8 @@ private:
bool ScanDirectory(int64_t ObjectID);
bool DeleteFiles();
bool DeleteEmptyDirectories();
+ void DeleteEmptyDirectory(int64_t dirId,
+ std::vector<int64_t>& rToExamine);
void DeleteFile(int64_t InDirectory, int64_t ObjectID, BackupStoreDirectory &rDirectory, const std::string &rDirectoryFilename, int64_t OriginalDirSizeInBlocks);
private:
@@ -52,6 +54,7 @@ private:
int64_t mSizeInBlocks;
int32_t mMarkNumber;
int32_t mVersionAgeWithinMark; // 0 == current, 1 latest old version, etc
+ bool mIsFlagDeleted; // false for files flagged "Old"
} DelEn;
struct DelEnCompare
diff --git a/bin/bbstored/backupprotocol.txt b/bin/bbstored/backupprotocol.txt
index 62d837ff..3eca514a 100644
--- a/bin/bbstored/backupprotocol.txt
+++ b/bin/bbstored/backupprotocol.txt
@@ -4,7 +4,7 @@
Name Backup
IdentString Box-Backup:v=C
-ServerContextClass BackupContext BackupContext.h
+ServerContextClass BackupStoreContext BackupStoreContext.h
ClientType Filename BackupStoreFilenameClear BackupStoreFilenameClear.h
ServerType Filename BackupStoreFilename BackupStoreFilename.h
@@ -204,6 +204,12 @@ GetBlockIndexByName 35 Command(Success)
# stream of the block index follows the reply if found ID != 0
+UndeleteFile 36 Command(Success)
+ int64 InDirectory
+ int64 ObjectID
+ # will return 0 if the object couldn't be found in the specified directory
+
+
# -------------------------------------------------------------------------------------
# Information commands
# -------------------------------------------------------------------------------------
diff --git a/bin/bbstored/bbstored-config.in b/bin/bbstored/bbstored-config.in
index 33cfb39a..5ad96d50 100755
--- a/bin/bbstored/bbstored-config.in
+++ b/bin/bbstored/bbstored-config.in
@@ -196,7 +196,7 @@ TimeBetweenHousekeeping = 900
Server
{
- PidFile = @localstatedir_expanded@/bbstored.pid
+ PidFile = @localstatedir_expanded@/run/bbstored.pid
User = $username
ListenAddresses = inet:$server
CertificateFile = $certificate
@@ -234,7 +234,7 @@ What you need to do now...
4) Create accounts with bbstoreaccounts
5) Start the backup store daemon with the command
- @bindir_expanded@/bbstored$daemon_args
+ @sbindir_expanded@/bbstored$daemon_args
in /etc/rc.local, or your local equivalent.
===================================================================
diff --git a/bin/bbstored/bbstored.cpp b/bin/bbstored/bbstored.cpp
index 54858dd4..21a9e5f1 100644
--- a/bin/bbstored/bbstored.cpp
+++ b/bin/bbstored/bbstored.cpp
@@ -18,7 +18,7 @@ int main(int argc, const char *argv[])
{
MAINHELPER_START
- Logging::SetProgramName("Box Backup (bbstored)");
+ Logging::SetProgramName("bbstored");
Logging::ToConsole(true);
Logging::ToSyslog (true);