From 32506e95005d396f91557e4a730ca0ee8e2c3102 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 10 Feb 2010 19:01:12 +0000 Subject: Log more detailed info about backup comparison failures, for debugging. Enable -V option in bbackupquery, and document that -q, -v, -V and -W are allowed in the command-line help. --- bin/bbackupquery/bbackupquery.cpp | 16 +++++++--- lib/backupclient/BackupClientFileAttributes.cpp | 41 +++++++++++++++++++------ lib/common/Logging.cpp | 21 +++++++++++++ lib/common/Logging.h | 27 ++++++++-------- 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/bin/bbackupquery/bbackupquery.cpp b/bin/bbackupquery/bbackupquery.cpp index bab697b8..5aa7e97e 100644 --- a/bin/bbackupquery/bbackupquery.cpp +++ b/bin/bbackupquery/bbackupquery.cpp @@ -60,7 +60,7 @@ void PrintUsageAndExit() { - printf("Usage: bbackupquery [-q] [-w] " + printf("Usage: bbackupquery [-q*|v*|V|W] [-w] " #ifdef WIN32 "[-u] " #endif @@ -123,10 +123,10 @@ int main(int argc, const char *argv[]) #endif #ifdef WIN32 - const char* validOpts = "qvwuc:l:o:O:W:"; + const char* validOpts = "qvVwuc:l:o:O:W:"; bool unicodeConsole = false; #else - const char* validOpts = "qvwc:l:o:O:W:"; + const char* validOpts = "qvVwc:l:o:O:W:"; #endif std::string fileLogFile; @@ -138,7 +138,7 @@ int main(int argc, const char *argv[]) { switch(c) { - case 'q': + case 'q': { if(masterLevel == Log::NOTHING) { @@ -151,7 +151,7 @@ int main(int argc, const char *argv[]) } break; - case 'v': + case 'v': { if(masterLevel == Log::EVERYTHING) { @@ -164,6 +164,12 @@ int main(int argc, const char *argv[]) } break; + case 'V': + { + masterLevel = Log::EVERYTHING; + } + break; + case 'W': { masterLevel = Logging::GetNamedLevel(optarg); diff --git a/lib/backupclient/BackupClientFileAttributes.cpp b/lib/backupclient/BackupClientFileAttributes.cpp index d896a363..749ca99e 100644 --- a/lib/backupclient/BackupClientFileAttributes.cpp +++ b/lib/backupclient/BackupClientFileAttributes.cpp @@ -234,6 +234,10 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr // Check sizes are the same, as a first check if(mpClearAttributes->GetSize() != rAttr.mpClearAttributes->GetSize()) { + BOX_TRACE("Attribute Compare: Attributes objects are " + "different sizes, cannot compare them: local " << + mpClearAttributes->GetSize() << " bytes, remote " << + rAttr.mpClearAttributes->GetSize() << " bytes"); return false; } @@ -241,15 +245,20 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr // Bytes are checked in network order, but this doesn't matter as we're only checking for equality. attr_StreamFormat *a1 = (attr_StreamFormat*)mpClearAttributes->GetBuffer(); attr_StreamFormat *a2 = (attr_StreamFormat*)rAttr.mpClearAttributes->GetBuffer(); - - if(a1->AttributeType != a2->AttributeType - || a1->UID != a2->UID - || a1->GID != a2->GID - || a1->UserDefinedFlags != a2->UserDefinedFlags - || a1->Mode != a2->Mode) - { - return false; + + #define COMPARE(attribute, message) \ + if (a1->attribute != a2->attribute) \ + { \ + BOX_TRACE("Attribute Compare: " << message << " differ: " \ + "local " << a1->attribute << ", " \ + "remote " << a2->attribute); \ + return false; \ } + COMPARE(AttributeType, "Attribute types"); + COMPARE(UID, "UIDs"); + COMPARE(GID, "GIDs"); + COMPARE(UserDefinedFlags, "User-defined flags"); + COMPARE(Mode, "Modes"); if(!IgnoreModTime) { @@ -257,6 +266,9 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr int t2 = a2->ModificationTime / 1000000; if(t1 != t2) { + BOX_TRACE("Attribute Compare: File modification " + "times differ: local " << t1 << ", " + "remote " << t2); return false; } } @@ -267,6 +279,9 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr int t2 = a2->AttrModificationTime / 1000000; if(t1 != t2) { + BOX_TRACE("Attribute Compare: Attribute modification " + "times differ: local " << t1 << ", " + "remote " << t2); return false; } } @@ -276,8 +291,16 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr if(size > sizeof(attr_StreamFormat)) { // Symlink strings don't match. This also compares xattrs - if(::memcmp(a1 + 1, a2 + 1, size - sizeof(attr_StreamFormat)) != 0) + int datalen = size - sizeof(attr_StreamFormat); + + if(::memcmp(a1 + 1, a2 + 1, datalen) != 0) { + std::string s1((char *)(a1 + 1), datalen); + std::string s2((char *)(a2 + 1), datalen); + BOX_TRACE("Attribute Compare: Symbolic link target " + "or extended attributes differ: " + "local " << PrintEscapedBinaryData(s1) << ", " + "remote " << PrintEscapedBinaryData(s2)); return false; } } diff --git a/lib/common/Logging.cpp b/lib/common/Logging.cpp index 681e1352..296443ea 100644 --- a/lib/common/Logging.cpp +++ b/lib/common/Logging.cpp @@ -495,3 +495,24 @@ bool FileLogger::Log(Log::Level Level, const std::string& rFile, Logging::Add(this); return true; } + +std::string PrintEscapedBinaryData(const std::string& rInput) +{ + std::ostringstream output; + + for (size_t i = 0; i < rInput.length(); i++) + { + if (isprint(rInput[i])) + { + output << rInput[i]; + } + else + { + output << "\\x" << std::hex << std::setw(2) << + std::setfill('0') << (int) rInput[i] << + std::dec; + } + } + + return output.str(); +} diff --git a/lib/common/Logging.h b/lib/common/Logging.h index 35e14d83..24863d2c 100644 --- a/lib/common/Logging.h +++ b/lib/common/Logging.h @@ -18,17 +18,6 @@ #include "FileStream.h" -/* -#define BOX_LOG(level, stuff) \ -{ \ - if(Log::sMaxLoggingLevelForAnyOutput >= level) \ - std::ostringstream line; \ - line << stuff; \ - Log::Write(level, __FILE__, __LINE__, line.str()); \ - } \ -} -*/ - #define BOX_LOG(level, stuff) \ { \ std::ostringstream _box_log_line; \ @@ -52,12 +41,20 @@ if (Logging::IsEnabled(Log::TRACE)) \ { BOX_LOG(Log::TRACE, stuff) } +#define BOX_SYS_ERROR(stuff) \ + stuff << ": " << std::strerror(errno) << " (" << errno << ")" + #define BOX_LOG_SYS_WARNING(stuff) \ - BOX_WARNING(stuff << ": " << std::strerror(errno) << " (" << errno << ")") + BOX_WARNING(BOX_SYS_ERROR(stuff)) #define BOX_LOG_SYS_ERROR(stuff) \ - BOX_ERROR(stuff << ": " << std::strerror(errno) << " (" << errno << ")") + BOX_ERROR(BOX_SYS_ERROR(stuff)) #define BOX_LOG_SYS_FATAL(stuff) \ - BOX_FATAL(stuff << ": " << std::strerror(errno) << " (" << errno << ")") + BOX_FATAL(BOX_SYS_ERROR(stuff)) + +#define LOG_AND_THROW_ERROR(message, filename, exception, subtype) \ + BOX_LOG_SYS_ERROR(message << ": " << filename); \ + THROW_EXCEPTION_MESSAGE(exception, subtype, \ + BOX_SYS_ERROR(message << ": " << filename)); inline std::string GetNativeErrorMessage() { @@ -339,4 +336,6 @@ class HideExceptionMessageGuard bool mOldHiddenState; }; +std::string PrintEscapedBinaryData(const std::string& rInput); + #endif // LOGGING__H -- cgit v1.2.3