summaryrefslogtreecommitdiff
path: root/bin/bbackupd/BackupClientInodeToIDMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbackupd/BackupClientInodeToIDMap.cpp')
-rw-r--r--bin/bbackupd/BackupClientInodeToIDMap.cpp119
1 files changed, 97 insertions, 22 deletions
diff --git a/bin/bbackupd/BackupClientInodeToIDMap.cpp b/bin/bbackupd/BackupClientInodeToIDMap.cpp
index f525d21e..6eaf7394 100644
--- a/bin/bbackupd/BackupClientInodeToIDMap.cpp
+++ b/bin/bbackupd/BackupClientInodeToIDMap.cpp
@@ -16,15 +16,16 @@
#include "BackupClientInodeToIDMap.h"
#undef BACKIPCLIENTINODETOIDMAP_IMPLEMENTATION
+#include "Archive.h"
#include "BackupStoreException.h"
+#include "CollectInBufferStream.h"
+#include "MemBlockStream.h"
+#include "autogen_CommonException.h"
#include "MemLeakFindOn.h"
-typedef struct
-{
- int64_t mObjectID;
- int64_t mInDirectory;
-} IDBRecord;
+#define BOX_DBM_INODE_DB_VERSION_KEY "BackupClientInodeToIDMap.Version"
+#define BOX_DBM_INODE_DB_VERSION_CURRENT 2
#define BOX_DBM_MESSAGE(stuff) stuff << " (qdbm): " << dperrmsg(dpecode)
@@ -118,12 +119,58 @@ void BackupClientInodeToIDMap::Open(const char *Filename, bool ReadOnly,
if(!mpDepot)
{
- BOX_WARNING(BOX_DBM_MESSAGE("Failed to open inode "
- "database: " << mFilename));
THROW_EXCEPTION_MESSAGE(BackupStoreException, BerkelyDBFailure,
BOX_DBM_MESSAGE("Failed to open inode database: " <<
mFilename));
}
+
+ const char* version_key = BOX_DBM_INODE_DB_VERSION_KEY;
+ int32_t version = 0;
+
+ if(CreateNew)
+ {
+ version = BOX_DBM_INODE_DB_VERSION_CURRENT;
+
+ int ret = dpput(mpDepot, version_key, strlen(version_key),
+ (char *)(&version), sizeof(version), DP_DKEEP);
+
+ if(!ret)
+ {
+ THROW_EXCEPTION_MESSAGE(BackupStoreException, BerkelyDBFailure,
+ BOX_DBM_MESSAGE("Failed to write version number to inode "
+ "database: " << mFilename));
+ }
+ }
+ else
+ {
+ int ret = dpgetwb(mpDepot, version_key, strlen(version_key), 0,
+ sizeof(version), (char *)(&version));
+
+ if(ret == -1)
+ {
+ THROW_EXCEPTION_MESSAGE(BackupStoreException, BerkelyDBFailure,
+ "Missing version number in inode database. Perhaps it "
+ "needs to be recreated: " << mFilename);
+ }
+
+ if(ret != sizeof(version))
+ {
+ THROW_EXCEPTION_MESSAGE(BackupStoreException, BerkelyDBFailure,
+ "Wrong size version number in inode database: expected "
+ << sizeof(version) << " bytes but found " << ret);
+ }
+
+ if(version != BOX_DBM_INODE_DB_VERSION_CURRENT)
+ {
+ THROW_EXCEPTION_MESSAGE(BackupStoreException, BerkelyDBFailure,
+ "Wrong version number in inode database: expected " <<
+ BOX_DBM_INODE_DB_VERSION_CURRENT << " but found " <<
+ version << ". Perhaps it needs to be recreated: " <<
+ mFilename);
+ }
+
+ // By this point the version number has been checked and is OK.
+ }
// Read only flag
mReadOnly = ReadOnly;
@@ -175,7 +222,7 @@ void BackupClientInodeToIDMap::Close()
//
// --------------------------------------------------------------------------
void BackupClientInodeToIDMap::AddToMap(InodeRefType InodeRef, int64_t ObjectID,
- int64_t InDirectory)
+ int64_t InDirectory, const std::string& LocalPath)
{
if(mReadOnly)
{
@@ -190,12 +237,15 @@ void BackupClientInodeToIDMap::AddToMap(InodeRefType InodeRef, int64_t ObjectID,
ASSERT_DBM_OPEN();
// Setup structures
- IDBRecord rec;
- rec.mObjectID = ObjectID;
- rec.mInDirectory = InDirectory;
+ CollectInBufferStream buf;
+ Archive arc(buf, IOStream::TimeOutInfinite);
+ arc.WriteExact((uint64_t)ObjectID);
+ arc.WriteExact((uint64_t)InDirectory);
+ arc.Write(LocalPath);
+ buf.SetForReading();
ASSERT_DBM_OK(dpput(mpDepot, (const char *)&InodeRef, sizeof(InodeRef),
- (const char *)&rec, sizeof(rec), DP_DOVER),
+ (const char *)buf.GetBuffer(), buf.GetSize(), DP_DOVER),
"Failed to add record to inode database", mFilename,
BackupStoreException, BerkelyDBFailure);
}
@@ -211,8 +261,8 @@ void BackupClientInodeToIDMap::AddToMap(InodeRefType InodeRef, int64_t ObjectID,
// Created: 11/11/03
//
// --------------------------------------------------------------------------
-bool BackupClientInodeToIDMap::Lookup(InodeRefType InodeRef,
- int64_t &rObjectIDOut, int64_t &rInDirectoryOut) const
+bool BackupClientInodeToIDMap::Lookup(InodeRefType InodeRef, int64_t &rObjectIDOut,
+ int64_t &rInDirectoryOut, std::string* pLocalPathOut) const
{
if(mEmpty)
{
@@ -226,19 +276,44 @@ bool BackupClientInodeToIDMap::Lookup(InodeRefType InodeRef,
}
ASSERT_DBM_OPEN();
-
- IDBRecord rec;
-
- if(dpgetwb(mpDepot, (const char *)&InodeRef, sizeof(InodeRef),
- 0, sizeof(IDBRecord), (char *)&rec) == -1)
+ int size;
+ char* data = dpget(mpDepot, (const char *)&InodeRef, sizeof(InodeRef),
+ 0, -1, &size);
+ if(data == NULL)
{
// key not in file
return false;
}
-
+
+ // Free data automatically when the guard goes out of scope.
+ MemoryBlockGuard<char *> guard(data);
+ MemBlockStream stream(data, size);
+ Archive arc(stream, IOStream::TimeOutInfinite);
+
// Return data
- rObjectIDOut = rec.mObjectID;
- rInDirectoryOut = rec.mInDirectory;
+ try
+ {
+ arc.Read(rObjectIDOut);
+ arc.Read(rInDirectoryOut);
+ if(pLocalPathOut)
+ {
+ arc.Read(*pLocalPathOut);
+ }
+ }
+ catch(CommonException &e)
+ {
+ if(e.GetSubType() == CommonException::ArchiveBlockIncompleteRead)
+ {
+ THROW_FILE_ERROR("Failed to lookup record in inode database: "
+ << InodeRef << ": not enough data in record", mFilename,
+ BackupStoreException, BerkelyDBFailure);
+ // Need to throw precisely that exception to ensure that the
+ // invalid database is deleted, so that we don't hit the same
+ // error next time.
+ }
+
+ throw;
+ }
// Found
return true;