From fa9c56e913259101dfd054c56f3af708b002294f Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Wed, 3 Sep 2014 14:39:36 +0200 Subject: binfile: avoid unnecessary write and truncate The goal is to leave binfile completely untouched, including its "last modified" time stamp, if nothing changes. There are cases where the upper layers will call TBinFileBase::updateRecord() and write the same data that already is in the file. Instead of catching those case-by-case, let's check at the lowest level. On btrfs (and possibly other file systems), ftruncate() bumps the "last modified" time stamp of a file even if the requested size matches the existing one. Avoid that by skipping the ftruncate() when the file already has the desired size. --- src/platform_adapters/binfile.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/platform_adapters/binfile.cpp b/src/platform_adapters/binfile.cpp index e1da717..02d6c52 100755 --- a/src/platform_adapters/binfile.cpp +++ b/src/platform_adapters/binfile.cpp @@ -21,6 +21,7 @@ #endif #include +#include namespace sysync { @@ -141,7 +142,20 @@ bool TBinFile::platformWriteFile(const void *aBuffer, uInt32 aBytes) return true; } - return fwrite(aBuffer,aBytes,1,fCBinFile) == 1; + // Don't overwrite content which is already exactly what we want it + // to be. + std::vector buffer(aBytes); + char *addr = &buffer.front(); + long offset = ftell(fCBinFile); + if (offset == -1) + return false; + if (fread(addr,aBytes,1,fCBinFile) != 1 || + memcmp(addr,aBuffer,aBytes)) { + return fseek(fCBinFile,offset,SEEK_SET) == 0 && + fwrite(aBuffer,aBytes,1,fCBinFile) == 1; + } else { + return true; + } } // TBinFile::platformWriteFile @@ -167,7 +181,10 @@ bool TBinFile::platformTruncateFile(uInt32 aNewSize) #if defined(LINUX) || defined(MACOSX) fflush(fCBinFile); // unbuffer everything int fd = fileno(fCBinFile); // get file descriptor - if (ftruncate(fd,aNewSize)) { + struct stat buffer; + if (fstat(fd, &buffer) || + buffer.st_size == (off_t)aNewSize || // avoid modifying file if it already has the right size + ftruncate(fd,aNewSize)) { ; // error ignored } #elif defined(WIN32) -- cgit v1.2.3