Skip to content

Commit fddd4a6

Browse files
leitzlergopherbot
authored andcommitted
gopls/filecache: prevent premature CAS file eviction
If the CAS file exists with the correct content when setting a cache value, the timestamp on the CAS file was not being updated. This causes the garbage collector to evict the CAS file potentially long before the index file. This can result in a large cache having many orphaned index files. This change ensures that the CAS file timestamp is updated even if it already exists during a Set call. Change-Id: I1f16253d7a8a5d0f9d2b6d7e1e766f34c5661303 Reviewed-on: https://go-review.googlesource.com/c/tools/+/740900 Reviewed-by: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Madeline Kalil <mkalil@google.com>
1 parent e3a69ff commit fddd4a6

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

gopls/internal/filecache/filecache.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,7 @@ func Get(kind string, key [32]byte) ([]byte, error) {
125125
// automatically, but for efficiency most POSIX systems have
126126
// for many years set the noatime mount option to avoid every
127127
// open or read operation entailing a metadata write.)
128-
now := time.Now()
129-
touch := func(filename string) {
130-
st, err := os.Stat(filename)
131-
if err == nil && now.Sub(st.ModTime()) > time.Hour {
132-
os.Chtimes(filename, now, now) // ignore error
133-
}
134-
}
135-
touch(indexName)
136-
touch(casName)
128+
touch(indexName, casName)
137129

138130
memCache.Set(memKey{kind, key}, value, len(value))
139131

@@ -198,9 +190,22 @@ func Set(kind string, key [32]byte, value []byte) error {
198190
return err // e.g. disk full
199191
}
200192

193+
// Update the CAS file's timestamp to prevent premature LRU eviction.
194+
touch(casName)
195+
201196
return nil
202197
}
203198

199+
func touch(filenames ...string) {
200+
now := time.Now()
201+
for _, filename := range filenames {
202+
st, err := os.Stat(filename)
203+
if err == nil && now.Sub(st.ModTime()) > time.Hour {
204+
os.Chtimes(filename, now, now) // ignore error
205+
}
206+
}
207+
}
208+
204209
// The active 1-channel is a selectable resettable event
205210
// indicating recent cache activity.
206211
var active = make(chan struct{}, 1)

0 commit comments

Comments
 (0)