diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2014-08-29 10:39:17 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2014-08-29 10:45:38 +0200 |
commit | 115cef8a0ec1823b58808bbb9820f7cb82c2a313 (patch) | |
tree | a7f66bad6f1512ff168c7a9b30bb53fa334bf362 | |
parent | 4683fceb72cef0e7301b735a23b1f40323da52ba (diff) |
binfileclient: avoid disk writes in changeLogPreflight()
During a normal sync where nothing changed, only the header gets
updated. This change is not critical and thus does not have to be
flushed to disk unless also some entries get added or updated.
The advantage is that when SyncEvolution detects a sync where nothing
changed on either side and skips the client's session shutdown, the
.bfi is left unchanged, which reduces flash wearout.
To detect item changes, a brute-force byte comparison is used. This
requires less changes to the code and is less error-prone than adding
"modified=true" to all places where "existingentries" gets modified.
-rwxr-xr-x | src/sysync/binfileimplds.cpp | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/src/sysync/binfileimplds.cpp b/src/sysync/binfileimplds.cpp index 314ccc7..947fa0c 100755 --- a/src/sysync/binfileimplds.cpp +++ b/src/sysync/binfileimplds.cpp @@ -741,9 +741,9 @@ localstatus TBinfileImplDS::changeLogPreflight(bool &aValidChangelog) lsd.c_str() )); #endif - // - save header - err = fChangeLog.flushHeader(); - if (err!=BFE_OK) goto done; + // - force saving of header only if some entry changes + bool modified=false; + string origentries; // - we don't need the changelog to be updated when all we do is refresh from server if (isRefreshOnly()) goto done; // done ok // - load entire existing changelog into memory @@ -751,10 +751,12 @@ localstatus TBinfileImplDS::changeLogPreflight(bool &aValidChangelog) PDEBUGPRINTFX(DBG_ADMIN+DBG_DBAPI,("changeLogPreflight: at start, changelog has %ld entries",(long)numexistinglogentries)); if (numexistinglogentries>0) { // - allocate array for all existing entries (use sysync_malloc because e.g. on PalmOS this uses special funcs to allow > 64k) - existingentries = (TChangeLogEntry *)sysync_malloc(sizeof(TChangeLogEntry)*numexistinglogentries); + size_t entriessize = sizeof(TChangeLogEntry)*numexistinglogentries; + existingentries = (TChangeLogEntry *)sysync_malloc(entriessize); if (!existingentries) { err=BFE_MEMORY; goto done; } // not enough memory // - read all entries fChangeLog.readRecord(0,existingentries,numexistinglogentries); + origentries.assign((char *)existingentries, entriessize); // Mark all not-yet-deleted in the log as delete candidate // (those that still exist will be get the candidate mark removed below) for (logindex=0;logindex<numexistinglogentries;logindex++) { @@ -952,6 +954,7 @@ localstatus TBinfileImplDS::changeLogPreflight(bool &aValidChangelog) // create if entry is new if (!chgentryexists) { // this is a new, additional entry (and not a resurrected deleted one) + modified=true; fChangeLog.newRecord(currentEntryP); PDEBUGPRINTFX(DBG_ADMIN+DBG_DBAPI,("- item was newly added (no entry existed in changelog before)")); } @@ -1033,7 +1036,18 @@ localstatus TBinfileImplDS::changeLogPreflight(bool &aValidChangelog) } #endif // - write back all existing entries - fChangeLog.updateRecord(0,existingentries,numexistinglogentries); + if (existingentries && + memcmp(existingentries, origentries.c_str(), origentries.size())) { + fChangeLog.updateRecord(0,existingentries,numexistinglogentries); + modified=true; + } + + // Also write updated header if (and only if) something changed. + if (modified) { + err = fChangeLog.flushHeader(); + if (err!=BFE_OK) goto done; + } + // - now we can confirm we have a valid changelog aValidChangelog=true; DEBUGPRINTFX(DBG_ADMIN+DBG_DBAPI+DBG_EXOTIC,("changeLogPreflight: seen=%ld, fNumberOfLocalChanges=%ld",(long)seen,(long)fNumberOfLocalChanges)); |