From subversion at boxbackup.org Wed Aug 21 01:57:18 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 21 Aug 2013 01:57:18 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3169 - box/trunk/lib/backupstore Message-ID: <201308210057.r7L0vI0N063680@wm.boxbackup.org> Author: chris Date: 2013-08-21 01:57:17 +0100 (Wed, 21 Aug 2013) New Revision: 3169 Modified: box/trunk/lib/backupstore/BackupClientFileAttributes.cpp box/trunk/lib/backupstore/BackupClientFileAttributes.h box/trunk/lib/backupstore/BackupStoreFile.cpp box/trunk/lib/backupstore/BackupStoreFile.h box/trunk/lib/backupstore/BackupStoreFileDiff.cpp box/trunk/lib/backupstore/BackupStoreFileEncodeStream.cpp box/trunk/lib/backupstore/BackupStoreFileEncodeStream.h Log: Pass std::strings to functions instead of const char *, for C++ style. Modified: box/trunk/lib/backupstore/BackupClientFileAttributes.cpp =================================================================== --- box/trunk/lib/backupstore/BackupClientFileAttributes.cpp 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupClientFileAttributes.cpp 2013-08-21 00:57:17 UTC (rev 3169) @@ -364,7 +364,7 @@ // Created: 2003/10/07 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::ReadAttributes(const char *Filename, +void BackupClientFileAttributes::ReadAttributes(const std::string& Filename, bool ZeroModificationTimes, box_time_t *pModTime, box_time_t *pAttrModTime, int64_t *pFileSize, InodeRefType *pInodeNumber, bool *pHasMultipleLinks) @@ -373,7 +373,7 @@ try { EMU_STRUCT_STAT st; - if(EMU_LSTAT(Filename, &st) != 0) + if(EMU_LSTAT(Filename.c_str(), &st) != 0) { THROW_SYS_FILE_ERROR("Failed to stat file", Filename, CommonException, OSFileError) @@ -465,7 +465,7 @@ // // -------------------------------------------------------------------------- void BackupClientFileAttributes::FillAttributes( - StreamableMemBlock &outputBlock, const char *Filename, + StreamableMemBlock &outputBlock, const std::string& rFilename, const EMU_STRUCT_STAT &st, bool ZeroModificationTimes ) { @@ -508,14 +508,16 @@ // Created: 2003/10/07 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::FillAttributesLink(StreamableMemBlock &outputBlock, const char *Filename, struct stat &st) +void BackupClientFileAttributes::FillAttributesLink( + StreamableMemBlock &outputBlock, const std::string& Filename, + struct stat &st) { // Make sure we're only called for symbolic links ASSERT((st.st_mode & S_IFMT) == S_IFLNK); // Get the filename the link is linked to char linkedTo[PATH_MAX+4]; - int linkedToSize = ::readlink(Filename, linkedTo, PATH_MAX); + int linkedToSize = ::readlink(Filename.c_str(), linkedTo, PATH_MAX); if(linkedToSize == -1) { BOX_LOG_SYS_ERROR("Failed to readlink '" << Filename << "'"); @@ -540,7 +542,8 @@ // Created: 2005/06/12 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBlock, const char *Filename) +void BackupClientFileAttributes::FillExtendedAttr(StreamableMemBlock &outputBlock, + const std::string& Filename) { #ifdef HAVE_SYS_XATTR_H int listBufferSize = 10000; @@ -550,13 +553,13 @@ { // This returns an unordered list of attribute names, each 0 terminated, // concatenated together - int listSize = ::llistxattr(Filename, list, listBufferSize); + int listSize = ::llistxattr(Filename.c_str(), list, listBufferSize); if(listSize>listBufferSize) { delete[] list, list = NULL; list = new char[listSize]; - listSize = ::llistxattr(Filename, list, listSize); + listSize = ::llistxattr(Filename.c_str(), list, listSize); } if(listSize>0) @@ -606,7 +609,7 @@ // Find size of attribute (must call with buffer and length 0 on some platforms, // as -1 is returned if the data doesn't fit.) - int valueSize = ::lgetxattr(Filename, attrKey.c_str(), 0, 0); + int valueSize = ::lgetxattr(Filename.c_str(), attrKey.c_str(), 0, 0); if(valueSize<0) { BOX_LOG_SYS_ERROR("Failed to get " @@ -625,7 +628,9 @@ } // This gets the attribute value (may be text or binary), no termination - valueSize = ::lgetxattr(Filename, attrKey.c_str(), buffer+xattrSize, xattrBufferSize-xattrSize); + valueSize = ::lgetxattr(Filename.c_str(), + attrKey.c_str(), buffer+xattrSize, + xattrBufferSize-xattrSize); if(valueSize<0) { BOX_LOG_SYS_ERROR("Failed to get " @@ -742,7 +747,7 @@ // Created: 2003/10/07 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::WriteAttributes(const char *Filename, +void BackupClientFileAttributes::WriteAttributes(const std::string& Filename, bool MakeUserWritable) const { // Got something loaded @@ -795,8 +800,8 @@ Filename << "'"); #else // Make a symlink, first deleting anything in the way - ::unlink(Filename); - if(::symlink((char*)(pattr + 1), Filename) != 0) + ::unlink(Filename.c_str()); + if(::symlink((char*)(pattr + 1), Filename.c_str()) != 0) { BOX_LOG_SYS_ERROR("Failed to symlink '" << Filename << "' to '" << (char*)(pattr + 1) << "'"); @@ -815,7 +820,7 @@ if((mode & S_IFMT) != S_IFLNK) { // Not a link, use normal chown - if(::chown(Filename, ntohl(pattr->UID), ntohl(pattr->GID)) != 0) + if(::chown(Filename.c_str(), ntohl(pattr->UID), ntohl(pattr->GID)) != 0) { BOX_LOG_SYS_ERROR("Failed to change " "owner of file " @@ -825,7 +830,7 @@ } #else // use the version which sets things on symlinks - if(::lchown(Filename, ntohl(pattr->UID), ntohl(pattr->GID)) != 0) + if(::lchown(Filename.c_str(), ntohl(pattr->UID), ntohl(pattr->GID)) != 0) { BOX_LOG_SYS_ERROR("Failed to change owner of " "symbolic link '" << Filename << "'"); @@ -871,7 +876,7 @@ #endif // Try to apply - if(::utimes(Filename, times) != 0) + if(::utimes(Filename.c_str(), times) != 0) { BOX_LOG_SYS_WARNING("Failed to change times of " "file '" << Filename << "' to ctime=" << @@ -887,8 +892,8 @@ // Apply everything else... (allowable mode flags only) // Mode must be done last (think setuid) - if(::chmod(Filename, mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID - | S_ISGID | S_ISVTX)) != 0) + if(::chmod(Filename.c_str(), mode & (S_IRWXU | S_IRWXG | S_IRWXO | + S_ISUID | S_ISGID | S_ISVTX)) != 0) { BOX_LOG_SYS_ERROR("Failed to change permissions of file " "'" << Filename << "'"); @@ -971,7 +976,7 @@ // Created: 2005/06/13 // // -------------------------------------------------------------------------- -void BackupClientFileAttributes::WriteExtendedAttr(const char *Filename, int xattrOffset) const +void BackupClientFileAttributes::WriteExtendedAttr(const std::string& Filename, int xattrOffset) const { #ifdef HAVE_SYS_XATTR_H const char* buffer = static_cast(mpClearAttributes->GetBuffer()); @@ -1004,7 +1009,8 @@ xattrOffset += sizeof(u_int32_t); // FIXME: Warn on EOPNOTSUPP - if(::lsetxattr(Filename, key, buffer+xattrOffset, valueSize, 0)!=0 && errno!=EOPNOTSUPP) + if(::lsetxattr(Filename.c_str(), key, buffer+xattrOffset, + valueSize, 0)!=0 && errno!=EOPNOTSUPP) { BOX_LOG_SYS_ERROR("Failed to set extended attributes " "on file '" << Filename << "'"); Modified: box/trunk/lib/backupstore/BackupClientFileAttributes.h =================================================================== --- box/trunk/lib/backupstore/BackupClientFileAttributes.h 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupClientFileAttributes.h 2013-08-21 00:57:17 UTC (rev 3169) @@ -43,10 +43,10 @@ // Prevent access to base class members accidently void Set(); - void ReadAttributes(const char *Filename, bool ZeroModificationTimes = false, + void ReadAttributes(const std::string& Filename, bool ZeroModificationTimes = false, box_time_t *pModTime = 0, box_time_t *pAttrModTime = 0, int64_t *pFileSize = 0, InodeRefType *pInodeNumber = 0, bool *pHasMultipleLinks = 0); - void WriteAttributes(const char *Filename, + void WriteAttributes(const std::string& Filename, bool MakeUserWritable = false) const; void GetModificationTimes(box_time_t *pModificationTime, box_time_t *pAttrModificationTime) const; @@ -56,15 +56,18 @@ static void SetBlowfishKey(const void *pKey, int KeyLength); static void SetAttributeHashSecret(const void *pSecret, int SecretLength); - static uint64_t GenerateAttributeHash(EMU_STRUCT_STAT &st, const std::string &filename, const std::string &leafname); - static void FillExtendedAttr(StreamableMemBlock &outputBlock, const char *Filename); + static uint64_t GenerateAttributeHash(EMU_STRUCT_STAT &st, + const std::string& Filename, const std::string &leafname); + static void FillExtendedAttr(StreamableMemBlock &outputBlock, + const std::string& Filename); private: static void FillAttributes(StreamableMemBlock &outputBlock, - const char *Filename, const EMU_STRUCT_STAT &st, + const std::string& Filename, const EMU_STRUCT_STAT &st, bool ZeroModificationTimes); - static void FillAttributesLink(StreamableMemBlock &outputBlock, const char *Filename, struct stat &st); - void WriteExtendedAttr(const char *Filename, int xattrOffset) const; + static void FillAttributesLink(StreamableMemBlock &outputBlock, + const std::string& Filename, struct stat &st); + void WriteExtendedAttr(const std::string& Filename, int xattrOffset) const; void RemoveClear() const; void EnsureClearAvailable() const; Modified: box/trunk/lib/backupstore/BackupStoreFile.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreFile.cpp 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupStoreFile.cpp 2013-08-21 00:57:17 UTC (rev 3169) @@ -74,7 +74,7 @@ // // -------------------------------------------------------------------------- std::auto_ptr BackupStoreFile::EncodeFile( - const char *Filename, int64_t ContainerID, + const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime, ReadLoggingStream::Logger* pLogger, Modified: box/trunk/lib/backupstore/BackupStoreFile.h =================================================================== --- box/trunk/lib/backupstore/BackupStoreFile.h 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupStoreFile.h 2013-08-21 00:57:17 UTC (rev 3169) @@ -121,7 +121,7 @@ // Main interface static std::auto_ptr EncodeFile ( - const char *Filename, + const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime = 0, ReadLoggingStream::Logger* pLogger = NULL, @@ -129,7 +129,7 @@ ); static std::auto_ptr EncodeFileDiff ( - const char *Filename, int64_t ContainerID, + const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t DiffFromObjectID, IOStream &rDiffFromBlockIndex, int Timeout, Modified: box/trunk/lib/backupstore/BackupStoreFileDiff.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreFileDiff.cpp 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupStoreFileDiff.cpp 2013-08-21 00:57:17 UTC (rev 3169) @@ -125,7 +125,7 @@ // -------------------------------------------------------------------------- std::auto_ptr BackupStoreFile::EncodeFileDiff ( - const char *Filename, int64_t ContainerID, + const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t DiffFromObjectID, IOStream &rDiffFromBlockIndex, int Timeout, DiffTimer *pDiffTimer, int64_t *pModificationTime, bool *pIsCompletelyDifferent) @@ -133,7 +133,7 @@ // Is it a symlink? { EMU_STRUCT_STAT st; - if(EMU_LSTAT(Filename, &st) != 0) + if(EMU_LSTAT(Filename.c_str(), &st) != 0) { THROW_EXCEPTION(CommonException, OSFileError) } Modified: box/trunk/lib/backupstore/BackupStoreFileEncodeStream.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreFileEncodeStream.cpp 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupStoreFileEncodeStream.cpp 2013-08-21 00:57:17 UTC (rev 3169) @@ -111,7 +111,7 @@ // Created: 8/12/03 // // -------------------------------------------------------------------------- -void BackupStoreFileEncodeStream::Setup(const char *Filename, +void BackupStoreFileEncodeStream::Setup(const std::string& Filename, BackupStoreFileEncodeStream::Recipe *pRecipe, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime, ReadLoggingStream::Logger* pLogger, Modified: box/trunk/lib/backupstore/BackupStoreFileEncodeStream.h =================================================================== --- box/trunk/lib/backupstore/BackupStoreFileEncodeStream.h 2013-02-13 00:27:54 UTC (rev 3168) +++ box/trunk/lib/backupstore/BackupStoreFileEncodeStream.h 2013-08-21 00:57:17 UTC (rev 3169) @@ -75,7 +75,7 @@ int64_t mOtherFileID; }; - void Setup(const char *Filename, Recipe *pRecipe, int64_t ContainerID, + void Setup(const std::string& Filename, Recipe *pRecipe, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime, ReadLoggingStream::Logger* pLogger = NULL, From subversion at boxbackup.org Wed Aug 21 02:00:23 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 21 Aug 2013 02:00:23 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3170 - box/trunk/lib/backupstore Message-ID: <201308210100.r7L10NG8063723@wm.boxbackup.org> Author: chris Date: 2013-08-21 02:00:23 +0100 (Wed, 21 Aug 2013) New Revision: 3170 Modified: box/trunk/lib/backupstore/BackupStoreContext.h Log: Allow getting the name of the current phase of a BackupStoreContext. Useful for debugging when the phase is not as expected. Modified: box/trunk/lib/backupstore/BackupStoreContext.h =================================================================== --- box/trunk/lib/backupstore/BackupStoreContext.h 2013-08-21 00:57:17 UTC (rev 3169) +++ box/trunk/lib/backupstore/BackupStoreContext.h 2013-08-21 01:00:23 UTC (rev 3170) @@ -66,6 +66,19 @@ }; int GetPhase() const {return mProtocolPhase;} + std::string GetPhaseName() const + { + switch(mProtocolPhase) + { + case Phase_Version: return "Phase_Version"; + case Phase_Login: return "Phase_Login"; + case Phase_Commands: return "Phase_Commands"; + default: + std::ostringstream oss; + oss << "Unknown phase " << mProtocolPhase; + return oss.str(); + } + } void SetPhase(int NewPhase) {mProtocolPhase = NewPhase;} // Read only locking From subversion at boxbackup.org Wed Aug 21 23:45:37 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Wed, 21 Aug 2013 23:45:37 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3171 - box/trunk/infrastructure Message-ID: <201308212245.r7LMjbIu070744@wm.boxbackup.org> Author: chris Date: 2013-08-21 23:45:36 +0100 (Wed, 21 Aug 2013) New Revision: 3171 Modified: box/trunk/infrastructure/buildenv-testmain-template.cpp Log: Add support for the -W option to test runner executable. Modified: box/trunk/infrastructure/buildenv-testmain-template.cpp =================================================================== --- box/trunk/infrastructure/buildenv-testmain-template.cpp 2013-08-21 01:00:23 UTC (rev 3170) +++ box/trunk/infrastructure/buildenv-testmain-template.cpp 2013-08-21 22:45:36 UTC (rev 3171) @@ -248,7 +248,7 @@ int ch; - while ((ch = getopt_long(argc, argv, "c:d:qs:t:vPTUV", longopts, NULL)) + while ((ch = getopt_long(argc, argv, "c:d:qs:t:vPTUVW:", longopts, NULL)) != -1) { switch(ch) @@ -320,6 +320,17 @@ } break; + case 'W': + { + logLevel = Logging::GetNamedLevel(optarg); + if (logLevel == Log::INVALID) + { + BOX_FATAL("Invalid logging level: " << optarg); + return 2; + } + } + break; + case 't': { Logging::SetProgramName(optarg); From subversion at boxbackup.org Thu Aug 22 00:44:13 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 00:44:13 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3172 - box/trunk/lib/server Message-ID: <201308212344.r7LNiDj4071040@wm.boxbackup.org> Author: chris Date: 2013-08-22 00:44:12 +0100 (Thu, 22 Aug 2013) New Revision: 3172 Modified: box/trunk/lib/server/makeprotocol.pl.in Log: Add a ToString() method on protocol objects, to help with debugging them. Modified: box/trunk/lib/server/makeprotocol.pl.in =================================================================== --- box/trunk/lib/server/makeprotocol.pl.in 2013-08-21 22:45:36 UTC (rev 3171) +++ box/trunk/lib/server/makeprotocol.pl.in 2013-08-21 23:44:12 UTC (rev 3172) @@ -342,6 +342,7 @@ print H "\tvirtual void LogSysLog(const char *Action) const;\n"; print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n"; + print H "\tvirtual std::string ToString() const;\n"; # write member variables and setup for cpp file my @def_constructor_list; @@ -467,31 +468,34 @@ my ($log) = make_log_strings_framework($cmd); print CPP <<__E; -void $cmd_class\::LogSysLog(const char *Action) const +std::string $cmd_class\::ToString() const { + std::ostringstream oss; try { - BOX_TRACE($log); + oss << $log; } catch(std::exception &e) { - BOX_WARNING("Failed to log command: " << Action << ": " << - e.what()); + oss << "Failed to log command: " << e.what(); } + return oss.str(); } -void $cmd_class\::LogFile(const char *Action, FILE *File) const +void $cmd_class\::LogSysLog(const char *Action) const { - std::ostringstream oss; try { - oss << $log; + BOX_TRACE(Action << " " << $log); } catch(std::exception &e) { - oss << "Failed to log command: " << Action << ": " << - e.what(); + BOX_WARNING("Failed to log command: " << Action << ": " << + e.what()); } - ::fprintf(File, "%s\\n", oss.str().c_str()); +} +void $cmd_class\::LogFile(const char *Action, FILE *File) const +{ + ::fprintf(File, "%s %s\\n", Action, ToString().c_str()); ::fflush(File); } __E @@ -1184,7 +1188,7 @@ } } - my $log_cmd = "Action << \" $cmd(\" "; + my $log_cmd = '"'.$cmd.'(" '; foreach my $arg (@args) { $arg = "<< $arg "; From subversion at boxbackup.org Thu Aug 22 01:17:34 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:17:34 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3173 - in box/trunk: bin/bbackupd lib/backupstore lib/server Message-ID: <201308220017.r7M0HYk8071212@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:17:34 +0100 (Thu, 22 Aug 2013) New Revision: 3173 Modified: box/trunk/bin/bbackupd/BackupClientDirectoryRecord.cpp box/trunk/bin/bbackupd/BackupDaemon.cpp box/trunk/lib/backupstore/BackupCommands.cpp box/trunk/lib/backupstore/BackupStoreFile.cpp box/trunk/lib/backupstore/BackupStoreFile.h box/trunk/lib/backupstore/BackupStoreFileDiff.cpp box/trunk/lib/server/makeprotocol.pl.in Log: Pass std::auto_ptr objects to Protocol for upload. Passing raw pointers is bad C++ style, and dangerous, because Protocol will free the passed-in pointers after uploading them, so we should not keep using them. Reduce code duplication in BackupClientDirectoryRecord patch/normal upload. Return a std::auto_ptr instead of a std::auto_ptr from BackupStoreFile::EncodeFile* functions. Modified: box/trunk/bin/bbackupd/BackupClientDirectoryRecord.cpp =================================================================== --- box/trunk/bin/bbackupd/BackupClientDirectoryRecord.cpp 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/bin/bbackupd/BackupClientDirectoryRecord.cpp 2013-08-22 00:17:34 UTC (rev 3173) @@ -28,6 +28,7 @@ #include "BackupStoreException.h" #include "BackupStoreFile.h" #include "BackupStoreFileEncodeStream.h" +#include "BufferedStream.h" #include "CommonException.h" #include "CollectInBufferStream.h" #include "FileModificationTime.h" @@ -727,7 +728,7 @@ BackupProtocolClient &connection(rParams.mrContext.GetConnection()); // Exception thrown if this doesn't work - MemBlockStream attrStream(attr); + std::auto_ptr attrStream(new MemBlockStream(attr)); connection.QueryChangeDirAttributes(mObjectID, attrModTime, attrStream); } } @@ -1195,8 +1196,10 @@ // Update store BackupClientFileAttributes attr; - attr.ReadAttributes(filename.c_str(), false /* put mod times in the attributes, please */); - MemBlockStream attrStream(attr); + attr.ReadAttributes(filename, + false /* put mod times in the attributes, please */); + std::auto_ptr attrStream( + new MemBlockStream(attr)); connection.QuerySetReplacementFileAttributes(mObjectID, attributesHash, storeFilename, attrStream); fileSynced = true; } @@ -1458,7 +1461,7 @@ // in the else if(...) above will be correct. // Build attribute stream for sending - MemBlockStream attrStream(attr); + std::auto_ptr attrStream(new MemBlockStream(attr)); if(renameDir) { @@ -1688,12 +1691,14 @@ // Info int64_t objID = 0; - bool doNormalUpload = true; int64_t uploadedSize = -1; // Use a try block to catch store full errors try { + std::auto_ptr apStreamToUpload; + int64_t diffFromID = 0; + // Might an old version be on the server, and is the file // size over the diffing threshold? if(!NoPreviousVersionOnServer && @@ -1702,7 +1707,7 @@ // YES -- try to do diff, if possible // First, query the server to see if there's an old version available std::auto_ptr getBlockIndex(connection.QueryGetBlockIndexByName(mObjectID, rStoreFilename)); - int64_t diffFromID = getBlockIndex->GetObjectID(); + diffFromID = getBlockIndex->GetObjectID(); if(diffFromID != 0) { @@ -1721,95 +1726,67 @@ bool isCompletelyDifferent = false; - std::auto_ptr patchStream( - BackupStoreFile::EncodeFileDiff( - rFilename.c_str(), - mObjectID, /* containing directory */ - rStoreFilename, diffFromID, *blockIndexStream, - connection.GetTimeout(), - &rContext, // DiffTimer implementation - 0 /* not interested in the modification time */, - &isCompletelyDifferent)); - - rContext.UnManageDiffProcess(); - rContext.SetNiceMode(true); + apStreamToUpload = BackupStoreFile::EncodeFileDiff( + rFilename, + mObjectID, /* containing directory */ + rStoreFilename, diffFromID, *blockIndexStream, + connection.GetTimeout(), + &rContext, // DiffTimer implementation + 0 /* not interested in the modification time */, + &isCompletelyDifferent); - RateLimitingStream rateLimit(*patchStream, - rParams.mMaxUploadRate); - IOStream* pStreamToUpload; - - if(rParams.mMaxUploadRate > 0) + if(isCompletelyDifferent) { - pStreamToUpload = &rateLimit; + diffFromID = 0; } - else - { - pStreamToUpload = patchStream.get(); - } - - // - // Upload the patch to the store - // - std::auto_ptr stored(connection.QueryStoreFile(mObjectID, ModificationTime, - AttributesHash, isCompletelyDifferent?(0):(diffFromID), rStoreFilename, *pStreamToUpload)); - - rContext.SetNiceMode(false); - - // Get object ID from the result - objID = stored->GetObjectID(); - - // Don't attempt to upload it again! - doNormalUpload = false; - - // Capture number of bytes sent - uploadedSize = ((BackupStoreFileEncodeStream &) - *patchStream).GetTotalBytesSent(); + + rContext.UnManageDiffProcess(); } } - if(doNormalUpload) + if(!apStreamToUpload.get()) // No patch upload, so do a normal upload { // below threshold or nothing to diff from, so upload whole rNotifier.NotifyFileUploading(this, rNonVssFilePath); // Prepare to upload, getting a stream which will encode the file as we go along - std::auto_ptr upload( - BackupStoreFile::EncodeFile(rFilename.c_str(), - mObjectID, rStoreFilename, NULL, - &rParams, - &(rParams.mrRunStatusProvider))); + apStreamToUpload = BackupStoreFile::EncodeFile( + rFilename, mObjectID, /* containing directory */ + rStoreFilename, NULL, &rParams, + &(rParams.mrRunStatusProvider)); + } - rContext.SetNiceMode(true); + rContext.SetNiceMode(true); + std::auto_ptr apWrappedStream; - RateLimitingStream rateLimit(*upload, - rParams.mMaxUploadRate); - IOStream* pStreamToUpload; + if(rParams.mMaxUploadRate > 0) + { + apWrappedStream.reset(new RateLimitingStream( + *apStreamToUpload, rParams.mMaxUploadRate)); + } + else + { + // Wrap the stream in *something*, so that + // QueryStoreFile() doesn't delete the original + // stream (upload object) and we can retrieve + // the byte counter. + apWrappedStream.reset(new BufferedStream( + *apStreamToUpload)); + } - if(rParams.mMaxUploadRate > 0) - { - pStreamToUpload = &rateLimit; - } - else - { - pStreamToUpload = upload.get(); - } - - // Send to store - std::auto_ptr stored( - connection.QueryStoreFile( - mObjectID, ModificationTime, - AttributesHash, - 0 /* no diff from file ID */, - rStoreFilename, *pStreamToUpload)); + // Send to store + std::auto_ptr stored( + connection.QueryStoreFile( + mObjectID, ModificationTime, + AttributesHash, + diffFromID, + rStoreFilename, apWrappedStream)); - rContext.SetNiceMode(false); - - // Get object ID from the result - objID = stored->GetObjectID(); + rContext.SetNiceMode(false); - uploadedSize = ((BackupStoreFileEncodeStream &) - *upload).GetTotalBytesSent(); - } + // Get object ID from the result + objID = stored->GetObjectID(); + uploadedSize = apStreamToUpload->GetTotalBytesSent(); } catch(BoxException &e) { Modified: box/trunk/bin/bbackupd/BackupDaemon.cpp =================================================================== --- box/trunk/bin/bbackupd/BackupDaemon.cpp 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/bin/bbackupd/BackupDaemon.cpp 2013-08-22 00:17:34 UTC (rev 3173) @@ -2460,7 +2460,8 @@ // Execute create directory command try { - MemBlockStream attrStream(attr); + std::auto_ptr attrStream( + new MemBlockStream(attr)); std::auto_ptr dirCreate(connection.QueryCreateDirectory( BackupProtocolListDirectory::RootDirectory, Modified: box/trunk/lib/backupstore/BackupCommands.cpp =================================================================== --- box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-22 00:17:34 UTC (rev 3173) @@ -207,7 +207,7 @@ stream->SetForReading(); // Get the protocol to send the stream - rProtocol.SendStreamAfterCommand(stream.release()); + rProtocol.SendStreamAfterCommand(static_cast< std::auto_ptr > (stream)); return std::auto_ptr( new BackupProtocolSuccess(mObjectID)); @@ -300,7 +300,7 @@ std::auto_ptr object(rContext.OpenObject(mObjectID)); // Stream it to the peer - rProtocol.SendStreamAfterCommand(object.release()); + rProtocol.SendStreamAfterCommand(object); // Tell the caller what the file was return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); @@ -463,11 +463,8 @@ } // Stream the reordered stream to the peer - rProtocol.SendStreamAfterCommand(stream.get()); + rProtocol.SendStreamAfterCommand(stream); - // Don't delete the stream here - stream.release(); - // Tell the caller what the file was return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); } @@ -831,7 +828,7 @@ // Get the stream ready to go stream->SetForReading(); // Tell the protocol to send the stream - rProtocol.SendStreamAfterCommand(stream.release()); + rProtocol.SendStreamAfterCommand(static_cast< std::auto_ptr >(stream)); } // Make reply @@ -859,7 +856,7 @@ BackupStoreFile::MoveStreamPositionToBlockIndex(*stream); // Return the stream to the client - rProtocol.SendStreamAfterCommand(stream.release()); + rProtocol.SendStreamAfterCommand(stream); // Return the object ID return std::auto_ptr(new BackupProtocolSuccess(mObjectID)); @@ -911,7 +908,7 @@ BackupStoreFile::MoveStreamPositionToBlockIndex(*stream); // Return the stream to the client - rProtocol.SendStreamAfterCommand(stream.release()); + rProtocol.SendStreamAfterCommand(stream); // Return the object ID return std::auto_ptr(new BackupProtocolSuccess(objectID)); Modified: box/trunk/lib/backupstore/BackupStoreFile.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreFile.cpp 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/lib/backupstore/BackupStoreFile.cpp 2013-08-22 00:17:34 UTC (rev 3173) @@ -73,7 +73,7 @@ // Created: 2003/08/28 // // -------------------------------------------------------------------------- -std::auto_ptr BackupStoreFile::EncodeFile( +std::auto_ptr BackupStoreFile::EncodeFile( const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t *pModificationTime, @@ -81,13 +81,12 @@ RunStatusProvider* pRunStatusProvider) { // Create the stream - std::auto_ptr stream(new BackupStoreFileEncodeStream); + std::auto_ptr stream( + new BackupStoreFileEncodeStream); // Do the initial setup - ((BackupStoreFileEncodeStream*)stream.get())->Setup(Filename, - 0 /* no recipe, just encode */, - ContainerID, rStoreFilename, pModificationTime, pLogger, - pRunStatusProvider); + stream->Setup(Filename, 0 /* no recipe, just encode */, ContainerID, + rStoreFilename, pModificationTime, pLogger, pRunStatusProvider); // Return the stream for the caller return stream; Modified: box/trunk/lib/backupstore/BackupStoreFile.h =================================================================== --- box/trunk/lib/backupstore/BackupStoreFile.h 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/lib/backupstore/BackupStoreFile.h 2013-08-22 00:17:34 UTC (rev 3173) @@ -60,6 +60,8 @@ virtual bool IsManaged() = 0; }; +class BackupStoreFileEncodeStream; + // -------------------------------------------------------------------------- // // Class @@ -119,7 +121,7 @@ // Main interface - static std::auto_ptr EncodeFile + static std::auto_ptr EncodeFile ( const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, @@ -127,7 +129,7 @@ ReadLoggingStream::Logger* pLogger = NULL, RunStatusProvider* pRunStatusProvider = NULL ); - static std::auto_ptr EncodeFileDiff + static std::auto_ptr EncodeFileDiff ( const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, Modified: box/trunk/lib/backupstore/BackupStoreFileDiff.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreFileDiff.cpp 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/lib/backupstore/BackupStoreFileDiff.cpp 2013-08-22 00:17:34 UTC (rev 3173) @@ -123,7 +123,7 @@ // Created: 12/1/04 // // -------------------------------------------------------------------------- -std::auto_ptr BackupStoreFile::EncodeFileDiff +std::auto_ptr BackupStoreFile::EncodeFileDiff ( const std::string& Filename, int64_t ContainerID, const BackupStoreFilename &rStoreFilename, int64_t DiffFromObjectID, @@ -206,10 +206,11 @@ // foundBlocks no longer required // Create the stream - std::auto_ptr stream(new BackupStoreFileEncodeStream); + std::auto_ptr stream( + new BackupStoreFileEncodeStream); // Do the initial setup - ((BackupStoreFileEncodeStream*)stream.get())->Setup(Filename, precipe, ContainerID, rStoreFilename, pModificationTime); + stream->Setup(Filename, precipe, ContainerID, rStoreFilename, pModificationTime); precipe = 0; // Stream has taken ownership of this // Tell user about completely different status? Modified: box/trunk/lib/server/makeprotocol.pl.in =================================================================== --- box/trunk/lib/server/makeprotocol.pl.in 2013-08-21 23:44:12 UTC (rev 3172) +++ box/trunk/lib/server/makeprotocol.pl.in 2013-08-22 00:17:34 UTC (rev 3173) @@ -541,7 +541,7 @@ virtual std::auto_ptr ReceiveStream() = 0; virtual int GetTimeout() = 0; - void SendStreamAfterCommand(IOStream *pStream); + void SendStreamAfterCommand(std::auto_ptr apStream); protected: std::list mStreamsToSend; @@ -573,10 +573,10 @@ $replyable_base_class\::~$replyable_base_class() { } -void $replyable_base_class\::SendStreamAfterCommand(IOStream *pStream) +void $replyable_base_class\::SendStreamAfterCommand(std::auto_ptr apStream) { - ASSERT(pStream != NULL); - mStreamsToSend.push_back(pStream); + ASSERT(apStream.get() != NULL); + mStreamsToSend.push_back(apStream.release()); } void $replyable_base_class\::DeleteStreamsToSend() @@ -585,6 +585,7 @@ { delete (*i); } + mStreamsToSend.clear(); } @@ -668,8 +669,8 @@ if(obj_is_type($cmd,'Command')) { my $has_stream = obj_is_type($cmd,'StreamWithCommand'); - my $argextra = $has_stream?', IOStream &rStream':''; - my $queryextra = $has_stream?', rStream':''; + my $argextra = $has_stream?', std::auto_ptr apStream':''; + my $queryextra = $has_stream?', apStream':''; my $request_class = $cmd_class{$cmd}; my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')}; @@ -772,8 +773,8 @@ if(obj_is_type($cmd,'Command')) { my $has_stream = obj_is_type($cmd,'StreamWithCommand'); - my $argextra = $has_stream?', IOStream &rStream':''; - my $queryextra = $has_stream?', rStream':''; + my $argextra = $has_stream?', std::auto_ptr apStream':''; + my $queryextra = $has_stream?', apStream':''; my $request_class = $cmd_class{$cmd}; my $reply_class = $cmd_class{obj_get_type_params($cmd,'Command')}; print H "\tstd::auto_ptr<$reply_class> Query(const $request_class &rQuery$argextra);\n"; @@ -1021,7 +1022,7 @@ my $reply_class = $cmd_class{$reply_msg}; my $reply_id = $cmd_id{$reply_msg}; my $has_stream = obj_is_type($cmd,'StreamWithCommand'); - my $argextra = $has_stream?', IOStream &rStream':''; + my $argextra = $has_stream?', std::auto_ptr apStream':''; my $send_stream_extra = ''; my $send_stream_method = $writing_client ? "SendStream" : "SendStreamAfterCommand"; @@ -1032,7 +1033,7 @@ { $send_stream_extra = <<__E; // Send stream after the command - SendStream(rStream); + SendStream(*apStream); __E } @@ -1059,7 +1060,7 @@ { $send_stream_extra = <<__E; // Send stream after the command - SendStreamAfterCommand(&rStream); + SendStreamAfterCommand(apStream); __E } From subversion at boxbackup.org Thu Aug 22 01:19:20 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:19:20 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3174 - box/trunk/test/backupstorefix Message-ID: <201308220019.r7M0JKcE071233@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:19:20 +0100 (Thu, 22 Aug 2013) New Revision: 3174 Modified: box/trunk/test/backupstorefix/testbackupstorefix.cpp Log: Refactor testbackupstorefix. Preparation work for better testing of fixing directories with entries that no longer exist on disk. Related to debugging the problems reported by Markus Grunwald. Modified: box/trunk/test/backupstorefix/testbackupstorefix.cpp =================================================================== --- box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:17:34 UTC (rev 3173) +++ box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:19:20 UTC (rev 3174) @@ -17,20 +17,25 @@ #include #include "Test.h" +#include "BackupClientCryptoKeys.h" #include "BackupStoreCheck.h" #include "BackupStoreConstants.h" +#include "BackupStoreContext.h" #include "BackupStoreDirectory.h" +#include "BackupStoreException.h" #include "BackupStoreFile.h" +#include "BackupStoreFileWire.h" +#include "BackupStoreFileEncodeStream.h" +#include "BackupStoreInfo.h" +#include "BufferedWriteStream.h" #include "FileStream.h" #include "RaidFileController.h" +#include "RaidFileException.h" +#include "RaidFileRead.h" #include "RaidFileWrite.h" -#include "RaidFileRead.h" -#include "BackupStoreInfo.h" -#include "BackupStoreException.h" -#include "RaidFileException.h" +#include "ServerControl.h" #include "StoreStructure.h" -#include "BackupStoreFileWire.h" -#include "ServerControl.h" +#include "ZeroStream.h" #include "MemLeakFindOn.h" @@ -147,7 +152,9 @@ while((en = i.Next()) != 0) { - TEST_THAT(ck->name != -1); + BackupStoreFilenameClear clear(en->GetName()); + TEST_LINE(ck->name != -1, "Unexpected entry found in " + "directory: " << clear.GetClearFilename()); if(ck->name == -1) { break; @@ -179,9 +186,12 @@ { break; } - TEST_THAT(en->GetObjectID() == ck->id); - TEST_THAT(en->GetDependsNewer() == ck->depNewer); - TEST_THAT(en->GetDependsOlder() == ck->depOlder); + TEST_EQUAL_LINE(ck->id, en->GetObjectID(), "Wrong object ID " + "for " << BOX_FORMAT_OBJECTID(ck->id)); + TEST_EQUAL_LINE(ck->depNewer, en->GetDependsNewer(), + "Wrong Newer dependency for " << BOX_FORMAT_OBJECTID(ck->id)); + TEST_EQUAL_LINE(ck->depOlder, en->GetDependsOlder(), + "Wrong Older dependency for " << BOX_FORMAT_OBJECTID(ck->id)); ++ck; } @@ -283,14 +293,61 @@ } } +int64_t fake_upload(BackupProtocolLocal& client, const std::string& file_path, + int64_t diff_from_id) +{ + std::auto_ptr upload; + if(diff_from_id) + { + std::auto_ptr getBlockIndex( + client.QueryGetBlockIndexByName( + BACKUPSTORE_ROOT_DIRECTORY_ID, fnames[0])); + std::auto_ptr blockIndexStream(client.ReceiveStream()); + upload = BackupStoreFile::EncodeFileDiff( + file_path, + BACKUPSTORE_ROOT_DIRECTORY_ID, fnames[0], + diff_from_id, *blockIndexStream, + IOStream::TimeOutInfinite, + NULL, // DiffTimer implementation + 0 /* not interested in the modification time */, + NULL // isCompletelyDifferent + ); + } + else + { + upload = BackupStoreFile::EncodeFile( + file_path, + BACKUPSTORE_ROOT_DIRECTORY_ID, fnames[0], + NULL, + NULL, // pLogger + NULL // pRunStatusProvider + ); + } + + return client.QueryStoreFile(BACKUPSTORE_ROOT_DIRECTORY_ID, + 1, // ModificationTime + 2, // AttributesHash + diff_from_id, // DiffFromFileID + fnames[0], // rFilename + upload)->GetObjectID(); +} + int test(int argc, const char *argv[]) { + { + MEMLEAKFINDER_NO_LEAKS; + fnames[0].SetAsClearFilename("x1"); + fnames[1].SetAsClearFilename("x2"); + fnames[2].SetAsClearFilename("x3"); + } + // Test the backupstore directory fixing test_dir_fixing(); // Initialise the raidfile controller RaidFileController &rcontroller = RaidFileController::GetController(); rcontroller.Initialise("testfiles/raidfile.conf"); + BackupClientCryptoKeys_Setup("testfiles/bbackupd.keys"); // Create an account TEST_THAT_ABORTONFAIL(::system(BBSTOREACCOUNTS From subversion at boxbackup.org Thu Aug 22 01:24:19 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:24:19 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3175 - box/trunk/lib/backupstore Message-ID: <201308220024.r7M0OJ6c071278@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:24:19 +0100 (Thu, 22 Aug 2013) New Revision: 3175 Modified: box/trunk/lib/backupstore/BackupCommands.cpp Log: Improve error messages from BackupCommands. When a command is sent in the wrong phase, or a command that requires write access is sent to a read-only session, log an error message with the command details (and current phase in the former case). Modified: box/trunk/lib/backupstore/BackupCommands.cpp =================================================================== --- box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-22 00:19:20 UTC (rev 3174) +++ box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-22 00:24:19 UTC (rev 3175) @@ -38,12 +38,17 @@ #define CHECK_PHASE(phase) \ if(rContext.GetPhase() != BackupStoreContext::phase) \ { \ + BOX_ERROR("Received command " << ToString() << " " \ + "in wrong protocol phase " << rContext.GetPhaseName() << ", " \ + "expected in " #phase); \ return PROTOCOL_ERROR(Err_NotInRightProtocolPhase); \ } #define CHECK_WRITEABLE_SESSION \ if(rContext.SessionIsReadOnly()) \ { \ + BOX_ERROR("Received command " << ToString() << " " \ + "in a read-only session"); \ return PROTOCOL_ERROR(Err_SessionReadOnly); \ } From subversion at boxbackup.org Thu Aug 22 01:24:25 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:24:25 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3176 - box/trunk/lib/backupstore Message-ID: <201308220024.r7M0OPf5071294@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:24:24 +0100 (Thu, 22 Aug 2013) New Revision: 3176 Modified: box/trunk/lib/backupstore/BackupCommands.cpp Log: Improve variable names and comments. Makes the source code more readable. Modified: box/trunk/lib/backupstore/BackupCommands.cpp =================================================================== --- box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-22 00:24:19 UTC (rev 3175) +++ box/trunk/lib/backupstore/BackupCommands.cpp 2013-08-22 00:24:24 UTC (rev 3176) @@ -249,13 +249,13 @@ } // A stream follows, which contains the file - std::auto_ptr dirstream(rProtocol.ReceiveStream()); + std::auto_ptr filestream(rProtocol.ReceiveStream()); // Ask the context to store it int64_t id = 0; try { - id = rContext.AddFile(*dirstream, mDirectoryObjectID, + id = rContext.AddFile(*filestream, mDirectoryObjectID, mModificationTime, mAttributesHash, mDiffFromFileID, mFilename, true /* mark files with same name as old versions */); @@ -276,7 +276,7 @@ } } - // Tell the caller what the file was + // Tell the caller what the file ID was return std::auto_ptr(new BackupProtocolSuccess(id)); } From subversion at boxbackup.org Thu Aug 22 01:28:23 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:28:23 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3177 - in box/trunk: lib/backupstore test/backupstorefix Message-ID: <201308220028.r7M0SNWF071326@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:28:23 +0100 (Thu, 22 Aug 2013) New Revision: 3177 Modified: box/trunk/lib/backupstore/BackupStoreCheck2.cpp box/trunk/test/backupstorefix/testbackupstorefix.cpp Log: Fix a bug where bbstoreaccounts check could hang or crash. It's not safe to use an iterator after the underlying collection has been modified. We need to restart iterating over the directory in that case. Otherwise we could loop forever looking for an end() that we've already passed, or start accessing unallocated memory. Modified: box/trunk/lib/backupstore/BackupStoreCheck2.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreCheck2.cpp 2013-08-22 00:24:24 UTC (rev 3176) +++ box/trunk/lib/backupstore/BackupStoreCheck2.cpp 2013-08-22 00:28:23 UTC (rev 3177) @@ -706,7 +706,12 @@ bool changed = false; // Check that if a file depends on a new version, that version is in this directory + bool restart; + + do { + restart = false; + std::vector::iterator i(mEntries.begin()); for(; i != mEntries.end(); ++i) { @@ -717,7 +722,7 @@ if(newerEn == 0) { // Depends on something, but it isn't there. - BOX_TRACE("Entry id " << FMT_i << + BOX_WARNING("Entry id " << FMT_i << " removed because depends " "on newer version " << FMT_OID(dependsNewer) << @@ -727,11 +732,12 @@ delete *i; mEntries.erase(i); - // Start again at the beginning of the vector, the iterator is now invalid - i = mEntries.begin(); - // Mark as changed changed = true; + + // Start again at the beginning of the vector, the iterator is now invalid + restart = true; + break; } else { @@ -753,6 +759,7 @@ } } } + while(restart); // Check that if a file has a dependency marked, it exists, and remove it if it doesn't { Modified: box/trunk/test/backupstorefix/testbackupstorefix.cpp =================================================================== --- box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:24:24 UTC (rev 3176) +++ box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:28:23 UTC (rev 3177) @@ -201,19 +201,35 @@ void test_dir_fixing() { + // Test that entries pointing to nonexistent entries are removed { - MEMLEAKFINDER_NO_LEAKS; - fnames[0].SetAsClearFilename("x1"); - fnames[1].SetAsClearFilename("x2"); - fnames[2].SetAsClearFilename("x3"); + BackupStoreDirectory dir; + BackupStoreDirectory::Entry* e = dir.AddEntry(fnames[0], 12, + 2 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion, 2); + e->SetDependsNewer(3); + + TEST_THAT(dir.CheckAndFix() == true); + TEST_THAT(dir.CheckAndFix() == false); + + dir_en_check ck[] = { + {-1, 0, 0} + }; + + check_dir(dir, ck); } { BackupStoreDirectory dir; - dir.AddEntry(fnames[0], 12, 2 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2); - dir.AddEntry(fnames[1], 12, 2 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2); - dir.AddEntry(fnames[0], 12, 3 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2); - dir.AddEntry(fnames[0], 12, 5 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2); + dir.AddEntry(fnames[0], 12, 2 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File, 2); + dir.AddEntry(fnames[1], 12, 2 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File, 2); + dir.AddEntry(fnames[0], 12, 3 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File, 2); + dir.AddEntry(fnames[0], 12, 5 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion, 2); dir_en_check ck[] = { {1, 2, BackupStoreDirectory::Entry::Flags_File}, @@ -250,20 +266,26 @@ // Test dependency fixing { BackupStoreDirectory dir; - BackupStoreDirectory::Entry *e2 - = dir.AddEntry(fnames[0], 12, 2 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2); + BackupStoreDirectory::Entry *e2 = dir.AddEntry(fnames[0], 12, + 2 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion, 2); TEST_THAT(e2 != 0); e2->SetDependsNewer(3); - BackupStoreDirectory::Entry *e3 - = dir.AddEntry(fnames[0], 12, 3 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2); + BackupStoreDirectory::Entry *e3 = dir.AddEntry(fnames[0], 12, + 3 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion, 2); TEST_THAT(e3 != 0); e3->SetDependsNewer(4); e3->SetDependsOlder(2); - BackupStoreDirectory::Entry *e4 - = dir.AddEntry(fnames[0], 12, 4 /* id */, 1, BackupStoreDirectory::Entry::Flags_File | BackupStoreDirectory::Entry::Flags_OldVersion, 2); + BackupStoreDirectory::Entry *e4 = dir.AddEntry(fnames[0], 12, + 4 /* id */, 1, + BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion, 2); TEST_THAT(e4 != 0); e4->SetDependsNewer(5); e4->SetDependsOlder(3); - BackupStoreDirectory::Entry *e5 - = dir.AddEntry(fnames[0], 12, 5 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2); + BackupStoreDirectory::Entry *e5 = dir.AddEntry(fnames[0], 12, + 5 /* id */, 1, BackupStoreDirectory::Entry::Flags_File, 2); TEST_THAT(e5 != 0); e5->SetDependsOlder(4); @@ -355,7 +377,167 @@ "create 01234567 0 10000B 20000B") == 0); TestRemoteProcessMemLeaks("bbstoreaccounts.memleaks"); + // Run the perl script to create the initial directories + TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE + " testfiles/testbackupstorefix.pl init") == 0); + + BOX_INFO("Test that an entry pointing to a file that doesn't exist " + "is really deleted"); + + { + // Check that the initial situation matches our expectations. + std::string rootDirName; + StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, + discSetNum, rootDirName, + true /* EnsureDirectoryExists */); + std::auto_ptr file(RaidFileRead::Open(discSetNum, + rootDirName)); + + file = RaidFileRead::Open(discSetNum, rootDirName); + BackupStoreDirectory dir; + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + dir_en_check start_entries[] = {{-1, 0, 0}}; + check_dir(dir, start_entries); + static checkdepinfoen start_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, start_deps); + + BackupStoreContext ctx(0x01234567, + *(HousekeepingInterface *)NULL, + "test" /* rConnectionDetails */); + ctx.SetClientHasAccount(storeRoot, discSetNum); + + BackupProtocolLocal client(ctx); + client.QueryVersion(BACKUP_STORE_SERVER_VERSION); + client.QueryLogin(0x01234567, 0 /* read/write */); + + std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats"; + int x1id = fake_upload(client, file_path, 0); + + file = RaidFileRead::Open(discSetNum, rootDirName); + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + + // Everything should be OK at the moment + TEST_THAT(dir.CheckAndFix() == false); + + // Check that we've ended up with the right preconditions + // for the tests below. + dir_en_check before_entries[] = { + {0, x1id, BackupStoreDirectory::Entry::Flags_File}, + {-1, 0, 0} + }; + check_dir(dir, before_entries); + static checkdepinfoen before_deps[] = {{x1id, 0, 0}, {-1, 0, 0}}; + check_dir_dep(dir, before_deps); + + // Now break the reverse dependency by deleting x1 (the file, + // not the directory entry) + std::string x1FileName; + StoreStructure::MakeObjectFilename(x1id, storeRoot, discSetNum, + x1FileName, true /* EnsureDirectoryExists */); + RaidFileWrite deleteX1(discSetNum, x1FileName); + deleteX1.Delete(); + + // Check the store, check that the error is detected and + // repaired, by removing x1 from the directory. + BackupStoreCheck check(storeRoot, discSetNum, + 0x01234567 /* AccountID */, true /* FixErrors */, + false /* Quiet */); + check.Check(); + + // Read the directory back in, check that it's empty + file = RaidFileRead::Open(discSetNum, rootDirName); + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + dir_en_check after_entries[] = {{-1, 0, 0}}; + check_dir(dir, after_entries); + static checkdepinfoen after_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, after_deps); + } + + BOX_INFO("Test that an entry pointing to another that doesn't exist " + "is really deleted"); + + { + // Check that the initial situation matches our expectations. + std::string rootDirName; + StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, + discSetNum, rootDirName, + true /* EnsureDirectoryExists */); + std::auto_ptr file(RaidFileRead::Open(discSetNum, + rootDirName)); + + file = RaidFileRead::Open(discSetNum, rootDirName); + BackupStoreDirectory dir; + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + dir_en_check start_entries[] = {{-1, 0, 0}}; + check_dir(dir, start_entries); + static checkdepinfoen start_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, start_deps); + + BackupStoreContext ctx(0x01234567, + *(HousekeepingInterface *)NULL, + "test" /* rConnectionDetails */); + ctx.SetClientHasAccount(storeRoot, discSetNum); + + BackupProtocolLocal client(ctx); + client.QueryVersion(BACKUP_STORE_SERVER_VERSION); + client.QueryLogin(0x01234567, 0 /* read/write */); + + std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats"; + int x1id = fake_upload(client, file_path, 0); + + // Make a small change to the file + FileStream fs(file_path, O_WRONLY | O_APPEND); + const char* more = " and more oats!"; + fs.Write(more, strlen(more)); + fs.Close(); + + int x1aid = fake_upload(client, file_path, x1id); + file = RaidFileRead::Open(discSetNum, rootDirName); + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + + // Everything should be OK at the moment + TEST_THAT(dir.CheckAndFix() == false); + + // Check that we've ended up with the right preconditions + // for the tests below. + dir_en_check before_entries[] = { + {0, x1id, BackupStoreDirectory::Entry::Flags_File | + BackupStoreDirectory::Entry::Flags_OldVersion}, + {0, x1aid, BackupStoreDirectory::Entry::Flags_File}, + {-1, 0, 0} + }; + check_dir(dir, before_entries); + static checkdepinfoen before_deps[] = {{x1id, x1aid, 0}, + {x1aid, 0, x1id}, {-1, 0, 0}}; + check_dir_dep(dir, before_deps); + + // Now break the reverse dependency by deleting x1a (the file, + // not the directory entry) + std::string x1aFileName; + StoreStructure::MakeObjectFilename(x1aid, storeRoot, discSetNum, + x1aFileName, true /* EnsureDirectoryExists */); + RaidFileWrite deleteX1a(discSetNum, x1aFileName); + deleteX1a.Delete(); + + // Check the store, check that the error is detected and + // repaired, by removing x1 from the directory. + BackupStoreCheck check(storeRoot, discSetNum, + 0x01234567 /* AccountID */, true /* FixErrors */, + false /* Quiet */); + check.Check(); + + // Read the directory back in, check that it's empty + file = RaidFileRead::Open(discSetNum, rootDirName); + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + dir_en_check after_entries[] = {{-1, 0, 0}}; + check_dir(dir, after_entries); + static checkdepinfoen after_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, after_deps); + } + // Start the bbstored server + BOX_TRACE("Starting bbstored server: " BBSTORED + " testfiles/bbstored.conf"); int bbstored_pid = LaunchServer(BBSTORED " testfiles/bbstored.conf", "testfiles/bbstored.pid"); TEST_THAT(bbstored_pid > 0); @@ -364,10 +546,6 @@ ::sleep(1); TEST_THAT(ServerIsAlive(bbstored_pid)); - // Run the perl script to create the initial directories - TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE - " testfiles/testbackupstorefix.pl init") == 0); - std::string cmd = BBACKUPD " " + bbackupd_args + " testfiles/bbackupd.conf"; int bbackupd_pid = LaunchServer(cmd, "testfiles/bbackupd.pid"); @@ -420,8 +598,13 @@ BackupStoreCheck checker(storeRoot, discSetNum, 0x01234567, true /* FixErrors */, false /* Quiet */); checker.Check(); - TEST_EQUAL(1, checker.GetNumErrorsFound()); + // Should just be greater than 1 really, we don't know quite + // how good the checker is (or will become) at spotting errors! + // But this will help us catch changes in checker behaviour, + // so it's not a bad thing to test. + TEST_EQUAL(5, checker.GetNumErrorsFound()); + file = RaidFileRead::Open(discSetNum, fn); dir.ReadFromStream(*file, IOStream::TimeOutInfinite); TEST_THAT(dir.FindEntryByID(0x1234567890123456LL) == 0); From subversion at boxbackup.org Thu Aug 22 01:31:58 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:31:58 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3178 - box/trunk/lib/backupstore Message-ID: <201308220031.r7M0VwcE071365@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:31:57 +0100 (Thu, 22 Aug 2013) New Revision: 3178 Modified: box/trunk/lib/backupstore/BackupStoreCheck.cpp Log: Improve debugging messages after repairing a directory. Report whether the directory still had errors after the first pass of dir.CheckAndFix(), and also whether a file is marked as both Old and Deleted, which means that its block usage is not accounted for anywhere. There's possibly still a bug here where an invalid directory entry that is itself a directory may not result in the parent directory being marked as isModified and written back out afterwards, which may be what's happening to Markus Grunwald (failure to correct the error with "check fix"). Modified: box/trunk/lib/backupstore/BackupStoreCheck.cpp =================================================================== --- box/trunk/lib/backupstore/BackupStoreCheck.cpp 2013-08-22 00:28:23 UTC (rev 3177) +++ box/trunk/lib/backupstore/BackupStoreCheck.cpp 2013-08-22 00:31:57 UTC (rev 3178) @@ -653,20 +653,21 @@ *en, pblock->mID[e], iIndex, isModified); } + // Item can't be found. Is it a directory? + else if(en->IsDir()) + { + // Store the directory for later attention + mDirsWhichContainLostDirs[en->GetObjectID()] = pblock->mID[e]; + } else { - // Item can't be found. Is it a directory? - if(en->IsDir()) - { - // Store the directory for later attention - mDirsWhichContainLostDirs[en->GetObjectID()] = pblock->mID[e]; - } - else - { - // Just remove the entry - badEntry = true; - BOX_WARNING("Directory ID " << BOX_FORMAT_OBJECTID(pblock->mID[e]) << " references object " << BOX_FORMAT_OBJECTID(en->GetObjectID()) << " which does not exist."); - } + // Just remove the entry + badEntry = true; + BOX_WARNING("Directory ID " << + BOX_FORMAT_OBJECTID(pblock->mID[e]) << + " references object " << + BOX_FORMAT_OBJECTID(en->GetObjectID()) << + " which does not exist."); } // Is this entry worth keeping? @@ -674,23 +675,32 @@ { toDelete.push_back(en->GetObjectID()); } - else if (en->IsFile()) + else if(!en->IsFile()) { - // Add to sizes? - if(en->IsOld()) - { - mBlocksInOldFiles += en->GetSizeInBlocks(); - } - if(en->IsDeleted()) - { - mBlocksInDeletedFiles += en->GetSizeInBlocks(); - } - if(!en->IsOld() && - !en->IsDeleted()) - { - mBlocksInCurrentFiles += en->GetSizeInBlocks(); - } + BOX_TRACE("Not counting object " << + BOX_FORMAT_OBJECTID(en->GetObjectID()) << + " with flags " << en->GetFlags()); } + else // it's a good file, add to sizes + if(en->IsOld() && en->IsDeleted()) + { + BOX_WARNING("File " << + BOX_FORMAT_OBJECTID(en->GetObjectID()) << + " is both old and deleted, " + "this should not happen!"); + } + else if(en->IsOld()) + { + mBlocksInOldFiles += en->GetSizeInBlocks(); + } + else if(en->IsDeleted()) + { + mBlocksInDeletedFiles += en->GetSizeInBlocks(); + } + else + { + mBlocksInCurrentFiles += en->GetSizeInBlocks(); + } } if(toDelete.size() > 0) @@ -704,11 +714,25 @@ // Mark as modified isModified = true; - // Check the directory again, now that entries have been removed - dir.CheckAndFix(); - // Errors found ++mNumberErrorsFound; + + // Check the directory again, now that entries have been removed + if(dir.CheckAndFix()) + { + // Wasn't quite right, and has been modified + BOX_WARNING("Directory ID " << + BOX_FORMAT_OBJECTID(pblock->mID[e]) << + " was still bad after first pass"); + ++mNumberErrorsFound; + isModified = true; + } + else + { + BOX_INFO("Directory ID " << + BOX_FORMAT_OBJECTID(pblock->mID[e]) << + " was OK after fixing"); + } } if(isModified && mFixErrors) From subversion at boxbackup.org Thu Aug 22 01:48:42 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Thu, 22 Aug 2013 01:48:42 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3179 - box/trunk/test/backupstorefix Message-ID: <201308220048.r7M0mgD9071469@wm.boxbackup.org> Author: chris Date: 2013-08-22 01:48:41 +0100 (Thu, 22 Aug 2013) New Revision: 3179 Modified: box/trunk/test/backupstorefix/testbackupstorefix.cpp Log: Re-enable test_dir_fixing. Modified: box/trunk/test/backupstorefix/testbackupstorefix.cpp =================================================================== --- box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:31:57 UTC (rev 3178) +++ box/trunk/test/backupstorefix/testbackupstorefix.cpp 2013-08-22 00:48:41 UTC (rev 3179) @@ -364,7 +364,7 @@ } // Test the backupstore directory fixing - test_dir_fixing(); + // FIXME reenable: test_dir_fixing(); // Initialise the raidfile controller RaidFileController &rcontroller = RaidFileController::GetController(); From subversion at boxbackup.org Sun Aug 25 10:51:08 2013 From: subversion at boxbackup.org (subversion at boxbackup.org) Date: Sun, 25 Aug 2013 10:51:08 +0100 (BST) Subject: [Box Backup-commit] COMMIT r3180 - in box/trunk/lib: common server Message-ID: <201308250951.r7P9p8m8083358@wm.boxbackup.org> Author: chris Date: 2013-08-25 10:51:07 +0100 (Sun, 25 Aug 2013) New Revision: 3180 Modified: box/trunk/lib/common/BoxConfig-MSVC.h box/trunk/lib/server/Daemon.cpp Log: Set process title on Windows. Thanks to Arnaud for submitting the patch: "I propose a little patch to enable the SetProcessTitle function on windows system." Modified: box/trunk/lib/common/BoxConfig-MSVC.h =================================================================== --- box/trunk/lib/common/BoxConfig-MSVC.h 2013-08-22 00:48:41 UTC (rev 3179) +++ box/trunk/lib/common/BoxConfig-MSVC.h 2013-08-25 09:51:07 UTC (rev 3180) @@ -185,7 +185,7 @@ /* Define to 1 if you have the `setproctitle' function. */ /* #undef HAVE_SETPROCTITLE */ - +#define HAVE_SETPROCTITLE 1 /* Define to 1 if you have the `setxattr' function. */ /* #undef HAVE_SETXATTR */ Modified: box/trunk/lib/server/Daemon.cpp =================================================================== --- box/trunk/lib/server/Daemon.cpp 2013-08-22 00:48:41 UTC (rev 3179) +++ box/trunk/lib/server/Daemon.cpp 2013-08-25 09:51:07 UTC (rev 3180) @@ -1025,9 +1025,14 @@ char title[256]; ::vsnprintf(title, sizeof(title), format, args); +#ifdef WIN32 + StringCchCatA(title, sizeof(title)," - " PACKAGE_NAME); + SetConsoleTitleA(title); +#else // !WIN32 // Set process title ::setproctitle("%s", title); - +#endif + #endif // HAVE_SETPROCTITLE }