summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/bbstored/BackupCommands.cpp959
-rw-r--r--bin/bbstored/BackupConstants.h21
-rw-r--r--bin/bbstored/BackupStoreContext.cpp1808
-rw-r--r--bin/bbstored/BackupStoreContext.h186
-rw-r--r--bin/bbstored/Makefile.extra9
-rw-r--r--bin/bbstored/backupprotocol.txt235
6 files changed, 0 insertions, 3218 deletions
diff --git a/bin/bbstored/BackupCommands.cpp b/bin/bbstored/BackupCommands.cpp
deleted file mode 100644
index 34f813df..00000000
--- a/bin/bbstored/BackupCommands.cpp
+++ /dev/null
@@ -1,959 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-// Name: BackupCommands.cpp
-// Purpose: Implement commands for the Backup store protocol
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-
-#include "Box.h"
-
-#include <set>
-#include <sstream>
-
-#include "autogen_BackupProtocolServer.h"
-#include "autogen_RaidFileException.h"
-#include "BackupConstants.h"
-#include "BackupStoreContext.h"
-#include "BackupStoreConstants.h"
-#include "BackupStoreDirectory.h"
-#include "BackupStoreException.h"
-#include "BackupStoreFile.h"
-#include "BackupStoreInfo.h"
-#include "BufferedStream.h"
-#include "CollectInBufferStream.h"
-#include "FileStream.h"
-#include "InvisibleTempFileStream.h"
-#include "RaidFileController.h"
-#include "StreamableMemBlock.h"
-
-#include "MemLeakFindOn.h"
-
-#define PROTOCOL_ERROR(code) \
- std::auto_ptr<ProtocolObject>(new BackupProtocolServerError( \
- BackupProtocolServerError::ErrorType, \
- BackupProtocolServerError::code));
-
-#define CHECK_PHASE(phase) \
- if(rContext.GetPhase() != BackupStoreContext::phase) \
- { \
- return PROTOCOL_ERROR(Err_NotInRightProtocolPhase); \
- }
-
-#define CHECK_WRITEABLE_SESSION \
- if(rContext.SessionIsReadOnly()) \
- { \
- return PROTOCOL_ERROR(Err_SessionReadOnly); \
- }
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Version)
-
- // Correct version?
- if(mVersion != BACKUP_STORE_SERVER_VERSION)
- {
- return PROTOCOL_ERROR(Err_WrongVersion);
- }
-
- // Mark the next phase
- rContext.SetPhase(BackupStoreContext::Phase_Login);
-
- // Return our version
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerVersion(BACKUP_STORE_SERVER_VERSION));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Login)
-
- // Check given client ID against the ID in the certificate certificate
- // and that the client actually has an account on this machine
- if(mClientID != rContext.GetClientID())
- {
- BOX_WARNING("Failed login from client ID " <<
- BOX_FORMAT_ACCOUNT(mClientID) <<
- ": wrong certificate for this account");
- return PROTOCOL_ERROR(Err_BadLogin);
- }
-
- if(!rContext.GetClientHasAccount())
- {
- BOX_WARNING("Failed login from client ID " <<
- BOX_FORMAT_ACCOUNT(mClientID) <<
- ": no such account on this server");
- return PROTOCOL_ERROR(Err_BadLogin);
- }
-
- // If we need to write, check that nothing else has got a write lock
- if((mFlags & Flags_ReadOnly) != Flags_ReadOnly)
- {
- // See if the context will get the lock
- if(!rContext.AttemptToGetWriteLock())
- {
- BOX_WARNING("Failed to get write lock for Client ID " <<
- BOX_FORMAT_ACCOUNT(mClientID));
- return PROTOCOL_ERROR(Err_CannotLockStoreForWriting);
- }
-
- // Debug: check we got the lock
- ASSERT(!rContext.SessionIsReadOnly());
- }
-
- // Load the store info
- rContext.LoadStoreInfo();
-
- // Get the last client store marker
- int64_t clientStoreMarker = rContext.GetClientStoreMarker();
-
- // Mark the next phase
- rContext.SetPhase(BackupStoreContext::Phase_Commands);
-
- // Log login
- BOX_NOTICE("Login from Client ID " <<
- BOX_FORMAT_ACCOUNT(mClientID) <<
- " " <<
- (((mFlags & Flags_ReadOnly) != Flags_ReadOnly)
- ?"Read/Write":"Read-only"));
-
- // Get the usage info for reporting to the client
- int64_t blocksUsed = 0, blocksSoftLimit = 0, blocksHardLimit = 0;
- rContext.GetStoreDiscUsageInfo(blocksUsed, blocksSoftLimit, blocksHardLimit);
-
- // Return success
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerLoginConfirmed(clientStoreMarker, blocksUsed, blocksSoftLimit, blocksHardLimit));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- BOX_NOTICE("Session finished for Client ID " <<
- BOX_FORMAT_ACCOUNT(rContext.GetClientID()));
-
- // Let the context know about it
- rContext.ReceivedFinishCommand();
-
- // can be called in any phase
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerFinished);
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerListDirectory::DoCommand(Protocol &, BackupStoreContext &)
-// Purpose: Command to list a directory
-// Created: 2003/09/02
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerListDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Store the listing to a stream
- std::auto_ptr<CollectInBufferStream> stream(new CollectInBufferStream);
-
- 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 PROTOCOL_ERROR(Err_DoesNotExist);
- }
- throw;
- }
-
- stream->SetForReading();
-
- // Get the protocol to send the stream
- rProtocol.SendStreamAfterCommand(stream.release());
-
- return std::auto_ptr<ProtocolObject>(
- new BackupProtocolServerSuccess(mObjectID));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, 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,
- BackupStoreContext::ObjectExists_File))
- {
- return PROTOCOL_ERROR(Err_DiffFromFileDoesNotExist);
- }
- }
-
- // A stream follows, which contains the file
- std::auto_ptr<IOStream> dirstream(rProtocol.ReceiveStream());
-
- // Ask the context to store it
- int64_t id = 0;
- try
- {
- id = rContext.AddFile(*dirstream, mDirectoryObjectID,
- mModificationTime, mAttributesHash, mDiffFromFileID,
- mFilename,
- true /* mark files with same name as old versions */);
- }
- catch(BackupStoreException &e)
- {
- if(e.GetSubType() == BackupStoreException::AddedFileDoesNotVerify)
- {
- return PROTOCOL_ERROR(Err_FileDoesNotVerify);
- }
- else if(e.GetSubType() == BackupStoreException::AddedFileExceedsStorageLimit)
- {
- return PROTOCOL_ERROR(Err_StorageLimitExceeded);
- }
- else
- {
- throw;
- }
- }
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(id));
-}
-
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Check the object exists
- if(!rContext.ObjectExists(mObjectID))
- {
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(NoObject));
- }
-
- // Open the object
- std::auto_ptr<IOStream> object(rContext.OpenObject(mObjectID));
-
- // Stream it to the peer
- rProtocol.SendStreamAfterCommand(object.release());
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Check the objects exist
- if(!rContext.ObjectExists(mObjectID)
- || !rContext.ObjectExists(mInDirectory))
- {
- return PROTOCOL_ERROR(Err_DoesNotExist);
- }
-
- // Get the directory it's in
- const BackupStoreDirectory &rdir(rContext.GetDirectory(mInDirectory));
-
- // Find the object within the directory
- BackupStoreDirectory::Entry *pfileEntry = rdir.FindEntryByID(mObjectID);
- if(pfileEntry == 0)
- {
- return PROTOCOL_ERROR(Err_DoesNotExistInDirectory);
- }
-
- // The result
- std::auto_ptr<IOStream> stream;
-
- // Does this depend on anything?
- if(pfileEntry->GetDependsNewer() != 0)
- {
- // File exists, but is a patch from a new version. Generate the older version.
- std::vector<int64_t> patchChain;
- int64_t id = mObjectID;
- BackupStoreDirectory::Entry *en = 0;
- do
- {
- patchChain.push_back(id);
- en = rdir.FindEntryByID(id);
- if(en == 0)
- {
- BOX_ERROR("Object " <<
- BOX_FORMAT_OBJECTID(mObjectID) <<
- " in dir " <<
- BOX_FORMAT_OBJECTID(mInDirectory) <<
- " for account " <<
- BOX_FORMAT_ACCOUNT(rContext.GetClientID()) <<
- " references object " <<
- BOX_FORMAT_OBJECTID(id) <<
- " which does not exist in dir");
- return PROTOCOL_ERROR(Err_PatchConsistencyError);
- }
- id = en->GetDependsNewer();
- }
- while(en != 0 && id != 0);
-
- // OK! The last entry in the chain is the full file, the others are patches back from it.
- // Open the last one, which is the current from file
- std::auto_ptr<IOStream> from(rContext.OpenObject(patchChain[patchChain.size() - 1]));
-
- // Then, for each patch in the chain, do a combine
- for(int p = ((int)patchChain.size()) - 2; p >= 0; --p)
- {
- // ID of patch
- int64_t patchID = patchChain[p];
-
- // Open it a couple of times
- std::auto_ptr<IOStream> diff(rContext.OpenObject(patchID));
- std::auto_ptr<IOStream> diff2(rContext.OpenObject(patchID));
-
- // Choose a temporary filename for the result of the combination
- std::ostringstream fs;
- fs << rContext.GetStoreRoot() << ".recombinetemp." << p;
- std::string tempFn =
- RaidFileController::DiscSetPathToFileSystemPath(
- rContext.GetStoreDiscSet(), fs.str(),
- p + 16);
-
- // Open the temporary file
- std::auto_ptr<IOStream> combined;
- try
- {
- {
- // Write nastily to allow this to work with gcc 2.x
- std::auto_ptr<IOStream> t(
- new InvisibleTempFileStream(
- tempFn.c_str(),
- O_RDWR | O_CREAT |
- O_EXCL | O_BINARY |
- O_TRUNC));
- combined = t;
- }
- }
- catch(...)
- {
- // Make sure it goes
- ::unlink(tempFn.c_str());
- throw;
- }
-
- // Do the combining
- BackupStoreFile::CombineFile(*diff, *diff2, *from, *combined);
-
- // Move to the beginning of the combined file
- combined->Seek(0, IOStream::SeekType_Absolute);
-
- // Then shuffle round for the next go
- if (from.get()) from->Close();
- from = combined;
- }
-
- // Now, from contains a nice file to send to the client. Reorder it
- {
- // Write nastily to allow this to work with gcc 2.x
- std::auto_ptr<IOStream> t(BackupStoreFile::ReorderFileToStreamOrder(from.get(), true /* take ownership */));
- stream = t;
- }
-
- // Release from file to avoid double deletion
- from.release();
- }
- else
- {
- // Simple case: file already exists on disc ready to go
-
- // Open the object
- std::auto_ptr<IOStream> object(rContext.OpenObject(mObjectID));
- BufferedStream buf(*object);
-
- // Verify it
- if(!BackupStoreFile::VerifyEncodedFileFormat(buf))
- {
- return PROTOCOL_ERROR(Err_FileDoesNotVerify);
- }
-
- // Reset stream -- seek to beginning
- object->Seek(0, IOStream::SeekType_Absolute);
-
- // Reorder the stream/file into stream order
- {
- // Write nastily to allow this to work with gcc 2.x
- std::auto_ptr<IOStream> t(BackupStoreFile::ReorderFileToStreamOrder(object.get(), true /* take ownership */));
- stream = t;
- }
-
- // Object will be deleted when the stream is deleted,
- // so can release the object auto_ptr here to avoid
- // premature deletion
- object.release();
- }
-
- // Stream the reordered stream to the peer
- rProtocol.SendStreamAfterCommand(stream.get());
-
- // Don't delete the stream here
- stream.release();
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerCreateDirectory::DoCommand(Protocol &, BackupStoreContext &)
-// Purpose: Create directory command
-// Created: 2003/09/04
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerCreateDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Get the stream containing the attributes
- std::auto_ptr<IOStream> attrstream(rProtocol.ReceiveStream());
- // Collect the attributes -- do this now so no matter what the outcome,
- // the data has been absorbed.
- StreamableMemBlock attr;
- attr.Set(*attrstream, rProtocol.GetTimeout());
-
- // Check to see if the hard limit has been exceeded
- if(rContext.HardLimitExceeded())
- {
- // Won't allow creation if the limit has been exceeded
- return PROTOCOL_ERROR(Err_StorageLimitExceeded);
- }
-
- bool alreadyExists = false;
- int64_t id = rContext.AddDirectory(mContainingDirectoryID, mDirectoryName, attr, mAttributesModTime, alreadyExists);
-
- if(alreadyExists)
- {
- return PROTOCOL_ERROR(Err_DirectoryAlreadyExists);
- }
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(id));
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerChangeDirAttributes::DoCommand(Protocol &, BackupStoreContext &)
-// Purpose: Change attributes on directory
-// Created: 2003/09/06
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerChangeDirAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Get the stream containing the attributes
- std::auto_ptr<IOStream> attrstream(rProtocol.ReceiveStream());
- // Collect the attributes -- do this now so no matter what the outcome,
- // the data has been absorbed.
- StreamableMemBlock attr;
- attr.Set(*attrstream, rProtocol.GetTimeout());
-
- // Get the context to do it's magic
- rContext.ChangeDirAttributes(mObjectID, attr, mAttributesModTime);
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerSetReplacementFileAttributes::DoCommand(Protocol &, BackupStoreContext &)
-// Purpose: Change attributes on directory
-// Created: 2003/09/06
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerSetReplacementFileAttributes::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Get the stream containing the attributes
- std::auto_ptr<IOStream> attrstream(rProtocol.ReceiveStream());
- // Collect the attributes -- do this now so no matter what the outcome,
- // the data has been absorbed.
- StreamableMemBlock attr;
- attr.Set(*attrstream, rProtocol.GetTimeout());
-
- // Get the context to do it's magic
- int64_t objectID = 0;
- if(!rContext.ChangeFileAttributes(mFilename, mInDirectory, attr, mAttributesHash, objectID))
- {
- // Didn't exist
- return PROTOCOL_ERROR(Err_DoesNotExist);
- }
-
- // Tell the caller what the file was
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(objectID));
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &, BackupStoreContext &)
-// Purpose: Delete a file
-// Created: 2003/10/21
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerDeleteFile::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Context handles this
- int64_t objectID = 0;
- rContext.DeleteFile(mFilename, mInDirectory, objectID);
-
- // return the object ID or zero for not found
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(objectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Check it's not asking for the root directory to be deleted
- if(mObjectID == BACKUPSTORE_ROOT_DIRECTORY_ID)
- {
- return PROTOCOL_ERROR(Err_CannotDeleteRoot);
- }
-
- // Context handles this
- try
- {
- rContext.DeleteDirectory(mObjectID);
- }
- catch (BackupStoreException &e)
- {
- if(e.GetSubType() == BackupStoreException::MultiplyReferencedObject)
- {
- return PROTOCOL_ERROR(Err_MultiplyReferencedObject);
- }
-
- throw;
- }
-
- // return the object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &, BackupStoreContext &)
-// Purpose: Undelete a directory
-// Created: 23/11/03
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<ProtocolObject> BackupProtocolServerUndeleteDirectory::DoCommand(BackupProtocolServer &rProtocol, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Check it's not asking for the root directory to be deleted
- if(mObjectID == BACKUPSTORE_ROOT_DIRECTORY_ID)
- {
- return PROTOCOL_ERROR(Err_CannotDeleteRoot);
- }
-
- // Context handles this
- rContext.DeleteDirectory(mObjectID, true /* undelete */);
-
- // return the object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Set the marker
- rContext.SetClientStoreMarker(mClientStoreMarker);
-
- // return store marker set
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mClientStoreMarker));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
- CHECK_WRITEABLE_SESSION
-
- // Let context do this, but modify error reporting on exceptions...
- try
- {
- rContext.MoveObject(mObjectID, mMoveFromDirectory, mMoveToDirectory,
- mNewFilename, (mFlags & Flags_MoveAllWithSameName) == Flags_MoveAllWithSameName,
- (mFlags & Flags_AllowMoveOverDeletedObject) == Flags_AllowMoveOverDeletedObject);
- }
- catch(BackupStoreException &e)
- {
- if(e.GetSubType() == BackupStoreException::CouldNotFindEntryInDirectory)
- {
- return PROTOCOL_ERROR(Err_DoesNotExist);
- }
- else if(e.GetSubType() == BackupStoreException::NameAlreadyExistsInDirectory)
- {
- return PROTOCOL_ERROR(Err_TargetNameExists);
- }
- else
- {
- throw;
- }
- }
-
- // Return the object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Create a stream for the list of filenames
- std::auto_ptr<CollectInBufferStream> stream(new CollectInBufferStream);
-
- // Object and directory IDs
- int64_t objectID = mObjectID;
- int64_t dirID = mContainingDirectoryID;
-
- // Data to return in the reply
- int32_t numNameElements = 0;
- int16_t objectFlags = 0;
- int64_t modTime = 0;
- uint64_t attrModHash = 0;
- bool haveModTimes = false;
-
- do
- {
- // Check the directory really exists
- if(!rContext.ObjectExists(dirID, BackupStoreContext::ObjectExists_Directory))
- {
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerObjectName(BackupProtocolServerObjectName::NumNameElements_ObjectDoesntExist, 0, 0, 0));
- }
-
- // Load up the directory
- const BackupStoreDirectory &rdir(rContext.GetDirectory(dirID));
-
- // Find the element in this directory and store it's name
- if(objectID != ObjectID_DirectoryOnly)
- {
- const BackupStoreDirectory::Entry *en = rdir.FindEntryByID(objectID);
-
- // If this can't be found, then there is a problem... tell the caller it can't be found
- if(en == 0)
- {
- // Abort!
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerObjectName(BackupProtocolServerObjectName::NumNameElements_ObjectDoesntExist, 0, 0, 0));
- }
-
- // Store flags?
- if(objectFlags == 0)
- {
- objectFlags = en->GetFlags();
- }
-
- // Store modification times?
- if(!haveModTimes)
- {
- modTime = en->GetModificationTime();
- attrModHash = en->GetAttributesHash();
- haveModTimes = true;
- }
-
- // Store the name in the stream
- en->GetName().WriteToStream(*stream);
-
- // Count of name elements
- ++numNameElements;
- }
-
- // Setup for next time round
- objectID = dirID;
- dirID = rdir.GetContainerID();
-
- } while(objectID != 0 && objectID != BACKUPSTORE_ROOT_DIRECTORY_ID);
-
- // Stream to send?
- if(numNameElements > 0)
- {
- // Get the stream ready to go
- stream->SetForReading();
- // Tell the protocol to send the stream
- rProtocol.SendStreamAfterCommand(stream.release());
- }
-
- // Make reply
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerObjectName(numNameElements, modTime, attrModHash, objectFlags));
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Open the file
- std::auto_ptr<IOStream> stream(rContext.OpenObject(mObjectID));
-
- // Move the file pointer to the block index
- BackupStoreFile::MoveStreamPositionToBlockIndex(*stream);
-
- // Return the stream to the client
- rProtocol.SendStreamAfterCommand(stream.release());
-
- // Return the object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(mObjectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Get the directory
- const BackupStoreDirectory &dir(rContext.GetDirectory(mInDirectory));
-
- // Find the latest object ID within it which has the same name
- int64_t objectID = 0;
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *en = 0;
- while((en = i.Next(BackupStoreDirectory::Entry::Flags_File)) != 0)
- {
- if(en->GetName() == mFilename)
- {
- // Store the ID, if it's a newer ID than the last one
- if(en->GetObjectID() > objectID)
- {
- objectID = en->GetObjectID();
- }
- }
- }
-
- // Found anything?
- if(objectID == 0)
- {
- // No... return a zero object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(0));
- }
-
- // Open the file
- std::auto_ptr<IOStream> stream(rContext.OpenObject(objectID));
-
- // Move the file pointer to the block index
- BackupStoreFile::MoveStreamPositionToBlockIndex(*stream);
-
- // Return the stream to the client
- rProtocol.SendStreamAfterCommand(stream.release());
-
- // Return the object ID
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerSuccess(objectID));
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- // Get store info from context
- const BackupStoreInfo &rinfo(rContext.GetBackupStoreInfo());
-
- // Find block size
- RaidFileController &rcontroller(RaidFileController::GetController());
- RaidFileDiscSet &rdiscSet(rcontroller.GetDiscSet(rinfo.GetDiscSetNumber()));
-
- // Return info
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerAccountUsage(
- rinfo.GetBlocksUsed(),
- rinfo.GetBlocksInOldFiles(),
- rinfo.GetBlocksInDeletedFiles(),
- rinfo.GetBlocksInDirectories(),
- rinfo.GetBlocksSoftLimit(),
- rinfo.GetBlocksHardLimit(),
- rdiscSet.GetBlockSize()
- ));
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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, BackupStoreContext &rContext)
-{
- CHECK_PHASE(Phase_Commands)
-
- //
- // NOOP
- //
- return std::auto_ptr<ProtocolObject>(new BackupProtocolServerIsAlive());
-}
diff --git a/bin/bbstored/BackupConstants.h b/bin/bbstored/BackupConstants.h
deleted file mode 100644
index 19d06a15..00000000
--- a/bin/bbstored/BackupConstants.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-// Name: BackupConstants.h
-// Purpose: Constants for the backup server and client
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-
-#ifndef BACKUPCONSTANTS__H
-#define BACKUPCONSTANTS__H
-
-// 15 minutes to timeout (milliseconds)
-#define BACKUP_STORE_TIMEOUT (15*60*1000)
-
-// Should the store daemon convert files to Raid immediately?
-#define BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY true
-
-#endif // BACKUPCONSTANTS__H
-
-
diff --git a/bin/bbstored/BackupStoreContext.cpp b/bin/bbstored/BackupStoreContext.cpp
deleted file mode 100644
index 9a98decf..00000000
--- a/bin/bbstored/BackupStoreContext.cpp
+++ /dev/null
@@ -1,1808 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-// Name: BackupStoreContext.cpp
-// Purpose: Context for backup store server
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-
-#include "Box.h"
-
-#include <stdio.h>
-
-#include "BackupConstants.h"
-#include "BackupStoreContext.h"
-#include "BackupStoreDaemon.h"
-#include "BackupStoreDirectory.h"
-#include "BackupStoreException.h"
-#include "BackupStoreFile.h"
-#include "BackupStoreInfo.h"
-#include "BackupStoreObjectMagic.h"
-#include "BufferedStream.h"
-#include "BufferedWriteStream.h"
-#include "FileStream.h"
-#include "InvisibleTempFileStream.h"
-#include "RaidFileController.h"
-#include "RaidFileRead.h"
-#include "RaidFileWrite.h"
-#include "StoreStructure.h"
-
-#include "MemLeakFindOn.h"
-
-
-// Maximum number of directories to keep in the cache
-// When the cache is bigger than this, everything gets
-// deleted.
-#ifdef BOX_RELEASE_BUILD
- #define MAX_CACHE_SIZE 32
-#else
- #define MAX_CACHE_SIZE 2
-#endif
-
-// Allow the housekeeping process 4 seconds to release an account
-#define MAX_WAIT_FOR_HOUSEKEEPING_TO_RELEASE_ACCOUNT 4
-
-// Maximum amount of store info updates before it's actually saved to disc.
-#define STORE_INFO_SAVE_DELAY 96
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::BackupStoreContext()
-// Purpose: Constructor
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-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),
- mpTestHook(NULL)
-{
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::~BackupStoreContext()
-// Purpose: Destructor
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-BackupStoreContext::~BackupStoreContext()
-{
- // Delete the objects in the cache
- for(std::map<int64_t, BackupStoreDirectory*>::iterator i(mDirectoryCache.begin()); i != mDirectoryCache.end(); ++i)
- {
- delete (i->second);
- }
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::CleanUp()
-// Purpose: Clean up after a connection
-// Created: 16/12/03
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::CleanUp()
-{
- // Make sure the store info is saved, if it has been loaded, isn't read only and has been modified
- if(mapStoreInfo.get() && !(mapStoreInfo->IsReadOnly()) &&
- mapStoreInfo->IsModified())
- {
- mapStoreInfo->Save();
- }
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::ReceivedFinishCommand()
-// Purpose: Called when the finish command is received by the protocol
-// Created: 16/12/03
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::ReceivedFinishCommand()
-{
- if(!mReadOnly && mapStoreInfo.get())
- {
- // Save the store info, not delayed
- SaveStoreInfo(false);
- }
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::AttemptToGetWriteLock()
-{
- // Make the filename of the write lock file
- std::string writeLockFile;
- StoreStructure::MakeWriteLockFilename(mStoreRoot, mStoreDiscSet, writeLockFile);
-
- // Request the lock
- bool gotLock = mWriteLock.TryAndGetLock(writeLockFile.c_str(), 0600 /* restrictive file permissions */);
-
- if(!gotLock)
- {
- // The housekeeping process might have the thing open -- ask it to stop
- char msg[256];
- int msgLen = sprintf(msg, "r%x\n", mClientID);
- // Send message
- mrDaemon.SendMessageToHousekeepingProcess(msg, msgLen);
-
- // Then try again a few times
- int tries = MAX_WAIT_FOR_HOUSEKEEPING_TO_RELEASE_ACCOUNT;
- do
- {
- ::sleep(1 /* second */);
- --tries;
- gotLock = mWriteLock.TryAndGetLock(writeLockFile.c_str(), 0600 /* restrictive file permissions */);
-
- } while(!gotLock && tries > 0);
- }
-
- if(gotLock)
- {
- // Got the lock, mark as not read only
- mReadOnly = false;
- }
-
- return gotLock;
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::LoadStoreInfo()
-// Purpose: Load the store info from disc
-// Created: 2003/09/03
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::LoadStoreInfo()
-{
- if(mapStoreInfo.get() != 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoAlreadyLoaded)
- }
-
- // Load it up!
- std::auto_ptr<BackupStoreInfo> i(BackupStoreInfo::Load(mClientID, mStoreRoot, mStoreDiscSet, mReadOnly));
-
- // Check it
- if(i->GetAccountID() != mClientID)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoForWrongAccount)
- }
-
- // Keep the pointer to it
- mapStoreInfo = i;
-
- BackupStoreAccountDatabase::Entry account(mClientID, mStoreDiscSet);
-
- // try to load the reference count database
- try
- {
- mapRefCount = BackupStoreRefCountDatabase::Load(account, false);
- }
- catch(BoxException &e)
- {
- BOX_WARNING("Reference count database is missing or corrupted, "
- "creating a new one, expect housekeeping to find and "
- "fix problems with reference counts later.");
-
- BackupStoreRefCountDatabase::CreateForRegeneration(account);
- mapRefCount = BackupStoreRefCountDatabase::Load(account, false);
- }
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::SaveStoreInfo(bool)
-// Purpose: Potentially delayed saving of the store info
-// Created: 16/12/03
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::SaveStoreInfo(bool AllowDelay)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- // Can delay saving it a little while?
- if(AllowDelay)
- {
- --mSaveStoreInfoDelay;
- if(mSaveStoreInfoDelay > 0)
- {
- return;
- }
- }
-
- // Want to save now
- mapStoreInfo->Save();
-
- // Set count for next delay
- mSaveStoreInfoDelay = STORE_INFO_SAVE_DELAY;
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutput, bool EnsureDirectoryExists)
-{
- // Delegate to utility function
- StoreStructure::MakeObjectFilename(ObjectID, mStoreRoot, mStoreDiscSet, rOutput, EnsureDirectoryExists);
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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.
-// Private version of this, which returns non-const directories.
-// Created: 2003/09/02
-//
-// --------------------------------------------------------------------------
-BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID)
-{
- // Get the filename
- std::string filename;
- MakeObjectFilename(ObjectID, filename);
-
- // Already in cache?
- std::map<int64_t, BackupStoreDirectory*>::iterator item(mDirectoryCache.find(ObjectID));
- if(item != mDirectoryCache.end())
- {
- // Check the revision ID of the file -- does it need refreshing?
- int64_t revID = 0;
- if(!RaidFileRead::FileExists(mStoreDiscSet, filename, &revID))
- {
- THROW_EXCEPTION(BackupStoreException, DirectoryHasBeenDeleted)
- }
-
- 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);
- }
-
- // Need to load it up
-
- // First check to see if the cache is too big
- if(mDirectoryCache.size() > MAX_CACHE_SIZE)
- {
- // Very simple. Just delete everything!
- for(std::map<int64_t, BackupStoreDirectory*>::iterator i(mDirectoryCache.begin()); i != mDirectoryCache.end(); ++i)
- {
- delete (i->second);
- }
- mDirectoryCache.clear();
- }
-
- // Get a RaidFileRead to read it
- int64_t revID = 0;
- std::auto_ptr<RaidFileRead> objectFile(RaidFileRead::Open(mStoreDiscSet, filename, &revID));
- ASSERT(revID != 0);
-
- // New directory object
- std::auto_ptr<BackupStoreDirectory> dir(new BackupStoreDirectory);
-
- // Read it from the stream, then set it's revision ID
- BufferedStream buf(*objectFile);
- dir->ReadFromStream(buf, IOStream::TimeOutInfinite);
- dir->SetRevisionID(revID);
-
- // Make sure the size of the directory is available for writing the dir back
- int64_t dirSize = objectFile->GetDiscUsageInBlocks();
- ASSERT(dirSize > 0);
- dir->SetUserInfo1_SizeInBlocks(dirSize);
-
- // Store in cache
- BackupStoreDirectory *pdir = dir.release();
- try
- {
- mDirectoryCache[ObjectID] = pdir;
- }
- catch(...)
- {
- delete pdir;
- throw;
- }
-
- // Return it
- return *pdir;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::AllocateObjectID()
-// Purpose: Allocate a new object ID, tolerant of failures to save store info
-// Created: 16/12/03
-//
-// --------------------------------------------------------------------------
-int64_t BackupStoreContext::AllocateObjectID()
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- // Given that the store info may not be saved for STORE_INFO_SAVE_DELAY
- // times after it has been updated, this is a reasonable number of times
- // to try for finding an unused ID.
- // (Sizes used in the store info are fixed by the housekeeping process)
- int retryLimit = (STORE_INFO_SAVE_DELAY * 2);
-
- while(retryLimit > 0)
- {
- // Attempt to allocate an ID from the store
- int64_t id = mapStoreInfo->AllocateObjectID();
-
- // Generate filename
- std::string filename;
- MakeObjectFilename(id, filename);
- // Check it doesn't exist
- if(!RaidFileRead::FileExists(mStoreDiscSet, filename))
- {
- // Success!
- return id;
- }
-
- // Decrement retry count, and try again
- --retryLimit;
-
- // Mark that the store info should be saved as soon as possible
- mSaveStoreInfoDelay = 0;
-
- BOX_WARNING("When allocating object ID, found that " <<
- BOX_FORMAT_OBJECTID(id) << " is already in use");
- }
-
- THROW_EXCEPTION(BackupStoreException, CouldNotFindUnusedIDDuringAllocation)
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::AddFile(IOStream &rFile, int64_t InDirectory,
- int64_t ModificationTime, int64_t AttributesHash,
- int64_t DiffFromFileID, const BackupStoreFilename &rFilename,
- bool MarkFileWithSameNameAsOldVersions)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- // This is going to be a bit complex to make sure it copes OK
- // with things going wrong.
- // The only thing which isn't safe is incrementing the object ID
- // and keeping the blocks used entirely accurate -- but these
- // aren't big problems if they go horribly wrong. The sizes will
- // be corrected the next time the account has a housekeeping run,
- // and the object ID allocation code is tolerant of missed IDs.
- // (the info is written lazily, so these are necessary)
-
- // Get the directory we want to modify
- BackupStoreDirectory &dir(GetDirectoryInternal(InDirectory));
-
- // Allocate the next ID
- int64_t id = AllocateObjectID();
-
- // Stream the file to disc
- std::string fn;
- MakeObjectFilename(id, fn, true /* make sure the directory it's in exists */);
- int64_t newObjectBlocksUsed = 0;
- RaidFileWrite *ppreviousVerStoreFile = 0;
- bool reversedDiffIsCompletelyDifferent = false;
- int64_t oldVersionNewBlocksUsed = 0;
- try
- {
- RaidFileWrite storeFile(mStoreDiscSet, fn);
- storeFile.Open(false /* no overwriting */);
-
- // size adjustment from use of patch in old file
- int64_t spaceSavedByConversionToPatch = 0;
-
- // Diff or full file?
- if(DiffFromFileID == 0)
- {
- // A full file, just store to disc
- if(!rFile.CopyStreamTo(storeFile, BACKUP_STORE_TIMEOUT))
- {
- THROW_EXCEPTION(BackupStoreException, ReadFileFromStreamTimedOut)
- }
- }
- else
- {
- // Check that the diffed from ID actually exists in the directory
- if(dir.FindEntryByID(DiffFromFileID) == 0)
- {
- THROW_EXCEPTION(BackupStoreException, DiffFromIDNotFoundInDirectory)
- }
-
- // Diff file, needs to be recreated.
- // Choose a temporary filename.
- std::string tempFn(RaidFileController::DiscSetPathToFileSystemPath(mStoreDiscSet, fn + ".difftemp",
- 1 /* NOT the same disc as the write file, to avoid using lots of space on the same disc unnecessarily */));
-
- try
- {
- // Open it twice
-#ifdef WIN32
- InvisibleTempFileStream diff(tempFn.c_str(),
- O_RDWR | O_CREAT | O_BINARY);
- InvisibleTempFileStream diff2(tempFn.c_str(),
- O_RDWR | O_BINARY);
-#else
- FileStream diff(tempFn.c_str(), O_RDWR | O_CREAT | O_EXCL);
- FileStream diff2(tempFn.c_str(), O_RDONLY);
-
- // Unlink it immediately, so it definitely goes away
- if(::unlink(tempFn.c_str()) != 0)
- {
- THROW_EXCEPTION(CommonException, OSFileError);
- }
-#endif
-
- // Stream the incoming diff to this temporary file
- if(!rFile.CopyStreamTo(diff, BACKUP_STORE_TIMEOUT))
- {
- THROW_EXCEPTION(BackupStoreException, ReadFileFromStreamTimedOut)
- }
-
- // Verify the diff
- diff.Seek(0, IOStream::SeekType_Absolute);
- if(!BackupStoreFile::VerifyEncodedFileFormat(diff))
- {
- THROW_EXCEPTION(BackupStoreException, AddedFileDoesNotVerify)
- }
-
- // Seek to beginning of diff file
- diff.Seek(0, IOStream::SeekType_Absolute);
-
- // Filename of the old version
- std::string oldVersionFilename;
- MakeObjectFilename(DiffFromFileID, oldVersionFilename, false /* no need to make sure the directory it's in exists */);
-
- // Reassemble that diff -- open previous file, and combine the patch and file
- std::auto_ptr<RaidFileRead> from(RaidFileRead::Open(mStoreDiscSet, oldVersionFilename));
- BackupStoreFile::CombineFile(diff, diff2, *from, storeFile);
-
- // Then... reverse the patch back (open the from file again, and create a write file to overwrite it)
- std::auto_ptr<RaidFileRead> from2(RaidFileRead::Open(mStoreDiscSet, oldVersionFilename));
- ppreviousVerStoreFile = new RaidFileWrite(mStoreDiscSet, oldVersionFilename);
- ppreviousVerStoreFile->Open(true /* allow overwriting */);
- from->Seek(0, IOStream::SeekType_Absolute);
- diff.Seek(0, IOStream::SeekType_Absolute);
- BackupStoreFile::ReverseDiffFile(diff, *from, *from2, *ppreviousVerStoreFile,
- DiffFromFileID, &reversedDiffIsCompletelyDifferent);
-
- // Store disc space used
- oldVersionNewBlocksUsed = ppreviousVerStoreFile->GetDiscUsageInBlocks();
-
- // And make a space adjustment for the size calculation
- spaceSavedByConversionToPatch =
- from->GetDiscUsageInBlocks() -
- oldVersionNewBlocksUsed;
-
- // Everything cleans up here...
- }
- catch(...)
- {
- // Be very paranoid about deleting this temp file -- we could only leave a zero byte file anyway
- ::unlink(tempFn.c_str());
- throw;
- }
- }
-
- // Get the blocks used
- newObjectBlocksUsed = storeFile.GetDiscUsageInBlocks();
-
- // Exceeds the hard limit?
- int64_t newBlocksUsed = mapStoreInfo->GetBlocksUsed() +
- newObjectBlocksUsed - spaceSavedByConversionToPatch;
- if(newBlocksUsed > mapStoreInfo->GetBlocksHardLimit())
- {
- THROW_EXCEPTION(BackupStoreException, AddedFileExceedsStorageLimit)
- // The store file will be deleted automatically by the RaidFile object
- }
-
- // Commit the file
- storeFile.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
- }
- catch(...)
- {
- // Delete any previous version store file
- if(ppreviousVerStoreFile != 0)
- {
- delete ppreviousVerStoreFile;
- ppreviousVerStoreFile = 0;
- }
-
- throw;
- }
-
- // Verify the file -- only necessary for non-diffed versions
- // NOTE: No need to catch exceptions and delete ppreviousVerStoreFile, because
- // in the non-diffed code path it's never allocated.
- if(DiffFromFileID == 0)
- {
- std::auto_ptr<RaidFileRead> checkFile(RaidFileRead::Open(mStoreDiscSet, fn));
- if(!BackupStoreFile::VerifyEncodedFileFormat(*checkFile))
- {
- // Error! Delete the file
- RaidFileWrite del(mStoreDiscSet, fn);
- del.Delete();
-
- // Exception
- THROW_EXCEPTION(BackupStoreException, AddedFileDoesNotVerify)
- }
- }
-
- // Modify the directory -- first make all files with the same name
- // marked as an old version
- int64_t blocksInOldFiles = 0;
- try
- {
- if(MarkFileWithSameNameAsOldVersions)
- {
- BackupStoreDirectory::Iterator i(dir);
-
- BackupStoreDirectory::Entry *e = 0;
- while((e = i.Next()) != 0)
- {
- // First, check it's not an old version (cheaper comparison)
- if(! e->IsOld())
- {
- // Compare name
- if(e->GetName() == rFilename)
- {
- // Check that it's definately not an old version
- ASSERT((e->GetFlags() & BackupStoreDirectory::Entry::Flags_OldVersion) == 0);
- // Set old version flag
- e->AddFlags(BackupStoreDirectory::Entry::Flags_OldVersion);
- // Can safely do this, because we know we won't be here if it's already
- // an old version
- blocksInOldFiles += e->GetSizeInBlocks();
- }
- }
- }
- }
-
- // Then the new entry
- BackupStoreDirectory::Entry *pnewEntry = dir.AddEntry(rFilename,
- ModificationTime, id, newObjectBlocksUsed,
- BackupStoreDirectory::Entry::Flags_File,
- AttributesHash);
-
- // Adjust for the patch back stuff?
- if(DiffFromFileID != 0)
- {
- // Get old version entry
- BackupStoreDirectory::Entry *poldEntry = dir.FindEntryByID(DiffFromFileID);
- ASSERT(poldEntry != 0);
-
- // Adjust dependency info of file?
- if(!reversedDiffIsCompletelyDifferent)
- {
- poldEntry->SetDependsNewer(id);
- pnewEntry->SetDependsOlder(DiffFromFileID);
- }
-
- // Adjust size of old entry
- int64_t oldSize = poldEntry->GetSizeInBlocks();
- poldEntry->SetSizeInBlocks(oldVersionNewBlocksUsed);
-
- // And adjust blocks used count, for later adjustment
- newObjectBlocksUsed += (oldVersionNewBlocksUsed - oldSize);
- blocksInOldFiles += (oldVersionNewBlocksUsed - oldSize);
- }
-
- // Write the directory back to disc
- SaveDirectory(dir, InDirectory);
-
- // Commit the old version's new patched version, now that the directory safely reflects
- // the state of the files on disc.
- if(ppreviousVerStoreFile != 0)
- {
- ppreviousVerStoreFile->Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
- delete ppreviousVerStoreFile;
- ppreviousVerStoreFile = 0;
- }
- }
- catch(...)
- {
- // Back out on adding that file
- RaidFileWrite del(mStoreDiscSet, fn);
- del.Delete();
-
- // Remove this entry from the cache
- RemoveDirectoryFromCache(InDirectory);
-
- // Delete any previous version store file
- if(ppreviousVerStoreFile != 0)
- {
- delete ppreviousVerStoreFile;
- ppreviousVerStoreFile = 0;
- }
-
- // Don't worry about the incremented number in the store info
- throw;
- }
-
- // Check logic
- ASSERT(ppreviousVerStoreFile == 0);
-
- // Modify the store info
-
- if(DiffFromFileID == 0)
- {
- mapStoreInfo->AdjustNumFiles(1);
- }
- else
- {
- mapStoreInfo->AdjustNumOldFiles(1);
- }
-
- mapStoreInfo->ChangeBlocksUsed(newObjectBlocksUsed);
- mapStoreInfo->ChangeBlocksInCurrentFiles(newObjectBlocksUsed -
- blocksInOldFiles);
- mapStoreInfo->ChangeBlocksInOldFiles(blocksInOldFiles);
-
- // Increment reference count on the new directory to one
- mapRefCount->AddReference(id);
-
- // Save the store info -- can cope if this exceptions because infomation
- // will be rebuilt by housekeeping, and ID allocation can recover.
- SaveStoreInfo(false);
-
- // Return the ID to the caller
- return id;
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// 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::DeleteFile(const BackupStoreFilename &rFilename, int64_t InDirectory, int64_t &rObjectIDOut)
-{
- // Essential checks!
- if(mapStoreInfo.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;
- rObjectIDOut = 0; // not found
-
- // Count of deleted blocks
- int64_t blocksDel = 0;
-
- try
- {
- // Iterate through directory, only looking at files which haven't been deleted
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *e = 0;
- while((e = i.Next(BackupStoreDirectory::Entry::Flags_File,
- BackupStoreDirectory::Entry::Flags_Deleted)) != 0)
- {
- // Compare name
- if(e->GetName() == rFilename)
- {
- // Check that it's definately not already deleted
- ASSERT((e->GetFlags() & BackupStoreDirectory::Entry::Flags_Deleted) == 0);
- // Set deleted flag
- e->AddFlags(BackupStoreDirectory::Entry::Flags_Deleted);
- // Mark as made a change
- madeChanges = true;
- // Can safely do this, because we know we won't be here if it's already
- // an old version
- blocksDel += e->GetSizeInBlocks();
- // Is this the last version?
- if((e->GetFlags() & BackupStoreDirectory::Entry::Flags_OldVersion) == 0)
- {
- // Yes. It's been found.
- rObjectIDOut = e->GetObjectID();
- fileExisted = true;
- }
- }
- }
-
- // Save changes?
- if(madeChanges)
- {
- // Save the directory back
- SaveDirectory(dir, InDirectory);
-
- // Modify the store info, and write
- // It definitely wasn't an old or deleted version
- mapStoreInfo->AdjustNumFiles(-1);
- mapStoreInfo->AdjustNumDeletedFiles(1);
- mapStoreInfo->ChangeBlocksInDeletedFiles(blocksDel);
-
- SaveStoreInfo(false);
- }
- }
- catch(...)
- {
- RemoveDirectoryFromCache(InDirectory);
- throw;
- }
-
- return fileExisted;
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::UndeleteFile(int64_t, int64_t)
-// Purpose: Undeletes a file, if it exists, returning true if
-// the file existed.
-// Created: 2003/10/21
-//
-// --------------------------------------------------------------------------
-bool BackupStoreContext::UndeleteFile(int64_t ObjectID, int64_t InDirectory)
-{
- // Essential checks!
- if(mapStoreInfo.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
- mapStoreInfo->ChangeBlocksInDeletedFiles(blocksDel);
-
- // Maybe postponed save of store info
- SaveStoreInfo();
- }
- }
- catch(...)
- {
- RemoveDirectoryFromCache(InDirectory);
- throw;
- }
-
- return fileExisted;
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::RemoveDirectoryFromCache(int64_t)
-// Purpose: Remove directory from cache
-// Created: 2003/09/04
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::RemoveDirectoryFromCache(int64_t ObjectID)
-{
- std::map<int64_t, BackupStoreDirectory*>::iterator item(mDirectoryCache.find(ObjectID));
- if(item != mDirectoryCache.end())
- {
- // Delete this cached object
- delete item->second;
- // Erase the entry form the map
- mDirectoryCache.erase(item);
- }
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::SaveDirectory(BackupStoreDirectory &, int64_t)
-// Purpose: Save directory back to disc, update time in cache
-// Created: 2003/09/04
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(rDir.GetObjectID() != ObjectID)
- {
- THROW_EXCEPTION(BackupStoreException, Internal)
- }
-
- try
- {
- // Write to disc, adjust size in store info
- std::string dirfn;
- MakeObjectFilename(ObjectID, dirfn);
- {
- RaidFileWrite writeDir(mStoreDiscSet, dirfn);
- writeDir.Open(true /* allow overwriting */);
-
- BufferedWriteStream buffer(writeDir);
- rDir.WriteToStream(buffer);
- buffer.Flush();
-
- // get the disc usage (must do this before commiting it)
- int64_t dirSize = writeDir.GetDiscUsageInBlocks();
-
- // Commit directory
- writeDir.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
-
- // Make sure the size of the directory is available for writing the dir back
- ASSERT(dirSize > 0);
- int64_t sizeAdjustment = dirSize - rDir.GetUserInfo1_SizeInBlocks();
- mapStoreInfo->ChangeBlocksUsed(sizeAdjustment);
- mapStoreInfo->ChangeBlocksInDirectories(sizeAdjustment);
- // Update size stored in directory
- rDir.SetUserInfo1_SizeInBlocks(dirSize);
- }
- // Refresh revision ID in cache
- {
- int64_t revid = 0;
- if(!RaidFileRead::FileExists(mStoreDiscSet, dirfn, &revid))
- {
- THROW_EXCEPTION(BackupStoreException, Internal)
- }
- rDir.SetRevisionID(revid);
- }
- }
- catch(...)
- {
- // Remove it from the cache if anything went wrong
- RemoveDirectoryFromCache(ObjectID);
- throw;
- }
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::AddDirectory(int64_t InDirectory, const BackupStoreFilename &rFilename, const StreamableMemBlock &Attributes, int64_t AttributesModTime, bool &rAlreadyExists)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- // Flags as not already existing
- rAlreadyExists = false;
-
- // Get the directory we want to modify
- BackupStoreDirectory &dir(GetDirectoryInternal(InDirectory));
-
- // Scan the directory for the name (only looking for directories which already exist)
- {
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *en = 0;
- while((en = i.Next(BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING,
- BackupStoreDirectory::Entry::Flags_Deleted | BackupStoreDirectory::Entry::Flags_OldVersion)) != 0) // Ignore deleted and old directories
- {
- if(en->GetName() == rFilename)
- {
- // Already exists
- rAlreadyExists = true;
- return en->GetObjectID();
- }
- }
- }
-
- // Allocate the next ID
- int64_t id = AllocateObjectID();
-
- // Create an empty directory with the given attributes on disc
- std::string fn;
- MakeObjectFilename(id, fn, true /* make sure the directory it's in exists */);
- {
- BackupStoreDirectory emptyDir(id, InDirectory);
- // add the atttribues
- emptyDir.SetAttributes(Attributes, AttributesModTime);
-
- // Write...
- RaidFileWrite dirFile(mStoreDiscSet, fn);
- dirFile.Open(false /* no overwriting */);
- emptyDir.WriteToStream(dirFile);
- // Get disc usage, before it's commited
- int64_t dirSize = dirFile.GetDiscUsageInBlocks();
- // Commit the file
- dirFile.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
-
- // Make sure the size of the directory is added to the usage counts in the info
- ASSERT(dirSize > 0);
- mapStoreInfo->ChangeBlocksUsed(dirSize);
- mapStoreInfo->ChangeBlocksInDirectories(dirSize);
- // Not added to cache, so don't set the size in the directory
- }
-
- // Then add it into the parent directory
- try
- {
- dir.AddEntry(rFilename, 0 /* modification time */, id, 0 /* blocks used */, BackupStoreDirectory::Entry::Flags_Dir, 0 /* attributes mod time */);
- SaveDirectory(dir, InDirectory);
-
- // Increment reference count on the new directory to one
- mapRefCount->AddReference(id);
- }
- catch(...)
- {
- // Back out on adding that directory
- RaidFileWrite del(mStoreDiscSet, fn);
- del.Delete();
-
- // Remove this entry from the cache
- RemoveDirectoryFromCache(InDirectory);
-
- // Don't worry about the incremented number in the store info
- throw;
- }
-
- // Save the store info (may not be postponed)
- mapStoreInfo->AdjustNumDirectories(1);
- SaveStoreInfo(false);
-
- // tell caller what the ID was
- return id;
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::DeleteDirectory(int64_t ObjectID, bool Undelete)
-{
- // Essential checks!
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- // Containing directory
- int64_t InDirectory = 0;
-
- // Count of blocks deleted
- int64_t blocksDeleted = 0;
-
- try
- {
- // Get the directory that's to be deleted
- {
- // In block, because dir may not be valid after the delete directory call
- BackupStoreDirectory &dir(GetDirectoryInternal(ObjectID));
-
- // Store the directory it's in for later
- InDirectory = dir.GetContainerID();
-
- // Depth first delete of contents
- DeleteDirectoryRecurse(ObjectID, blocksDeleted, Undelete);
- }
-
- // Remove the entry from the directory it's in
- ASSERT(InDirectory != 0);
- BackupStoreDirectory &parentDir(GetDirectoryInternal(InDirectory));
-
- BackupStoreDirectory::Iterator i(parentDir);
- BackupStoreDirectory::Entry *en = 0;
- while((en = i.Next(Undelete?(BackupStoreDirectory::Entry::Flags_Deleted):(BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING),
- Undelete?(0):(BackupStoreDirectory::Entry::Flags_Deleted))) != 0) // Ignore deleted directories (or not deleted if Undelete)
- {
- if(en->GetObjectID() == ObjectID)
- {
- // This is the one to delete
- if(Undelete)
- {
- en->RemoveFlags(BackupStoreDirectory::Entry::Flags_Deleted);
- }
- else
- {
- en->AddFlags(BackupStoreDirectory::Entry::Flags_Deleted);
- }
-
- // Save it
- SaveDirectory(parentDir, InDirectory);
-
- // Done
- break;
- }
- }
-
- // Update blocks deleted count
- mapStoreInfo->ChangeBlocksInDeletedFiles(Undelete?(0 - blocksDeleted):(blocksDeleted));
- mapStoreInfo->AdjustNumDirectories(-1);
- SaveStoreInfo(false);
- }
- catch(...)
- {
- RemoveDirectoryFromCache(InDirectory);
- throw;
- }
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::DeleteDirectoryRecurse(BackupStoreDirectory &, int64_t)
-// Purpose: Private. Deletes a directory depth-first recusively.
-// Created: 2003/10/21
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDeletedOut, bool Undelete)
-{
- try
- {
- // Does things carefully to avoid using a directory in the cache after recursive call
- // because it may have been deleted.
-
- // Do sub directories
- {
- // Get the directory...
- BackupStoreDirectory &dir(GetDirectoryInternal(ObjectID));
-
- // Then scan it for directories
- std::vector<int64_t> subDirs;
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *en = 0;
- if(Undelete)
- {
- while((en = i.Next(BackupStoreDirectory::Entry::Flags_Dir | BackupStoreDirectory::Entry::Flags_Deleted, // deleted dirs
- BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING)) != 0)
- {
- // Store the directory ID.
- subDirs.push_back(en->GetObjectID());
- }
- }
- else
- {
- while((en = i.Next(BackupStoreDirectory::Entry::Flags_Dir, // dirs only
- BackupStoreDirectory::Entry::Flags_Deleted)) != 0) // but not deleted ones
- {
- // Store the directory ID.
- subDirs.push_back(en->GetObjectID());
- }
- }
-
- // Done with the directory for now. Recurse to sub directories
- for(std::vector<int64_t>::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i)
- {
- DeleteDirectoryRecurse((*i), rBlocksDeletedOut, Undelete);
- }
- }
-
- // Then, delete the files. Will need to load the directory again because it might have
- // been removed from the cache.
- {
- // Get the directory...
- BackupStoreDirectory &dir(GetDirectoryInternal(ObjectID));
-
- // Changes made?
- bool changesMade = false;
-
- // Run through files
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *en = 0;
-
- while((en = i.Next(Undelete?(BackupStoreDirectory::Entry::Flags_Deleted):(BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING),
- Undelete?(0):(BackupStoreDirectory::Entry::Flags_Deleted))) != 0) // Ignore deleted directories (or not deleted if Undelete)
- {
- // Add/remove the deleted flags
- if(Undelete)
- {
- en->RemoveFlags(BackupStoreDirectory::Entry::Flags_Deleted);
- }
- else
- {
- en->AddFlags(BackupStoreDirectory::Entry::Flags_Deleted);
- }
-
- // Keep count of the deleted blocks
- if((en->GetFlags() & BackupStoreDirectory::Entry::Flags_File) != 0)
- {
- rBlocksDeletedOut += en->GetSizeInBlocks();
- }
-
- // Did something
- changesMade = true;
- }
-
- // Save the directory
- if(changesMade)
- {
- SaveDirectory(dir, ObjectID);
- }
- }
- }
- catch(...)
- {
- RemoveDirectoryFromCache(ObjectID);
- throw;
- }
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::ChangeDirAttributes(int64_t, const StreamableMemBlock &, int64_t)
-// Purpose: Change the attributes of a directory
-// Created: 2003/09/06
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::ChangeDirAttributes(int64_t Directory, const StreamableMemBlock &Attributes, int64_t AttributesModTime)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- try
- {
- // Get the directory we want to modify
- BackupStoreDirectory &dir(GetDirectoryInternal(Directory));
-
- // Set attributes
- dir.SetAttributes(Attributes, AttributesModTime);
-
- // Save back
- SaveDirectory(dir, Directory);
- }
- catch(...)
- {
- RemoveDirectoryFromCache(Directory);
- throw;
- }
-}
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::ChangeFileAttributes(const BackupStoreFilename &rFilename, int64_t InDirectory, const StreamableMemBlock &Attributes, int64_t AttributesHash, int64_t &rObjectIDOut)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- try
- {
- // Get the directory we want to modify
- BackupStoreDirectory &dir(GetDirectoryInternal(InDirectory));
-
- // Find the file entry
- BackupStoreDirectory::Entry *en = 0;
- // Iterate through current versions of files, only
- BackupStoreDirectory::Iterator i(dir);
- while((en = i.Next(
- BackupStoreDirectory::Entry::Flags_File,
- BackupStoreDirectory::Entry::Flags_Deleted | BackupStoreDirectory::Entry::Flags_OldVersion)
- ) != 0)
- {
- if(en->GetName() == rFilename)
- {
- // Set attributes
- en->SetAttributes(Attributes, AttributesHash);
-
- // Tell caller the object ID
- rObjectIDOut = en->GetObjectID();
-
- // Done
- break;
- }
- }
- if(en == 0)
- {
- // Didn't find it
- return false;
- }
-
- // Save back
- SaveDirectory(dir, InDirectory);
- }
- catch(...)
- {
- RemoveDirectoryFromCache(InDirectory);
- throw;
- }
-
- // Changed, everything OK
- return true;
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::ObjectExists(int64_t)
-// Purpose: Test to see if an object of this ID exists in the store
-// Created: 2003/09/03
-//
-// --------------------------------------------------------------------------
-bool BackupStoreContext::ObjectExists(int64_t ObjectID, int MustBe)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- // Note that we need to allow object IDs a little bit greater than the last one in the store info,
- // because the store info may not have got saved in an error condition. Max greater ID is
- // STORE_INFO_SAVE_DELAY in this case, *2 to be safe.
- if(ObjectID <= 0 || ObjectID > (mapStoreInfo->GetLastObjectIDUsed() + (STORE_INFO_SAVE_DELAY * 2)))
- {
- // Obviously bad object ID
- return false;
- }
-
- // Test to see if it exists on the disc
- std::string filename;
- MakeObjectFilename(ObjectID, filename);
- if(!RaidFileRead::FileExists(mStoreDiscSet, filename))
- {
- // RaidFile reports no file there
- return false;
- }
-
- // Do we need to be more specific?
- if(MustBe != ObjectExists_Anything)
- {
- // Open the file
- std::auto_ptr<RaidFileRead> objectFile(RaidFileRead::Open(mStoreDiscSet, filename));
-
- // Read the first integer
- u_int32_t magic;
- if(!objectFile->ReadFullBuffer(&magic, sizeof(magic), 0 /* not interested in how many read if failure */))
- {
- // Failed to get any bytes, must have failed
- return false;
- }
-
-#ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE
- if(MustBe == ObjectExists_File && ntohl(magic) == OBJECTMAGIC_FILE_MAGIC_VALUE_V0)
- {
- // Old version detected
- return true;
- }
-#endif
-
- // Right one?
- u_int32_t requiredMagic = (MustBe == ObjectExists_File)?OBJECTMAGIC_FILE_MAGIC_VALUE_V1:OBJECTMAGIC_DIR_MAGIC_VALUE;
-
- // Check
- if(ntohl(magic) != requiredMagic)
- {
- return false;
- }
-
- // File is implicitly closed
- }
-
- return true;
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::OpenObject(int64_t)
-// Purpose: Opens an object
-// Created: 2003/09/03
-//
-// --------------------------------------------------------------------------
-std::auto_ptr<IOStream> BackupStoreContext::OpenObject(int64_t ObjectID)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- // Attempt to open the file
- std::string fn;
- MakeObjectFilename(ObjectID, fn);
- return std::auto_ptr<IOStream>(RaidFileRead::Open(mStoreDiscSet, fn).release());
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::GetClientStoreMarker()
-// Purpose: Retrieve the client store marker
-// Created: 2003/10/29
-//
-// --------------------------------------------------------------------------
-int64_t BackupStoreContext::GetClientStoreMarker()
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- return mapStoreInfo->GetClientStoreMarker();
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::GetStoreDiscUsageInfo(int64_t &, int64_t &, int64_t &)
-// Purpose: Get disc usage info from store info
-// Created: 1/1/04
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::GetStoreDiscUsageInfo(int64_t &rBlocksUsed, int64_t &rBlocksSoftLimit, int64_t &rBlocksHardLimit)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- rBlocksUsed = mapStoreInfo->GetBlocksUsed();
- rBlocksSoftLimit = mapStoreInfo->GetBlocksSoftLimit();
- rBlocksHardLimit = mapStoreInfo->GetBlocksHardLimit();
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::HardLimitExceeded()
-// Purpose: Returns true if the hard limit has been exceeded
-// Created: 1/1/04
-//
-// --------------------------------------------------------------------------
-bool BackupStoreContext::HardLimitExceeded()
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- return mapStoreInfo->GetBlocksUsed() > mapStoreInfo->GetBlocksHardLimit();
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::SetClientStoreMarker(int64_t)
-// Purpose: Sets the client store marker, and commits it to disc
-// Created: 2003/10/29
-//
-// --------------------------------------------------------------------------
-void BackupStoreContext::SetClientStoreMarker(int64_t ClientStoreMarker)
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- mapStoreInfo->SetClientStoreMarker(ClientStoreMarker);
- SaveStoreInfo(false /* don't delay saving this */);
-}
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// 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 BackupStoreContext::MoveObject(int64_t ObjectID, int64_t MoveFromDirectory, int64_t MoveToDirectory, const BackupStoreFilename &rNewFilename, bool MoveAllWithSameName, bool AllowMoveOverDeletedObject)
-{
- if(mReadOnly)
- {
- THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
- }
-
- // Should deleted files be excluded when checking for the existance of objects with the target name?
- int64_t targetSearchExcludeFlags = (AllowMoveOverDeletedObject)
- ?(BackupStoreDirectory::Entry::Flags_Deleted)
- :(BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING);
-
- // Special case if the directories are the same...
- if(MoveFromDirectory == MoveToDirectory)
- {
- try
- {
- // Get the first directory
- BackupStoreDirectory &dir(GetDirectoryInternal(MoveFromDirectory));
-
- // Find the file entry
- BackupStoreDirectory::Entry *en = dir.FindEntryByID(ObjectID);
-
- // Error if not found
- if(en == 0)
- {
- THROW_EXCEPTION(BackupStoreException, CouldNotFindEntryInDirectory)
- }
-
- // Check the new name doens't already exist (optionally ignoring deleted files)
- {
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *c = 0;
- while((c = i.Next(BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING, targetSearchExcludeFlags)) != 0)
- {
- if(c->GetName() == rNewFilename)
- {
- THROW_EXCEPTION(BackupStoreException, NameAlreadyExistsInDirectory)
- }
- }
- }
-
- // Need to get all the entries with the same name?
- if(MoveAllWithSameName)
- {
- // Iterate through the directory, copying all with matching names
- BackupStoreDirectory::Iterator i(dir);
- BackupStoreDirectory::Entry *c = 0;
- while((c = i.Next()) != 0)
- {
- if(c->GetName() == en->GetName())
- {
- // Rename this one
- c->SetName(rNewFilename);
- }
- }
- }
- else
- {
- // Just copy this one
- en->SetName(rNewFilename);
- }
-
- // Save the directory back
- SaveDirectory(dir, MoveFromDirectory);
- }
- catch(...)
- {
- RemoveDirectoryFromCache(MoveToDirectory); // either will do, as they're the same
- throw;
- }
-
- return;
- }
-
- // Got to be careful how this is written, as we can't guarentte that if we have two
- // directories open, the first won't be deleted as the second is opened. (cache)
-
- // List of entries to move
- std::vector<BackupStoreDirectory::Entry *> moving;
-
- // list of directory IDs which need to have containing dir id changed
- std::vector<int64_t> dirsToChangeContainingID;
-
- try
- {
- // First of all, get copies of the entries to move to the to directory.
-
- {
- // Get the first directory
- BackupStoreDirectory &from(GetDirectoryInternal(MoveFromDirectory));
-
- // Find the file entry
- BackupStoreDirectory::Entry *en = from.FindEntryByID(ObjectID);
-
- // Error if not found
- if(en == 0)
- {
- THROW_EXCEPTION(BackupStoreException, CouldNotFindEntryInDirectory)
- }
-
- // Need to get all the entries with the same name?
- if(MoveAllWithSameName)
- {
- // Iterate through the directory, copying all with matching names
- BackupStoreDirectory::Iterator i(from);
- BackupStoreDirectory::Entry *c = 0;
- while((c = i.Next()) != 0)
- {
- if(c->GetName() == en->GetName())
- {
- // Copy
- moving.push_back(new BackupStoreDirectory::Entry(*c));
-
- // Check for containing directory correction
- if(c->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) dirsToChangeContainingID.push_back(c->GetObjectID());
- }
- }
- ASSERT(!moving.empty());
- }
- else
- {
- // Just copy this one
- moving.push_back(new BackupStoreDirectory::Entry(*en));
-
- // Check for containing directory correction
- if(en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) dirsToChangeContainingID.push_back(en->GetObjectID());
- }
- }
-
- // Secondly, insert them into the to directory, and save it
-
- {
- // To directory
- BackupStoreDirectory &to(GetDirectoryInternal(MoveToDirectory));
-
- // Check the new name doens't already exist
- {
- BackupStoreDirectory::Iterator i(to);
- BackupStoreDirectory::Entry *c = 0;
- while((c = i.Next(BackupStoreDirectory::Entry::Flags_INCLUDE_EVERYTHING, targetSearchExcludeFlags)) != 0)
- {
- if(c->GetName() == rNewFilename)
- {
- THROW_EXCEPTION(BackupStoreException, NameAlreadyExistsInDirectory)
- }
- }
- }
-
- // Copy the entries into it, changing the name as we go
- for(std::vector<BackupStoreDirectory::Entry *>::iterator i(moving.begin()); i != moving.end(); ++i)
- {
- BackupStoreDirectory::Entry *en = (*i);
- en->SetName(rNewFilename);
- to.AddEntry(*en); // adds copy
- }
-
- // Save back
- SaveDirectory(to, MoveToDirectory);
- }
-
- // Thirdly... remove them from the first directory -- but if it fails, attempt to delete them from the to directory
- try
- {
- // Get directory
- BackupStoreDirectory &from(GetDirectoryInternal(MoveFromDirectory));
-
- // Delete each one
- for(std::vector<BackupStoreDirectory::Entry *>::iterator i(moving.begin()); i != moving.end(); ++i)
- {
- from.DeleteEntry((*i)->GetObjectID());
- }
-
- // Save back
- SaveDirectory(from, MoveFromDirectory);
- }
- catch(...)
- {
- // UNDO modification to To directory
-
- // Get directory
- BackupStoreDirectory &to(GetDirectoryInternal(MoveToDirectory));
-
- // Delete each one
- for(std::vector<BackupStoreDirectory::Entry *>::iterator i(moving.begin()); i != moving.end(); ++i)
- {
- to.DeleteEntry((*i)->GetObjectID());
- }
-
- // Save back
- SaveDirectory(to, MoveToDirectory);
-
- // Throw the error
- throw;
- }
-
- // Finally... for all the directories we moved, modify their containing directory ID
- for(std::vector<int64_t>::iterator i(dirsToChangeContainingID.begin()); i != dirsToChangeContainingID.end(); ++i)
- {
- // Load the directory
- BackupStoreDirectory &change(GetDirectoryInternal(*i));
-
- // Modify containing dir ID
- change.SetContainerID(MoveToDirectory);
-
- // Save it back
- SaveDirectory(change, *i);
- }
- }
- catch(...)
- {
- // Make sure directories aren't in the cache, as they may have been modified
- RemoveDirectoryFromCache(MoveToDirectory);
- RemoveDirectoryFromCache(MoveFromDirectory);
- for(std::vector<int64_t>::iterator i(dirsToChangeContainingID.begin()); i != dirsToChangeContainingID.end(); ++i)
- {
- RemoveDirectoryFromCache(*i);
- }
-
- while(!moving.empty())
- {
- delete moving.back();
- moving.pop_back();
- }
- throw;
- }
-
- // Clean up
- while(!moving.empty())
- {
- delete moving.back();
- moving.pop_back();
- }
-}
-
-
-
-// --------------------------------------------------------------------------
-//
-// Function
-// Name: BackupStoreContext::GetBackupStoreInfo()
-// Purpose: Return the backup store info object, exception if it isn't loaded
-// Created: 19/4/04
-//
-// --------------------------------------------------------------------------
-const BackupStoreInfo &BackupStoreContext::GetBackupStoreInfo() const
-{
- if(mapStoreInfo.get() == 0)
- {
- THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
- }
-
- return *(mapStoreInfo.get());
-}
-
-
diff --git a/bin/bbstored/BackupStoreContext.h b/bin/bbstored/BackupStoreContext.h
deleted file mode 100644
index 44a05dd8..00000000
--- a/bin/bbstored/BackupStoreContext.h
+++ /dev/null
@@ -1,186 +0,0 @@
-// --------------------------------------------------------------------------
-//
-// File
-// Name: BackupStoreContext.h
-// Purpose: Context for backup store server
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-
-#ifndef BACKUPCONTEXT__H
-#define BACKUPCONTEXT__H
-
-#include <string>
-#include <map>
-#include <memory>
-
-#include "BackupStoreRefCountDatabase.h"
-#include "NamedLock.h"
-#include "ProtocolObject.h"
-#include "Utils.h"
-
-class BackupStoreDirectory;
-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: BackupStoreContext
-// Purpose: Context for backup store server
-// Created: 2003/08/20
-//
-// --------------------------------------------------------------------------
-class BackupStoreContext
-{
-public:
- BackupStoreContext(int32_t ClientID, HousekeepingInterface &rDaemon);
- ~BackupStoreContext();
-private:
- BackupStoreContext(const BackupStoreContext &rToCopy);
-public:
-
- void ReceivedFinishCommand();
- void CleanUp();
-
- int32_t GetClientID() {return mClientID;}
-
- enum
- {
- Phase_START = 0,
- Phase_Version = 0,
- Phase_Login = 1,
- Phase_Commands = 2
- };
-
- int GetPhase() const {return mProtocolPhase;}
- void SetPhase(int NewPhase) {mProtocolPhase = NewPhase;}
-
- // Read only locking
- bool SessionIsReadOnly() {return mReadOnly;}
- bool AttemptToGetWriteLock();
-
- void SetClientHasAccount(const std::string &rStoreRoot, int StoreDiscSet) {mClientHasAccount = true; mStoreRoot = rStoreRoot; mStoreDiscSet = StoreDiscSet;}
- bool GetClientHasAccount() const {return mClientHasAccount;}
- const std::string &GetStoreRoot() const {return mStoreRoot;}
- int GetStoreDiscSet() const {return mStoreDiscSet;}
-
- // Store info
- void LoadStoreInfo();
- void SaveStoreInfo(bool AllowDelay = true);
- const BackupStoreInfo &GetBackupStoreInfo() const;
-
- // Client marker
- int64_t GetClientStoreMarker();
- void SetClientStoreMarker(int64_t ClientStoreMarker);
-
- // Usage information
- void GetStoreDiscUsageInfo(int64_t &rBlocksUsed, int64_t &rBlocksSoftLimit, int64_t &rBlocksHardLimit);
- bool HardLimitExceeded();
-
- // Reading directories
- // --------------------------------------------------------------------------
- //
- // Function
- // 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.
- // Created: 2003/09/02
- //
- // --------------------------------------------------------------------------
- const BackupStoreDirectory &GetDirectory(int64_t ObjectID)
- {
- // External callers aren't allowed to change it -- this function
- // merely turns the the returned directory const.
- return GetDirectoryInternal(ObjectID);
- }
-
- // Manipulating files/directories
- int64_t AddFile(IOStream &rFile, int64_t InDirectory, int64_t ModificationTime, int64_t AttributesHash, int64_t DiffFromFileID, const BackupStoreFilename &rFilename, bool MarkFileWithSameNameAsOldVersions);
- int64_t AddDirectory(int64_t InDirectory, const BackupStoreFilename &rFilename, const StreamableMemBlock &Attributes, int64_t AttributesModTime, bool &rAlreadyExists);
- 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);
-
- // Manipulating objects
- enum
- {
- ObjectExists_Anything = 0,
- ObjectExists_File = 1,
- ObjectExists_Directory = 2
- };
- bool ObjectExists(int64_t ObjectID, int MustBe = ObjectExists_Anything);
- std::auto_ptr<IOStream> OpenObject(int64_t ObjectID);
-
- // Info
- int32_t GetClientID() const {return mClientID;}
-
-private:
- void MakeObjectFilename(int64_t ObjectID, std::string &rOutput, bool EnsureDirectoryExists = false);
- BackupStoreDirectory &GetDirectoryInternal(int64_t ObjectID);
- void SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID);
- void RemoveDirectoryFromCache(int64_t ObjectID);
- void DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDeletedOut, bool Undelete);
- int64_t AllocateObjectID();
-
- int32_t mClientID;
- HousekeepingInterface &mrDaemon;
- int mProtocolPhase;
- bool mClientHasAccount;
- std::string mStoreRoot; // has final directory separator
- int mStoreDiscSet;
- bool mReadOnly;
- NamedLock mWriteLock;
- int mSaveStoreInfoDelay; // how many times to delay saving the store info
-
- // Store info
- std::auto_ptr<BackupStoreInfo> mapStoreInfo;
-
- // Refcount database
- std::auto_ptr<BackupStoreRefCountDatabase> mapRefCount;
-
- // 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/Makefile.extra b/bin/bbstored/Makefile.extra
deleted file mode 100644
index 6562647d..00000000
--- a/bin/bbstored/Makefile.extra
+++ /dev/null
@@ -1,9 +0,0 @@
-
-MAKEPROTOCOL = ../../lib/server/makeprotocol.pl
-
-GEN_CMD_SRV = $(MAKEPROTOCOL) Server backupprotocol.txt
-
-# AUTOGEN SEEDING
-autogen_BackupProtocolServer.cpp autogen_BackupProtocolServer.h: $(MAKEPROTOCOL) backupprotocol.txt
- $(_PERL) $(GEN_CMD_SRV)
-
diff --git a/bin/bbstored/backupprotocol.txt b/bin/bbstored/backupprotocol.txt
deleted file mode 100644
index 011458e8..00000000
--- a/bin/bbstored/backupprotocol.txt
+++ /dev/null
@@ -1,235 +0,0 @@
-#
-# backup protocol definition
-#
-
-Name Backup
-IdentString Box-Backup:v=C
-ServerContextClass BackupStoreContext BackupStoreContext.h
-
-ClientType Filename BackupStoreFilenameClear BackupStoreFilenameClear.h
-ServerType Filename BackupStoreFilename BackupStoreFilename.h
-
-ImplementLog Server syslog
-ImplementLog Client syslog
-ImplementLog Client file
-
-LogTypeToText Client Filename \"%s\" VAR.GetClearFilename().c_str()
-
-BEGIN_OBJECTS
-
-# -------------------------------------------------------------------------------------
-# Session commands
-# -------------------------------------------------------------------------------------
-
-Error 0 IsError(Type,SubType) Reply
- int32 Type
- int32 SubType
- CONSTANT ErrorType 1000
- CONSTANT Err_WrongVersion 1
- CONSTANT Err_NotInRightProtocolPhase 2
- CONSTANT Err_BadLogin 3
- CONSTANT Err_CannotLockStoreForWriting 4
- CONSTANT Err_SessionReadOnly 5
- CONSTANT Err_FileDoesNotVerify 6
- CONSTANT Err_DoesNotExist 7
- CONSTANT Err_DirectoryAlreadyExists 8
- CONSTANT Err_CannotDeleteRoot 9
- CONSTANT Err_TargetNameExists 10
- CONSTANT Err_StorageLimitExceeded 11
- CONSTANT Err_DiffFromFileDoesNotExist 12
- CONSTANT Err_DoesNotExistInDirectory 13
- CONSTANT Err_PatchConsistencyError 14
- CONSTANT Err_MultiplyReferencedObject 15
-
-Version 1 Command(Version) Reply
- int32 Version
-
-
-Login 2 Command(LoginConfirmed)
- int32 ClientID
- int32 Flags
- CONSTANT Flags_ReadOnly 1
-
-
-LoginConfirmed 3 Reply
- int64 ClientStoreMarker
- int64 BlocksUsed
- int64 BlocksSoftLimit
- int64 BlocksHardLimit
-
-
-Finished 4 Command(Finished) Reply EndsConversation
-
-
-# generic success object
-Success 5 Reply
- int64 ObjectID
-
-
-SetClientStoreMarker 6 Command(Success)
- int64 ClientStoreMarker
-
-
-# -------------------------------------------------------------------------------------
-# Generic object commands
-# -------------------------------------------------------------------------------------
-
-GetObject 10 Command(Success)
- int64 ObjectID
- CONSTANT NoObject 0
- # reply has stream following, if ObjectID != NoObject
-
-
-MoveObject 11 Command(Success)
- int64 ObjectID
- int64 MoveFromDirectory
- int64 MoveToDirectory
- int32 Flags
- Filename NewFilename
-
- CONSTANT Flags_MoveAllWithSameName 1
- CONSTANT Flags_AllowMoveOverDeletedObject 2
-
-# consider this an object command as, although it deals with directory entries,
-# it's not specific to either a file or a directory
-
-
-GetObjectName 12 Command(ObjectName)
- int64 ObjectID
- int64 ContainingDirectoryID
- CONSTANT ObjectID_DirectoryOnly 0
-
- # set ObjectID to ObjectID_DirectoryOnly to only get info on the directory
-
-
-ObjectName 13 Reply
- int32 NumNameElements
- int64 ModificationTime
- int64 AttributesHash
- int16 Flags
- # NumNameElements is zero if the object doesn't exist
- CONSTANT NumNameElements_ObjectDoesntExist 0
- # a stream of Filename objects follows, if and only if NumNameElements > 0
-
-
-# -------------------------------------------------------------------------------------
-# Directory commands
-# -------------------------------------------------------------------------------------
-
-CreateDirectory 20 Command(Success) StreamWithCommand
- int64 ContainingDirectoryID
- int64 AttributesModTime
- Filename DirectoryName
- # stream following containing attributes
-
-
-ListDirectory 21 Command(Success)
- int64 ObjectID
- int16 FlagsMustBeSet
- int16 FlagsNotToBeSet
- bool SendAttributes
- # make sure these flags are synced with those in BackupStoreDirectory
- CONSTANT Flags_INCLUDE_EVERYTHING -1
- CONSTANT Flags_EXCLUDE_NOTHING 0
- CONSTANT Flags_EXCLUDE_EVERYTHING 15
- CONSTANT Flags_File 1
- CONSTANT Flags_Dir 2
- CONSTANT Flags_Deleted 4
- CONSTANT Flags_OldVersion 8
- # make sure this is the same as in BackupStoreConstants.h
- CONSTANT RootDirectory 1
-
- # reply has stream following Success object, containing a stored BackupStoreDirectory
-
-
-ChangeDirAttributes 22 Command(Success) StreamWithCommand
- int64 ObjectID
- int64 AttributesModTime
- # stream following containing attributes
-
-
-DeleteDirectory 23 Command(Success)
- int64 ObjectID
-
-UndeleteDirectory 24 Command(Success)
- int64 ObjectID
- # may not have exactly the desired effect if files within in have been deleted before the directory was deleted.
-
-
-# -------------------------------------------------------------------------------------
-# File commands
-# -------------------------------------------------------------------------------------
-
-StoreFile 30 Command(Success) StreamWithCommand
- int64 DirectoryObjectID
- int64 ModificationTime
- int64 AttributesHash
- int64 DiffFromFileID # 0 if the file is not a diff
- Filename Filename
- # then send a stream containing the encoded file
-
-
-GetFile 31 Command(Success)
- int64 InDirectory
- int64 ObjectID
- # error returned if not a file, or does not exist
- # reply has stream following, containing an encoded file IN STREAM ORDER
- # (use GetObject to get it in file order)
-
-
-SetReplacementFileAttributes 32 Command(Success) StreamWithCommand
- int64 InDirectory
- int64 AttributesHash
- Filename Filename
- # stream follows containing attributes
-
-
-DeleteFile 33 Command(Success)
- int64 InDirectory
- Filename Filename
- # will return 0 if the object couldn't be found in the specified directory
-
-
-GetBlockIndexByID 34 Command(Success)
- int64 ObjectID
-
- # stream of the block index follows the reply
- # returns an error if the object didn't exist
-
-
-GetBlockIndexByName 35 Command(Success)
- int64 InDirectory
- Filename Filename
-
- # Success object contains the found ID -- or 0 if the entry wasn't found in the directory
- # 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
-# -------------------------------------------------------------------------------------
-
-GetAccountUsage 40 Command(AccountUsage)
- # no data members
-
-AccountUsage 41 Reply
- int64 BlocksUsed
- int64 BlocksInOldFiles
- int64 BlocksInDeletedFiles
- int64 BlocksInDirectories
- int64 BlocksSoftLimit
- int64 BlocksHardLimit
- int32 BlockSize
-
-GetIsAlive 42 Command(IsAlive)
- # no data members
-
-IsAlive 43 Reply
- # no data members
-