From 0d0c634242d4f575a83ee8775277dbfec15e268d Mon Sep 17 00:00:00 2001 From: William Elwood Date: Sun, 10 Nov 2019 11:32:38 +0000 Subject: [PATCH] Avoid writing cache if it didn't change Most of the time the only useful difference being written is the new modification time anyway, which is now being done explicitly. --- dnscrypt-proxy/sources.go | 37 ++++++++++++++++++++++------------ dnscrypt-proxy/sources_test.go | 5 ++++- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/dnscrypt-proxy/sources.go b/dnscrypt-proxy/sources.go index 755bcbfe..b36e611a 100644 --- a/dnscrypt-proxy/sources.go +++ b/dnscrypt-proxy/sources.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "io" "io/ioutil" @@ -77,8 +78,7 @@ func (source *Source) fetchFromCache(now time.Time) (delay time.Duration, err er return } -func (source *Source) writeToCache(bin, sig []byte, now time.Time) (err error) { - f := source.cacheFile +func writeSource(f string, bin, sig []byte) (err error) { var fSrc, fSig *safefile.File if fSrc, err = safefile.Create(f, 0644); err != nil { return @@ -97,10 +97,28 @@ func (source *Source) writeToCache(bin, sig []byte, now time.Time) (err error) { if err = fSrc.Commit(); err != nil { return } - if err = fSig.Commit(); err != nil { - return + return fSig.Commit() +} + +func (source *Source) writeToCache(bin, sig []byte, now time.Time) { + f := source.cacheFile + var writeErr error // an error writing cache isn't fatal + defer func() { + source.in = bin + if writeErr == nil { + return + } + if absPath, absErr := filepath.Abs(f); absErr == nil { + f = absPath + } + dlog.Warnf("%s: %s", f, writeErr) + }() + if !bytes.Equal(source.in, bin) { + if writeErr = writeSource(f, bin, sig); writeErr != nil { + return + } } - return os.Chtimes(f, now, now) + writeErr = os.Chtimes(f, now, now) } func (source *Source) parseURLs(urls []string) { @@ -161,14 +179,7 @@ func (source *Source) fetchWithCache(xTransport *XTransport, now time.Time) (del if err != nil { return } - source.in = bin - if writeErr := source.writeToCache(bin, sig, now); writeErr != nil { // an error here isn't fatal - f := source.cacheFile - if absPath, absErr := filepath.Abs(f); absErr == nil { - f = absPath - } - dlog.Warnf("%s: %s", f, writeErr) - } + source.writeToCache(bin, sig, now) delay = source.prefetchDelay return } diff --git a/dnscrypt-proxy/sources_test.go b/dnscrypt-proxy/sources_test.go index 79bc2da7..845829da 100644 --- a/dnscrypt-proxy/sources_test.go +++ b/dnscrypt-proxy/sources_test.go @@ -428,7 +428,10 @@ func TestPrefetchSources(t *testing.T) { for i := range d.sources { _, e := setupSourceTestCase(t, d, i, nil, downloadTest) e.mtime = d.timeUpd - sources = append(sources, e.Source) + s := &Source{} + *s = *e.Source + s.in = nil + sources = append(sources, s) expects = append(expects, e) } t.Run("download "+downloadTestName, func(t *testing.T) {