[Box Backup-commit] COMMIT r2756 - in box/invisnet/perfhack1: bin/bbstored lib/backupclient lib/raidfile
subversion at boxbackup.org
subversion at boxbackup.org
Fri Sep 24 01:22:35 BST 2010
Author: invisnet
Date: 2010-09-24 01:22:34 +0100 (Fri, 24 Sep 2010)
New Revision: 2756
Modified:
box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.cpp
box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.h
box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp
box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h
box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.cpp
box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.h
Log:
This should fix ticket #8.
Modified: box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.cpp
===================================================================
--- box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.cpp 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.cpp 2010-09-24 00:22:34 UTC (rev 2756)
@@ -136,7 +136,7 @@
// 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
@@ -144,7 +144,7 @@
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
@@ -152,16 +152,16 @@
::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;
}
@@ -180,16 +180,16 @@
{
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
mpStoreInfo = i;
@@ -205,7 +205,7 @@
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);
}
@@ -241,7 +241,7 @@
}
}
- // Want to save now
+ // Want to save now
mpStoreInfo->Save();
// Set count for next delay
@@ -254,7 +254,7 @@
//
// Function
// Name: BackupStoreContext::MakeObjectFilename(int64_t, std::string &, bool)
-// Purpose: Create the filename of an object in the store, optionally creating the
+// 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
//
@@ -270,7 +270,7 @@
//
// Function
// Name: BackupStoreContext::GetDirectoryInternal(int64_t)
-// Purpose: Return a reference to a directory. Valid only until the
+// 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.
@@ -282,7 +282,7 @@
// 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())
@@ -293,7 +293,7 @@
{
THROW_EXCEPTION(BackupStoreException, DirectoryHasBeenDeleted)
}
-
+
if(revID == item->second->GetRevisionID())
{
// Looks good... return the cached object
@@ -302,7 +302,7 @@
" from cache, modtime = " << revID);
return *(item->second);
}
-
+
BOX_TRACE("Refreshing object " <<
BOX_FORMAT_OBJECTID(ObjectID) <<
" in cache, modtime changed from " <<
@@ -312,9 +312,9 @@
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)
{
@@ -330,15 +330,15 @@
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);
@@ -347,7 +347,7 @@
// Store in cache
BackupStoreDirectory *pdir = dir.release();
try
- {
+ {
mDirectoryCache[ObjectID] = pdir;
}
catch(...)
@@ -355,7 +355,7 @@
delete pdir;
throw;
}
-
+
// Return it
return *pdir;
}
@@ -380,12 +380,12 @@
// 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 = mpStoreInfo->AllocateObjectID();
-
+
// Generate filename
std::string filename;
MakeObjectFilename(id, filename);
@@ -395,17 +395,17 @@
// 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)
}
@@ -434,7 +434,7 @@
{
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
@@ -443,13 +443,13 @@
// 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 */);
@@ -479,19 +479,19 @@
{
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(),
+ InvisibleTempFileStream diff(tempFn.c_str(),
O_RDWR | O_CREAT | O_BINARY);
- InvisibleTempFileStream diff2(tempFn.c_str(),
+ InvisibleTempFileStream diff2(tempFn.c_str(),
O_RDWR | O_BINARY);
#else
FileStream diff(tempFn.c_str(), O_RDWR | O_CREAT | O_EXCL);
@@ -503,13 +503,13 @@
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))
@@ -523,7 +523,7 @@
// 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);
@@ -536,10 +536,10 @@
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
spaceAdjustFromDiff = from->GetDiscUsageInBlocks() - oldVersionNewBlocksUsed;
@@ -552,10 +552,10 @@
throw;
}
}
-
+
// Get the blocks used
blocksUsed = storeFile.GetDiscUsageInBlocks();
-
+
// Exceeds the hard limit?
if((mpStoreInfo->GetBlocksUsed() + blocksUsed - spaceAdjustFromDiff) > mpStoreInfo->GetBlocksHardLimit())
{
@@ -574,7 +574,7 @@
delete ppreviousVerStoreFile;
ppreviousVerStoreFile = 0;
}
-
+
throw;
}
@@ -589,12 +589,12 @@
// 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;
@@ -617,14 +617,14 @@
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
+ // 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, blocksUsed, BackupStoreDirectory::Entry::Flags_File, AttributesHash);
@@ -635,25 +635,25 @@
// 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
blocksUsed += (oldVersionNewBlocksUsed - oldSize);
blocksInOldFiles += (oldVersionNewBlocksUsed - oldSize);
}
// Write the directory back to disc
- SaveDirectory(dir, InDirectory);
+ SaveDirectory(dir, InDirectory, (0 == DiffFromFileID) /* Append last (new) entry only */ );
// Commit the old version's new patched version, now that the directory safely reflects
// the state of the files on disc.
@@ -669,35 +669,35 @@
// 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
mpStoreInfo->ChangeBlocksUsed(blocksUsed);
mpStoreInfo->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();
-
+
// Return the ID to the caller
return id;
}
@@ -753,7 +753,7 @@
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
+ // 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?
@@ -765,16 +765,16 @@
}
}
}
-
+
// Save changes?
if(madeChanges)
{
// Save the directory back
SaveDirectory(dir, InDirectory);
-
+
// Modify the store info, and write
mpStoreInfo->ChangeBlocksInDeletedFiles(blocksDel);
-
+
// Maybe postponed save of store info
SaveStoreInfo();
}
@@ -848,16 +848,16 @@
}
}
}
-
+
// Save changes?
if(madeChanges)
{
// Save the directory back
SaveDirectory(dir, InDirectory);
-
+
// Modify the store info, and write
mpStoreInfo->ChangeBlocksInDeletedFiles(blocksDel);
-
+
// Maybe postponed save of store info
SaveStoreInfo();
}
@@ -896,12 +896,12 @@
// --------------------------------------------------------------------------
//
// Function
-// Name: BackupStoreContext::SaveDirectory(BackupStoreDirectory &, int64_t)
+// Name: BackupStoreContext::SaveDirectory(BackupStoreDirectory &, int64_t, bool)
// Purpose: Save directory back to disc, update time in cache
// Created: 2003/09/04
//
// --------------------------------------------------------------------------
-void BackupStoreContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID)
+void BackupStoreContext::SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID, bool AppendLastEntryOnly)
{
if(mpStoreInfo.get() == 0)
{
@@ -919,10 +919,17 @@
MakeObjectFilename(ObjectID, dirfn);
{
RaidFileWrite writeDir(mStoreDiscSet, dirfn);
- writeDir.Open(true /* allow overwriting */);
+ writeDir.Open(true /* allow overwriting */, AppendLastEntryOnly);
BufferedWriteStream buffer(writeDir);
- rDir.WriteToStream(buffer);
+ if(AppendLastEntryOnly)
+ {
+ rDir.UpdateToStream(buffer);
+ }
+ else
+ {
+ rDir.WriteToStream(buffer);
+ }
buffer.Flush();
// get the disc usage (must do this before commiting it)
@@ -930,7 +937,7 @@
// 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();
@@ -978,10 +985,10 @@
{
THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
}
-
+
// Flags as not already existing
rAlreadyExists = false;
-
+
// Get the directory we want to modify
BackupStoreDirectory &dir(GetDirectoryInternal(InDirectory));
@@ -1011,7 +1018,7 @@
BackupStoreDirectory emptyDir(id, InDirectory);
// add the atttribues
emptyDir.SetAttributes(Attributes, AttributesModTime);
-
+
// Write...
RaidFileWrite dirFile(mStoreDiscSet, fn);
dirFile.Open(false /* no overwriting */);
@@ -1019,7 +1026,7 @@
// Get disc usage, before it's commited
int64_t dirSize = dirFile.GetDiscUsageInBlocks();
// Commit the file
- dirFile.Commit(BACKUP_STORE_CONVERT_TO_RAID_IMMEDIATELY);
+ 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);
@@ -1027,7 +1034,7 @@
mpStoreInfo->ChangeBlocksInDirectories(dirSize);
// Not added to cache, so don't set the size in the directory
}
-
+
// Then add it into the parent directory
try
{
@@ -1042,12 +1049,12 @@
// 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;
+ throw;
}
// Save the store info (may be postponed)
@@ -1079,7 +1086,7 @@
// Containing directory
int64_t InDirectory = 0;
-
+
// Count of blocks deleted
int64_t blocksDeleted = 0;
@@ -1089,18 +1096,18 @@
{
// 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),
@@ -1117,18 +1124,18 @@
{
en->AddFlags(BackupStoreDirectory::Entry::Flags_Deleted);
}
-
+
// Save it
SaveDirectory(parentDir, InDirectory);
-
+
// Done
break;
}
}
-
+
// Update blocks deleted count
mpStoreInfo->ChangeBlocksInDeletedFiles(Undelete?(0 - blocksDeleted):(blocksDeleted));
-
+
// Save store info, may be postponed
SaveStoreInfo();
}
@@ -1153,12 +1160,12 @@
{
// 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);
@@ -1181,24 +1188,24 @@
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);
+ 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
+
+ // Run through files
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en = 0;
@@ -1214,17 +1221,17 @@
{
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)
{
@@ -1261,13 +1268,13 @@
}
try
- {
+ {
// Get the directory we want to modify
BackupStoreDirectory &dir(GetDirectoryInternal(Directory));
-
+
// Set attributes
dir.SetAttributes(Attributes, AttributesModTime);
-
+
// Save back
SaveDirectory(dir, Directory);
}
@@ -1296,12 +1303,12 @@
{
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
@@ -1315,10 +1322,10 @@
{
// Set attributes
en->SetAttributes(Attributes, AttributesHash);
-
+
// Tell caller the object ID
rObjectIDOut = en->GetObjectID();
-
+
// Done
break;
}
@@ -1328,7 +1335,7 @@
// Didn't find it
return false;
}
-
+
// Save back
SaveDirectory(dir, InDirectory);
}
@@ -1337,7 +1344,7 @@
RemoveDirectoryFromCache(InDirectory);
throw;
}
-
+
// Changed, everything OK
return true;
}
@@ -1357,7 +1364,7 @@
{
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.
@@ -1366,7 +1373,7 @@
// Obviously bad object ID
return false;
}
-
+
// Test to see if it exists on the disc
std::string filename;
MakeObjectFilename(ObjectID, filename);
@@ -1375,7 +1382,7 @@
// RaidFile reports no file there
return false;
}
-
+
// Do we need to be more specific?
if(MustBe != ObjectExists_Anything)
{
@@ -1400,16 +1407,16 @@
// 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;
}
@@ -1428,7 +1435,7 @@
{
THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
}
-
+
// Attempt to open the file
std::string fn;
MakeObjectFilename(ObjectID, fn);
@@ -1450,7 +1457,7 @@
{
THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
}
-
+
return mpStoreInfo->GetClientStoreMarker();
}
@@ -1513,7 +1520,7 @@
{
THROW_EXCEPTION(BackupStoreException, ContextIsReadOnly)
}
-
+
mpStoreInfo->SetClientStoreMarker(ClientStoreMarker);
SaveStoreInfo(false /* don't delay saving this */);
}
@@ -1538,7 +1545,7 @@
int64_t targetSearchExcludeFlags = (AllowMoveOverDeletedObject)
?(BackupStoreDirectory::Entry::Flags_Deleted)
:(BackupStoreDirectory::Entry::Flags_EXCLUDE_NOTHING);
-
+
// Special case if the directories are the same...
if(MoveFromDirectory == MoveToDirectory)
{
@@ -1546,16 +1553,16 @@
{
// 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);
@@ -1568,7 +1575,7 @@
}
}
}
-
+
// Need to get all the entries with the same name?
if(MoveAllWithSameName)
{
@@ -1589,7 +1596,7 @@
// Just copy this one
en->SetName(rNewFilename);
}
-
+
// Save the directory back
SaveDirectory(dir, MoveFromDirectory);
}
@@ -1598,7 +1605,7 @@
RemoveDirectoryFromCache(MoveToDirectory); // either will do, as they're the same
throw;
}
-
+
return;
}
@@ -1607,27 +1614,27 @@
// 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)
{
@@ -1640,7 +1647,7 @@
{
// 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());
}
@@ -1656,13 +1663,13 @@
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);
@@ -1675,7 +1682,7 @@
}
}
}
-
+
// Copy the entries into it, changing the name as we go
for(std::vector<BackupStoreDirectory::Entry *>::iterator i(moving.begin()); i != moving.end(); ++i)
{
@@ -1683,7 +1690,7 @@
en->SetName(rNewFilename);
to.AddEntry(*en); // adds copy
}
-
+
// Save back
SaveDirectory(to, MoveToDirectory);
}
@@ -1693,57 +1700,57 @@
{
// 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);
+ 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
+ // 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);
+ RemoveDirectoryFromCache(*i);
}
while(!moving.empty())
@@ -1752,7 +1759,7 @@
moving.pop_back();
}
throw;
- }
+ }
// Clean up
while(!moving.empty())
@@ -1778,7 +1785,7 @@
{
THROW_EXCEPTION(BackupStoreException, StoreInfoNotLoaded)
}
-
+
return *(mpStoreInfo.get());
}
Modified: box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.h
===================================================================
--- box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.h 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/bin/bbstored/BackupStoreContext.h 2010-09-24 00:22:34 UTC (rev 2756)
@@ -63,10 +63,10 @@
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();
@@ -84,7 +84,7 @@
// 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();
@@ -94,7 +94,7 @@
//
// Function
// Name: BackupStoreContext::GetDirectory(int64_t)
- // Purpose: Return a reference to a directory. Valid only until the
+ // 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
@@ -106,7 +106,7 @@
// 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);
@@ -126,14 +126,14 @@
};
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 SaveDirectory(BackupStoreDirectory &rDir, int64_t ObjectID, bool AppendLastEntryOnly = false);
void RemoveDirectoryFromCache(int64_t ObjectID);
void DeleteDirectoryRecurse(int64_t ObjectID, int64_t &rBlocksDeletedOut, bool Undelete);
int64_t AllocateObjectID();
@@ -147,13 +147,13 @@
bool mReadOnly;
NamedLock mWriteLock;
int mSaveStoreInfoDelay; // how many times to delay saving the store info
-
+
// Store info
std::auto_ptr<BackupStoreInfo> mpStoreInfo;
// Refcount database
std::auto_ptr<BackupStoreRefCountDatabase> mapRefCount;
-
+
// Directory cache
std::map<int64_t, BackupStoreDirectory*> mDirectoryCache;
Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp
===================================================================
--- box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.cpp 2010-09-24 00:22:34 UTC (rev 2756)
@@ -267,7 +267,55 @@
}
}
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: BackupStoreDirectory::UpdateToStream(IOStream &, int16_t, int16_t, bool, bool)
+// Purpose: Writes the header to a stream
+// Created: 2010/09/23
+//
+// --------------------------------------------------------------------------
+void BackupStoreDirectory::UpdateToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const
+{
+ // Check that sensible IDs have been set
+ ASSERT(mObjectID != 0);
+ ASSERT(mContainerID != 0);
+ Entry *pen = mEntries.back();
+
+ if( FlagsMustBeSet == Entry::Flags_INCLUDE_EVERYTHING
+ && FlagsNotToBeSet == Entry::Flags_EXCLUDE_NOTHING
+ && !HasDependencyInfo()
+ && ( (!StreamDependencyInfo && !HasDependencyInfoInline()) || (StreamDependencyInfo && HasDependencyInfoInline() == pen->HasDependencies()) ) )
+ {
+ BOX_TRACE("Appending to directory");
+
+ WriteHeaderToStream(rStream, mEntries.size(), mOptions);
+
+ // Write the attributes?
+ if(StreamAttributes)
+ {
+ mAttributes.WriteToStream(rStream);
+ }
+ else
+ {
+ // Write a blank header instead
+ StreamableMemBlock::WriteEmptyBlockToStream(rStream);
+ }
+
+ rStream.Seek(0, IOStream::SeekType_End);
+ pen->WriteToStream(rStream);
+ if(HasDependencyInfoInline())
+ {
+ pen->WriteToStreamDependencyInfo(rStream);
+ }
+ }
+ else
+ {
+ WriteToStream(rStream, FlagsMustBeSet, FlagsNotToBeSet, StreamAttributes, StreamDependencyInfo);
+ }
+}
+
// --------------------------------------------------------------------------
//
// Function
Modified: box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h
===================================================================
--- box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/lib/backupclient/BackupStoreDirectory.h 2010-09-24 00:22:34 UTC (rev 2756)
@@ -130,6 +130,10 @@
int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING,
int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING,
bool StreamAttributes = true, bool StreamDependencyInfo = true) const;
+ void UpdateToStream(IOStream &rStream,
+ int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING,
+ int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING,
+ bool StreamAttributes = true, bool StreamDependencyInfo = true) const;
void WriteHeaderToStream(IOStream &rStream, int32_t Count, int32_t Options) const;
Entry *AddEntry(const Entry &rEntryToCopy);
Modified: box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.cpp
===================================================================
--- box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.cpp 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.cpp 2010-09-24 00:22:34 UTC (rev 2756)
@@ -108,8 +108,10 @@
// Created: 2003/07/10
//
// --------------------------------------------------------------------------
-void RaidFileWrite::Open(bool AllowOverwrite)
+void RaidFileWrite::Open(bool AllowOverwrite, bool UpdateOnly)
{
+ ASSERT( !(AllowOverwrite && UpdateOnly) );
+
if(mOSFileHandle != -1)
{
THROW_EXCEPTION(RaidFileException, AlreadyOpen)
@@ -134,8 +136,11 @@
// Get the filename for the write file
std::string writeFilename(RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename));
- // Add on a temporary extension
- writeFilename += 'X';
+ if(!UpdateOnly)
+ {
+ // Add on a temporary extension
+ writeFilename += 'X';
+ }
// Attempt to open
mOSFileHandle = ::open(writeFilename.c_str(),
@@ -181,12 +186,16 @@
}
}
- // Truncate it to size zero
- if(::ftruncate(mOSFileHandle, 0) != 0)
+ if(!UpdateOnly)
{
- THROW_EXCEPTION(RaidFileException, ErrorOpeningWriteFileOnTruncate)
+ // Truncate it to size zero
+ if(::ftruncate(mOSFileHandle, 0) != 0)
+ {
+ THROW_EXCEPTION(RaidFileException, ErrorOpeningWriteFileOnTruncate)
+ }
}
+ mUpdateOnly = UpdateOnly;
// Done!
}
@@ -290,40 +299,43 @@
RequestedModifyUnreferencedFile);
}
- // Rename it into place -- BEFORE it's closed so lock remains
+ if(!mUpdateOnly)
+ {
+ // Rename it into place -- BEFORE it's closed so lock remains
#ifdef WIN32
- // Except on Win32 which doesn't allow renaming open files
- // Close file...
- if(::close(mOSFileHandle) != 0)
- {
- THROW_EXCEPTION(RaidFileException, OSError)
- }
- mOSFileHandle = -1;
+ // Except on Win32 which doesn't allow renaming open files
+ // Close file...
+ if(::close(mOSFileHandle) != 0)
+ {
+ THROW_EXCEPTION(RaidFileException, OSError)
+ }
+ mOSFileHandle = -1;
#endif // WIN32
- RaidFileController &rcontroller(RaidFileController::GetController());
- RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(mSetNumber));
- // Get the filename for the write file
- std::string renameTo(RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename));
- // And the current name
- std::string renameFrom(renameTo + 'X');
+ RaidFileController &rcontroller(RaidFileController::GetController());
+ RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(mSetNumber));
+ // Get the filename for the write file
+ std::string renameTo(RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename));
+ // And the current name
+ std::string renameFrom(renameTo + 'X');
#ifdef WIN32
- // need to delete the target first
- if(::unlink(renameTo.c_str()) != 0 &&
- GetLastError() != ERROR_FILE_NOT_FOUND)
- {
- BOX_LOG_WIN_ERROR("Failed to delete file: " << renameTo);
- THROW_EXCEPTION(RaidFileException, OSError)
- }
+ // need to delete the target first
+ if(::unlink(renameTo.c_str()) != 0 &&
+ GetLastError() != ERROR_FILE_NOT_FOUND)
+ {
+ BOX_LOG_WIN_ERROR("Failed to delete file: " << renameTo);
+ THROW_EXCEPTION(RaidFileException, OSError)
+ }
#endif
- if(::rename(renameFrom.c_str(), renameTo.c_str()) != 0)
- {
- BOX_LOG_SYS_ERROR("Failed to rename file: " << renameFrom <<
- " to " << renameTo);
- THROW_EXCEPTION(RaidFileException, OSError)
+ if(::rename(renameFrom.c_str(), renameTo.c_str()) != 0)
+ {
+ BOX_LOG_SYS_ERROR("Failed to rename file: " << renameFrom <<
+ " to " << renameTo);
+ THROW_EXCEPTION(RaidFileException, OSError)
+ }
}
#ifndef WIN32
Modified: box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.h
===================================================================
--- box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.h 2010-09-23 00:10:41 UTC (rev 2755)
+++ box/invisnet/perfhack1/lib/raidfile/RaidFileWrite.h 2010-09-24 00:22:34 UTC (rev 2756)
@@ -44,17 +44,17 @@
virtual bool StreamClosed();
// Extra bits
- void Open(bool AllowOverwrite = false);
+ void Open(bool AllowOverwrite = false, bool UpdateOnly = false);
void Commit(bool ConvertToRaidNow = false);
void Discard();
void TransformToRaidStorage();
void Delete();
pos_type GetFileSize();
pos_type GetDiscUsageInBlocks();
-
+
static void CreateDirectory(int SetNumber, const std::string &rDirName, bool Recursive = false, int mode = 0777);
static void CreateDirectory(const RaidFileDiscSet &rSet, const std::string &rDirName, bool Recursive = false, int mode = 0777);
-
+
private:
private:
@@ -62,6 +62,7 @@
std::string mFilename;
int mOSFileHandle;
int mRefCount;
+ bool mUpdateOnly;
};
#endif // RAIDFILEWRITE__H
More information about the Boxbackup-commit
mailing list