[Box Backup-dev] COMMIT r338 - in box/chris/bb-save-state: bin/bbackupd lib/backupclient lib/common
boxbackup-dev@fluffy.co.uk
boxbackup-dev@fluffy.co.uk
Fri, 27 Jan 2006 22:29:13 +0000 (GMT)
Author: chris
Date: 2006-01-27 22:29:09 +0000 (Fri, 27 Jan 2006)
New Revision: 338
Modified:
box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.cpp
box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.h
box/chris/bb-save-state/bin/bbackupd/BackupDaemon.cpp
box/chris/bb-save-state/bin/bbackupd/BackupDaemon.h
box/chris/bb-save-state/lib/backupclient/BackupDaemonConfigVerify.cpp
box/chris/bb-save-state/lib/common/Configuration.cpp
box/chris/bb-save-state/lib/common/Configuration.h
box/chris/bb-save-state/lib/common/ExcludeList.cpp
box/chris/bb-save-state/lib/common/ExcludeList.h
Log:
* lib/backupclient/BackupDaemonConfigVerify.cpp
* lib/common/Configuration.h
* lib/common/ExcludeList.h
* lib/common/Configuration.cpp
* lib/common/ExcludeList.cpp
* bin/bbackupd/BackupDaemon.h
* bin/bbackupd/BackupClientDirectoryRecord.cpp
* bin/bbackupd/BackupDaemon.cpp
* bin/bbackupd/BackupClientDirectoryRecord.h
- Committed Gary's save state (serialisation) patch, with minor modifications
Modified: box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.cpp
===================================================================
--- box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.cpp 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.cpp 2006-01-27 22:29:09 UTC (rev 338)
@@ -1211,5 +1211,147 @@
{
}
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupClientDirectoryRecord::Deserialize(Archive & rArchive)
+// Purpose: Deserializes this object instance from a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void BackupClientDirectoryRecord::Deserialize(Archive & rArchive)
+{
+ // Make deletion recursive
+ DeleteSubDirectories();
+ // Delete maps
+ if(mpPendingEntries != 0)
+ {
+ delete mpPendingEntries;
+ mpPendingEntries = 0;
+ }
+ //
+ //
+ //
+ rArchive >> mObjectID >> mSubDirName >> mInitialSyncDone >> mSyncDone;
+
+ //
+ //
+ //
+ int64_t iCount = 0;
+ rArchive.Get(iCount);
+
+ if (iCount != sizeof(mStateChecksum)/sizeof(mStateChecksum[0]))
+ {
+ // we have some kind of internal system representation change: throw for now
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+
+ for (int v = 0; v < iCount; v++)
+ /**** LOAD ****/ rArchive.Get(mStateChecksum[v]);
+
+ //
+ //
+ //
+ iCount = 0;
+ rArchive.Get(iCount);
+
+ if (iCount > 0)
+ {
+ /**** LOAD ****/ mpPendingEntries = new std::map<std::string, box_time_t>;
+ if (!mpPendingEntries)
+ throw std::bad_alloc();
+
+ for (int v = 0; v < iCount; v++)
+ {
+ std::string strItem;
+ box_time_t btItem;
+
+ rArchive >> strItem >> btItem;
+ (*mpPendingEntries)[strItem] = btItem;
+ }
+ }
+
+ //
+ //
+ //
+ iCount = 0;
+ rArchive.Get(iCount);
+
+ if (iCount > 0)
+ {
+ for (int v = 0; v < iCount; v++)
+ {
+ std::string strItem;
+ rArchive.Get(strItem);
+
+ BackupClientDirectoryRecord* pSubDirRecord = new BackupClientDirectoryRecord(0, ""); // will be deserialized anyway, give it id 0 for now
+ if (!pSubDirRecord)
+ throw std::bad_alloc();
+
+ /***** RECURSE *****/
+ pSubDirRecord->Deserialize(rArchive);
+ mSubDirectories[strItem] = pSubDirRecord;
+ }
+ }
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupClientDirectoryRecord::Serialize(Archive & rArchive)
+// Purpose: Serializes this object instance into a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void BackupClientDirectoryRecord::Serialize(Archive & rArchive) const
+{
+ //
+ //
+ //
+ rArchive << mObjectID << mSubDirName << mInitialSyncDone << mSyncDone;
+
+ //
+ //
+ //
+ int64_t iCount = 0;
+
+ iCount = sizeof(mStateChecksum)/sizeof(mStateChecksum[0]);
+ rArchive.Add(iCount); // add count to see if we have crossed build-level mods
+ for (int v = 0; v < iCount; v++)
+ rArchive.Add(mStateChecksum[v]);
+
+ //
+ //
+ //
+ if (!mpPendingEntries)
+ {
+ iCount = 0;
+ rArchive.Add(iCount);
+ }
+ else
+ {
+ iCount = mpPendingEntries->size();
+ rArchive.Add(iCount);
+
+ for (std::map<std::string, box_time_t>::const_iterator i = mpPendingEntries->begin(); i != mpPendingEntries->end(); i++)
+ rArchive << (*i).first << (*i).second;
+ }
+ //
+ //
+ //
+ iCount = mSubDirectories.size();
+ rArchive.Add(iCount);
+
+ for (std::map<std::string, BackupClientDirectoryRecord*>::const_iterator i = mSubDirectories.begin(); i != mSubDirectories.end(); i++)
+ {
+ const BackupClientDirectoryRecord* pSubItem = (*i).second;
+ ASSERT(pSubItem);
+
+ rArchive.Add((*i).first);
+ pSubItem->Serialize(rArchive);
+ }
+}
Modified: box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.h
===================================================================
--- box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.h 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/bin/bbackupd/BackupClientDirectoryRecord.h 2006-01-27 22:29:09 UTC (rev 338)
@@ -18,6 +18,8 @@
#include "BackupStoreDirectory.h"
#include "MD5Digest.h"
+#include "Archive.h"
+
class BackupClientContext;
class BackupDaemon;
@@ -34,6 +36,9 @@
public:
BackupClientDirectoryRecord(int64_t ObjectID, const std::string &rSubDirName);
~BackupClientDirectoryRecord();
+
+ void Deserialize(Archive & rArchive);
+ void Serialize(Archive & rArchive) const;
private:
BackupClientDirectoryRecord(const BackupClientDirectoryRecord &);
public:
Modified: box/chris/bb-save-state/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/bb-save-state/bin/bbackupd/BackupDaemon.cpp 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/bin/bbackupd/BackupDaemon.cpp 2006-01-27 22:29:09 UTC (rev 338)
@@ -463,10 +463,18 @@
// When the last sync started (only updated if the store was not full when the sync ended)
box_time_t lastSyncTime = 0;
+ // --------------------------------------------------------------------------------------------
+
+ // And what's the current client store marker?
+ int64_t clientStoreMarker =
+ BackupClientContext::ClientStoreMarker_NotKnown;
+ // haven't contacted the store yet
+
+ DeserializeStoreObjectInfo(clientStoreMarker, lastSyncTime,
+ nextSyncTime);
+
// --------------------------------------------------------------------------------------------
- // And what's the current client store marker?
- int64_t clientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown; // haven't contacted the store yet
// Set state
SetState(State_Idle);
@@ -670,6 +678,13 @@
// Log
::syslog(LOG_INFO, "Finished scan of local files");
+
+ // --------------------------------------------------------------------------------------------
+
+ // We had a successful backup, save the store info
+ SerializeStoreObjectInfo(clientStoreMarker, lastSyncTime, nextSyncTime);
+
+ // --------------------------------------------------------------------------------------------
}
catch(BoxException &e)
{
@@ -1827,7 +1842,19 @@
mUnusedRootDirEntries.clear();
}
+// --------------------------------------------------------------------------
+typedef struct
+{
+ int32_t mMagicValue; // also the version number
+ int32_t mNumEntries;
+ int64_t mObjectID; // this object ID
+ int64_t mContainerID; // ID of container
+ uint64_t mAttributesModTime;
+ int32_t mOptionsPresent; // bit mask of optional sections / features present
+
+} loc_StreamFormat;
+
// --------------------------------------------------------------------------
//
// Function
@@ -1866,10 +1893,177 @@
}
}
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupDaemon::Location::Deserialize(Archive & rArchive)
+// Purpose: Deserializes this object instance from a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void BackupDaemon::Location::Deserialize(Archive & rArchive)
+{
+ //
+ //
+ //
+ mpDirectoryRecord.reset(NULL);
+ if (mpExcludeFiles)
+ {
+ delete mpExcludeFiles;
+ mpExcludeFiles = NULL;
+ }
+ if (mpExcludeDirs)
+ {
+ delete mpExcludeDirs;
+ mpExcludeDirs = NULL;
+ }
+ //
+ //
+ //
+ rArchive >> mName >> mPath >> mIDMapIndex;
+
+ //
+ //
+ //
+ int64_t aMagicMarker = 0;
+ rArchive.Get(aMagicMarker);
+
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ {
+ // NOOP
+ }
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ {
+ BackupClientDirectoryRecord *pSubRecord = new BackupClientDirectoryRecord(0, "");
+ if (!pSubRecord)
+ throw std::bad_alloc();
+
+ mpDirectoryRecord.reset(pSubRecord);
+ mpDirectoryRecord->Deserialize(rArchive);
+ }
+ else
+ {
+ // there is something going on here
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+
+ //
+ //
+ //
+ rArchive.Get(aMagicMarker);
+
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ {
+ // NOOP
+ }
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ {
+ mpExcludeFiles = new ExcludeList;
+ if (!mpExcludeFiles)
+ throw std::bad_alloc();
+
+ mpExcludeFiles->Deserialize(rArchive);
+ }
+ else
+ {
+ // there is something going on here
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+
+ //
+ //
+ //
+ rArchive.Get(aMagicMarker);
+
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ {
+ // NOOP
+ }
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ {
+ mpExcludeDirs = new ExcludeList;
+ if (!mpExcludeDirs)
+ throw std::bad_alloc();
+
+ mpExcludeDirs->Deserialize(rArchive);
+ }
+ else
+ {
+ // there is something going on here
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+}
+
// --------------------------------------------------------------------------
//
// Function
+// Name: BackupDaemon::Location::Serialize(Archive & rArchive)
+// Purpose: Serializes this object instance into a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void BackupDaemon::Location::Serialize(Archive & rArchive) const
+{
+ //
+ //
+ //
+ rArchive << mName << mPath << mIDMapIndex;
+
+ //
+ //
+ //
+ if (mpDirectoryRecord.get() == NULL)
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
+ rArchive.Add(aMagicMarker);
+ }
+ else
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_RECURSE; // be explicit about whether recursion follows
+ rArchive.Add(aMagicMarker);
+
+ mpDirectoryRecord->Serialize(rArchive);
+ }
+
+ //
+ //
+ //
+ if (!mpExcludeFiles)
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
+ rArchive.Add(aMagicMarker);
+ }
+ else
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_RECURSE; // be explicit about whether recursion follows
+ rArchive.Add(aMagicMarker);
+
+ mpExcludeFiles->Serialize(rArchive);
+ }
+
+ //
+ //
+ //
+ if (!mpExcludeDirs)
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
+ rArchive.Add(aMagicMarker);
+ }
+ else
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_RECURSE; // be explicit about whether recursion follows
+ rArchive.Add(aMagicMarker);
+
+ mpExcludeDirs->Serialize(rArchive);
+ }
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
// Name: BackupDaemon::CommandSocketInfo::CommandSocketInfo()
// Purpose: Constructor
// Created: 18/2/04
@@ -1897,3 +2091,192 @@
mpGetLine = 0;
}
}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime)
+// Purpose: Serializes remote directory and file information into a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+
+static const int STOREOBJECTINFO_MAGIC_ID_VALUE = 0x7777525F;
+static const std::string STOREOBJECTINFO_MAGIC_ID_STRING = "BBACKUPD-STATE";
+static const int STOREOBJECTINFO_VERSION = 1;
+
+void BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
+{
+ if(!GetConfiguration().KeyExists("StoreObjectInfoFile") || GetConfiguration().GetKeyValue("StoreObjectInfoFile").size() <= 0)
+ return;
+
+ try
+ {
+ FileStream aFile(GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str(), O_WRONLY | O_CREAT | O_TRUNC);
+ IOStreamArchive anArchive(aFile, 0);
+
+ anArchive << STOREOBJECTINFO_MAGIC_ID_VALUE << STOREOBJECTINFO_MAGIC_ID_STRING << STOREOBJECTINFO_VERSION
+ << GetConfiguration().GetModTime()
+ << aClientStoreMarker << theLastSyncTime << theNextSyncTime;
+
+ //
+ //
+ //
+ int64_t iCount = mLocations.size();
+ anArchive.Add(iCount);
+
+ for (int v = 0; v < iCount; v++)
+ {
+ ASSERT(mLocations[v]);
+ mLocations[v]->Serialize(anArchive);
+ }
+
+ //
+ //
+ //
+ iCount = mIDMapMounts.size();
+ anArchive.Add(iCount);
+
+ for (int v = 0; v < iCount; v++)
+ anArchive.Add(mIDMapMounts[v]);
+
+ //
+ //
+ //
+ aFile.Close();
+ ::syslog(LOG_INFO, "Saved store object info file '%s'", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ }
+ catch (...)
+ {
+ ::syslog(LOG_WARNING, "Requested store object info file '%s' not accessible or could not be created", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ }
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime)
+// Purpose: Deserializes remote directory and file information from a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime)
+{
+ //
+ //
+ //
+ DeleteAllLocations();
+
+ //
+ //
+ //
+ if(!GetConfiguration().KeyExists("StoreObjectInfoFile") || GetConfiguration().GetKeyValue("StoreObjectInfoFile").size() <=0)
+ return;
+
+ try
+ {
+ FileStream aFile(GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str(), O_RDONLY);
+ IOStreamArchive anArchive(aFile, 0);
+
+ //
+ // see if the content has a chance to be what we think it is
+ //
+ int iMagicValue = 0;
+ anArchive.Get(iMagicValue);
+
+ if (iMagicValue != STOREOBJECTINFO_MAGIC_ID_VALUE)
+ {
+ ::syslog(LOG_WARNING, "Store object info file '%s' is not what you think it is: no harm done, will re-cache from store", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ return;
+ }
+
+ //
+ // get a bit optimistic and read in a string identifier
+ //
+ std::string strMagicValue;
+ anArchive.Get(strMagicValue);
+
+ if (strMagicValue != STOREOBJECTINFO_MAGIC_ID_STRING)
+ {
+ ::syslog(LOG_WARNING, "Store object info file '%s' is not what you think it is: no harm done, will re-cache from store", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ return;
+ }
+
+ //
+ // ok, check if we are not loading some future development version by mistake
+ //
+ int iVersion = 0;
+ anArchive.Get(iVersion);
+
+ if (iVersion != STOREOBJECTINFO_VERSION)
+ {
+ ::syslog(LOG_WARNING, "Store object info file '%s' version [%d] unsupported: no harm done, will re-cache from store", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str(), iVersion);
+ return;
+ }
+
+ //
+ // check if this state file is even valid for the loaded bbackupd.conf file
+ //
+ box_time_t lastKnownConfigModTime;
+ anArchive.Get(lastKnownConfigModTime);
+
+ if (lastKnownConfigModTime != GetConfiguration().GetModTime())
+ {
+ ::syslog(LOG_WARNING, "Store object info file '%s' out of date: no harm done, will re-cache from store", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ return;
+ }
+
+ //
+ // this is it, go at it
+ //
+ anArchive >> aClientStoreMarker >> theLastSyncTime >> theNextSyncTime;
+
+ //
+ //
+ //
+ int64_t iCount = 0;
+ anArchive.Get(iCount);
+
+ for (int v = 0; v < iCount; v++)
+ {
+ Location* pLocation = new Location;
+ if (!pLocation)
+ throw std::bad_alloc();
+
+ pLocation->Deserialize(anArchive);
+ mLocations.push_back(pLocation);
+ }
+
+ //
+ //
+ //
+ iCount = 0;
+ anArchive.Get(iCount);
+
+ for (int v = 0; v < iCount; v++)
+ {
+ std::string strItem;
+ anArchive.Get(strItem);
+
+ mIDMapMounts.push_back(strItem);
+ }
+
+ //
+ //
+ //
+ aFile.Close();
+ ::syslog(LOG_INFO, "Loaded store object info file '%s', version [%04d]", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str(), iVersion);
+ }
+ catch (...)
+ {
+ DeleteAllLocations();
+
+ aClientStoreMarker = BackupClientContext::ClientStoreMarker_NotKnown;
+ theLastSyncTime = 0;
+ theNextSyncTime = 0;
+
+ ::syslog(LOG_WARNING, "Requested store object info file '%s' does not exist, not accessible, or inconsistent: no harm done, will re-cache from store", GetConfiguration().GetKeyValue("StoreObjectInfoFile").c_str());
+ }
+}
Modified: box/chris/bb-save-state/bin/bbackupd/BackupDaemon.h
===================================================================
--- box/chris/bb-save-state/bin/bbackupd/BackupDaemon.h 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/bin/bbackupd/BackupDaemon.h 2006-01-27 22:29:09 UTC (rev 338)
@@ -21,6 +21,8 @@
#include "SocketStream.h"
#include "WinNamedPipeStream.h"
+#include "Archive.h"
+
class BackupClientDirectoryRecord;
class BackupClientContext;
class Configuration;
@@ -41,6 +43,10 @@
public:
BackupDaemon();
~BackupDaemon();
+
+ // methods below do partial (specialized) serialization of client state only
+ void SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const;
+ void DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime);
private:
BackupDaemon(const BackupDaemon &);
public:
@@ -117,6 +123,9 @@
public:
Location();
~Location();
+
+ void Deserialize(Archive & rArchive);
+ void Serialize(Archive & rArchive) const;
private:
Location(const Location &); // copy not allowed
Location &operator=(const Location &);
Modified: box/chris/bb-save-state/lib/backupclient/BackupDaemonConfigVerify.cpp
===================================================================
--- box/chris/bb-save-state/lib/backupclient/BackupDaemonConfigVerify.cpp 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/lib/backupclient/BackupDaemonConfigVerify.cpp 2006-01-27 22:29:09 UTC (rev 338)
@@ -84,6 +84,7 @@
{"ExtendedLogging", "no", ConfigTest_IsBool, 0}, // make value "yes" to enable in config file
{"CommandSocket", 0, 0, 0}, // not compulsory to have this
+ {"StoreObjectInfoFile", 0, 0, 0}, // optional
{"NotifyScript", 0, 0, 0}, // optional script to run when backup needs attention, eg store full
@@ -102,4 +103,3 @@
ConfigTest_Exists | ConfigTest_LastEntry,
0
};
-
Modified: box/chris/bb-save-state/lib/common/Configuration.cpp
===================================================================
--- box/chris/bb-save-state/lib/common/Configuration.cpp 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/lib/common/Configuration.cpp 2006-01-27 22:29:09 UTC (rev 338)
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <limits.h>
+#include <errno.h>
#include "Configuration.h"
#include "CommonException.h"
@@ -19,6 +20,8 @@
#include "MemLeakFindOn.h"
+#include "FileModificationTime.h"
+
// utility whitespace function
inline bool iw(int c)
{
@@ -29,22 +32,19 @@
static const char *sValueBooleanStrings[] = {"yes", "true", "no", "false", 0};
static const bool sValueBooleanValue[] = {true, true, false, false};
-
-
// --------------------------------------------------------------------------
//
// Function
-// Name: Configuration::Configuration(const std::string &)
+// Name: Configuration::Configuration(const std::string &, box_time_t)
// Purpose: Constructor
// Created: 2003/07/23
//
// --------------------------------------------------------------------------
-Configuration::Configuration(const std::string &rName)
- : mName(rName)
+Configuration::Configuration(const std::string &rName, box_time_t configModTime)
+ : mName(rName), mConfigModTime(configModTime)
{
}
-
// --------------------------------------------------------------------------
//
// Function
@@ -56,7 +56,8 @@
Configuration::Configuration(const Configuration &rToCopy)
: mName(rToCopy.mName),
mSubConfigurations(rToCopy.mSubConfigurations),
- mKeys(rToCopy.mKeys)
+ mKeys(rToCopy.mKeys),
+ mConfigModTime(rToCopy.mConfigModTime)
{
}
@@ -94,6 +95,19 @@
// Just to make sure
rErrorMsg.erase();
+ // Save modification time to be able to distinguish across configuration sets
+ struct stat st;
+ if(::stat(Filename, &st) != 0)
+ {
+ // Used to THROW_EXCEPTION(CommonException, OSFileError) here
+ // but this is not the normal behaviour if the file doesn't
+ // exist
+ if (errno != ENOENT)
+ {
+ THROW_EXCEPTION(CommonException, OSFileError)
+ }
+ }
+
// Open the file
FileHandleGuard<O_RDONLY> file(Filename);
@@ -101,7 +115,7 @@
FdGetLine getline(file);
// Object to create
- Configuration *pconfig = new Configuration(std::string("<root>"));
+ Configuration *pconfig = new Configuration(std::string("<root>"), FileModificationTime(st));
try
{
@@ -176,7 +190,7 @@
if(startBlockExpected)
{
// New config object
- Configuration config(blockName);
+ Configuration config(blockName, rConfig.mConfigModTime);
// Continue processing into this block
if(!LoadInto(config, rGetLine, rErrorMsg, false))
Modified: box/chris/bb-save-state/lib/common/Configuration.h
===================================================================
--- box/chris/bb-save-state/lib/common/Configuration.h 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/lib/common/Configuration.h 2006-01-27 22:29:09 UTC (rev 338)
@@ -16,6 +16,8 @@
#include <string>
#include <memory>
+#include "BoxTime.h"
+
// For defining tests
enum
{
@@ -58,11 +60,13 @@
class Configuration
{
private:
- Configuration(const std::string &rName);
+ Configuration(const std::string &rName, box_time_t configModTime);
public:
Configuration(const Configuration &rToCopy);
~Configuration();
+ box_time_t GetModTime() const { return mConfigModTime; }
+
enum
{
// The character to separate multi-values
@@ -88,7 +92,8 @@
SubConfigListType mSubConfigurations;
// Order of keys, not preserved
std::map<std::string, std::string> mKeys;
-
+protected:
+ box_time_t mConfigModTime;
private:
static bool LoadInto(Configuration &rConfig, FdGetLine &rGetLine, std::string &rErrorMsg, bool RootLevel);
static bool Verify(Configuration &rConfig, const ConfigurationVerify &rVerify, const std::string &rLevel, std::string &rErrorMsg);
Modified: box/chris/bb-save-state/lib/common/ExcludeList.cpp
===================================================================
--- box/chris/bb-save-state/lib/common/ExcludeList.cpp 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/lib/common/ExcludeList.cpp 2006-01-27 22:29:09 UTC (rev 338)
@@ -130,6 +130,8 @@
// Store in list of regular expressions
mRegex.push_back(pregex);
+ // Store in list of regular expression string for Serialize
+ mRegexStr.push_back(i->c_str());
}
catch(...)
{
@@ -213,7 +215,169 @@
mpAlwaysInclude = pAlwaysInclude;
}
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ExcludeList::Deserialize(Archive & rArchive)
+// Purpose: Deserializes this object instance from a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void ExcludeList::Deserialize(Archive & rArchive)
+{
+ //
+ //
+ //
+ mDefinite.clear();
-
+#ifndef PLATFORM_REGEX_NOT_SUPPORTED
+ // free regex memory
+ while(mRegex.size() > 0)
+ {
+ regex_t *pregex = mRegex.back();
+ mRegex.pop_back();
+ // Free regex storage, and the structure itself
+ ::regfree(pregex);
+ delete pregex;
+ }
+ mRegexStr.clear();
+#endif
+ // Clean up exceptions list
+ if(mpAlwaysInclude != 0)
+ {
+ delete mpAlwaysInclude;
+ mpAlwaysInclude = 0;
+ }
+
+ //
+ //
+ //
+ int64_t iCount = 0;
+ rArchive.Get(iCount);
+
+ if (iCount > 0)
+ {
+ for (int v = 0; v < iCount; v++)
+ {
+ std::string strItem;
+ rArchive.Get(strItem);
+
+ /**** LOAD ****/ mDefinite.insert(strItem);
+ }
+ }
+
+ //
+ //
+ //
+#ifndef PLATFORM_REGEX_NOT_SUPPORTED
+ rArchive.Get(iCount);
+
+ if (iCount > 0)
+ {
+ for (int v = 0; v < iCount; v++)
+ {
+ std::string strItem;
+ rArchive.Get(strItem);
+
+ // Allocate memory
+ regex_t* pregex = new regex_t;
+
+ try
+ {
+ // Compile
+ if(::regcomp(pregex, strItem.c_str(), REG_EXTENDED | REG_NOSUB) != 0)
+ {
+ THROW_EXCEPTION(CommonException, BadRegularExpression)
+ }
+
+ // Store in list of regular expressions
+ /**** LOAD ****/ mRegex.push_back(pregex);
+ // Store in list of regular expression string for Serialize
+ /**** LOAD ****/ mRegexStr.push_back(strItem);
+ }
+ catch(...)
+ {
+ delete pregex;
+ throw;
+ }
+ }
+ }
+#endif // PLATFORM_REGEX_NOT_SUPPORTED
+
+ //
+ //
+ //
+ int64_t aMagicMarker = 0;
+ rArchive.Get(aMagicMarker);
+
+ if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP)
+ {
+ // NOOP
+ }
+ else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE)
+ {
+ /**** LOAD ****/ mpAlwaysInclude = new ExcludeList;
+ if (!mpAlwaysInclude)
+ throw std::bad_alloc();
+
+ mpAlwaysInclude->Deserialize(rArchive);
+ }
+ else
+ {
+ // there is something going on here
+ THROW_EXCEPTION(CommonException, Internal)
+ }
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ExcludeList::Serialize(Archive & rArchive)
+// Purpose: Serializes this object instance into a stream of bytes, using an Archive abstraction.
+//
+// Created: 2005/04/11
+//
+// --------------------------------------------------------------------------
+void ExcludeList::Serialize(Archive & rArchive) const
+{
+ //
+ //
+ //
+ int64_t iCount = mDefinite.size();
+ rArchive.Add(iCount);
+
+ for (std::set<std::string>::const_iterator i = mDefinite.begin(); i != mDefinite.end(); i++)
+ rArchive.Add(*i);
+
+ //
+ //
+ //
+#ifndef PLATFORM_REGEX_NOT_SUPPORTED
+ ASSERT(mRegex.size() == mRegexStr.size()); // don't even try to save compiled regular expressions - use string copies
+
+ iCount = mRegexStr.size();
+ rArchive.Add(iCount);
+
+ for (std::vector<std::string>::const_iterator i = mRegexStr.begin(); i != mRegexStr.end(); i++)
+ rArchive.Add(*i);
+#endif // PLATFORM_REGEX_NOT_SUPPORTED
+
+ //
+ //
+ //
+ if (!mpAlwaysInclude)
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP;
+ rArchive.Add(aMagicMarker);
+ }
+ else
+ {
+ int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_RECURSE; // be explicit about whether recursion follows
+ rArchive.Add(aMagicMarker);
+
+ mpAlwaysInclude->Serialize(rArchive);
+ }
+}
Modified: box/chris/bb-save-state/lib/common/ExcludeList.h
===================================================================
--- box/chris/bb-save-state/lib/common/ExcludeList.h 2006-01-27 22:23:29 UTC (rev 337)
+++ box/chris/bb-save-state/lib/common/ExcludeList.h 2006-01-27 22:29:09 UTC (rev 338)
@@ -19,6 +19,8 @@
typedef int regex_t;
#endif
+#include "Archive.h"
+
// --------------------------------------------------------------------------
//
// Class
@@ -33,6 +35,9 @@
ExcludeList();
~ExcludeList();
+ void Deserialize(Archive & rArchive);
+ void Serialize(Archive & rArchive) const;
+
void AddDefiniteEntries(const std::string &rEntries);
void AddRegexEntries(const std::string &rEntries);
@@ -55,6 +60,7 @@
std::set<std::string> mDefinite;
#ifdef HAVE_REGEX_H
std::vector<regex_t *> mRegex;
+ std::vector<std::string> mRegexStr; // save original regular expression string-based source for Serialize
#endif
// For exceptions to the excludes