@@ -31,8 +31,37 @@ type ActionID [HashSize]byte
31
31
// An OutputID is a cache output key, the hash of an output of a computation.
32
32
type OutputID [HashSize ]byte
33
33
34
+ // Cache is the interface as used by the cmd/go.
35
+ type Cache interface {
36
+ // Get returns the cache entry for the provided ActionID.
37
+ // On miss, the error type should be of type *entryNotFoundError.
38
+ Get (ActionID ) (Entry , error )
39
+
40
+ // Put adds an item to the cache.
41
+ //
42
+ // The seeker is only used to seek to the beginning. After a call to Put,
43
+ // the seek position is not guaranteed to be in any particular state.
44
+ //
45
+ // As a special case, if the ReadSeeker is of type noVerifyReadSeeker,
46
+ // the verification from GODEBUG=goverifycache=1 is skipped.
47
+ Put (ActionID , io.ReadSeeker ) (_ OutputID , size int64 , _ error )
48
+
49
+ // Trim does some optional clean-up at the end of the go tool's action.
50
+ Trim () error
51
+
52
+ // OutputFile returns the path on disk where OutputID is stored.
53
+ //
54
+ // It's only called after a successful get or put call so it doesn't need
55
+ // to return an error; it's assumed that if the previous get or put succeeded,
56
+ // it's already on disk.
57
+ OutputFile (OutputID ) string
58
+
59
+ // FuzzDir returns where fuzz files are stored.
60
+ FuzzDir () string
61
+ }
62
+
34
63
// A Cache is a package cache, backed by a file system directory tree.
35
- type Cache struct {
64
+ type DiskCache struct {
36
65
dir string
37
66
now func () time.Time
38
67
}
@@ -48,7 +77,7 @@ type Cache struct {
48
77
// to share a cache directory (for example, if the directory were stored
49
78
// in a network file system). File locking is notoriously unreliable in
50
79
// network file systems and may not suffice to protect the cache.
51
- func Open (dir string ) (* Cache , error ) {
80
+ func Open (dir string ) (* DiskCache , error ) {
52
81
info , err := os .Stat (dir )
53
82
if err != nil {
54
83
return nil , err
@@ -62,15 +91,15 @@ func Open(dir string) (*Cache, error) {
62
91
return nil , err
63
92
}
64
93
}
65
- c := & Cache {
94
+ c := & DiskCache {
66
95
dir : dir ,
67
96
now : time .Now ,
68
97
}
69
98
return c , nil
70
99
}
71
100
72
101
// fileName returns the name of the file corresponding to the given id.
73
- func (c * Cache ) fileName (id [HashSize ]byte , key string ) string {
102
+ func (c * DiskCache ) fileName (id [HashSize ]byte , key string ) string {
74
103
return filepath .Join (c .dir , fmt .Sprintf ("%02x" , id [0 ]), fmt .Sprintf ("%x" , id )+ "-" + key )
75
104
}
76
105
@@ -136,7 +165,7 @@ func initEnv() {
136
165
// returning the corresponding output ID and file size, if any.
137
166
// Note that finding an output ID does not guarantee that the
138
167
// saved file for that output ID is still available.
139
- func (c * Cache ) Get (id ActionID ) (Entry , error ) {
168
+ func (c * DiskCache ) Get (id ActionID ) (Entry , error ) {
140
169
if verify {
141
170
return Entry {}, & entryNotFoundError {Err : errVerifyMode }
142
171
}
@@ -150,7 +179,7 @@ type Entry struct {
150
179
}
151
180
152
181
// get is Get but does not respect verify mode, so that Put can use it.
153
- func (c * Cache ) get (id ActionID ) (Entry , error ) {
182
+ func (c * DiskCache ) get (id ActionID ) (Entry , error ) {
154
183
missing := func (reason error ) (Entry , error ) {
155
184
return Entry {}, & entryNotFoundError {Err : reason }
156
185
}
@@ -214,7 +243,7 @@ func (c *Cache) get(id ActionID) (Entry, error) {
214
243
215
244
// GetFile looks up the action ID in the cache and returns
216
245
// the name of the corresponding data file.
217
- func (c * Cache ) GetFile ( id ActionID ) (file string , entry Entry , err error ) {
246
+ func GetFile (c Cache , id ActionID ) (file string , entry Entry , err error ) {
218
247
entry , err = c .Get (id )
219
248
if err != nil {
220
249
return "" , Entry {}, err
@@ -233,7 +262,7 @@ func (c *Cache) GetFile(id ActionID) (file string, entry Entry, err error) {
233
262
// GetBytes looks up the action ID in the cache and returns
234
263
// the corresponding output bytes.
235
264
// GetBytes should only be used for data that can be expected to fit in memory.
236
- func (c * Cache ) GetBytes ( id ActionID ) ([]byte , Entry , error ) {
265
+ func GetBytes (c Cache , id ActionID ) ([]byte , Entry , error ) {
237
266
entry , err := c .Get (id )
238
267
if err != nil {
239
268
return nil , entry , err
@@ -248,7 +277,7 @@ func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) {
248
277
// GetMmap looks up the action ID in the cache and returns
249
278
// the corresponding output bytes.
250
279
// GetMmap should only be used for data that can be expected to fit in memory.
251
- func (c * Cache ) GetMmap ( id ActionID ) ([]byte , Entry , error ) {
280
+ func GetMmap (c Cache , id ActionID ) ([]byte , Entry , error ) {
252
281
entry , err := c .Get (id )
253
282
if err != nil {
254
283
return nil , entry , err
@@ -264,7 +293,7 @@ func (c *Cache) GetMmap(id ActionID) ([]byte, Entry, error) {
264
293
}
265
294
266
295
// OutputFile returns the name of the cache file storing output with the given OutputID.
267
- func (c * Cache ) OutputFile (out OutputID ) string {
296
+ func (c * DiskCache ) OutputFile (out OutputID ) string {
268
297
file := c .fileName (out , "d" )
269
298
c .used (file )
270
299
return file
@@ -297,7 +326,7 @@ const (
297
326
// mtime is more than an hour old. This heuristic eliminates
298
327
// nearly all of the mtime updates that would otherwise happen,
299
328
// while still keeping the mtimes useful for cache trimming.
300
- func (c * Cache ) used (file string ) {
329
+ func (c * DiskCache ) used (file string ) {
301
330
info , err := os .Stat (file )
302
331
if err == nil && c .now ().Sub (info .ModTime ()) < mtimeInterval {
303
332
return
@@ -306,7 +335,7 @@ func (c *Cache) used(file string) {
306
335
}
307
336
308
337
// Trim removes old cache entries that are likely not to be reused.
309
- func (c * Cache ) Trim () error {
338
+ func (c * DiskCache ) Trim () error {
310
339
now := c .now ()
311
340
312
341
// We maintain in dir/trim.txt the time of the last completed cache trim.
@@ -346,7 +375,7 @@ func (c *Cache) Trim() error {
346
375
}
347
376
348
377
// trimSubdir trims a single cache subdirectory.
349
- func (c * Cache ) trimSubdir (subdir string , cutoff time.Time ) {
378
+ func (c * DiskCache ) trimSubdir (subdir string , cutoff time.Time ) {
350
379
// Read all directory entries from subdir before removing
351
380
// any files, in case removing files invalidates the file offset
352
381
// in the directory scan. Also, ignore error from f.Readdirnames,
@@ -374,7 +403,7 @@ func (c *Cache) trimSubdir(subdir string, cutoff time.Time) {
374
403
375
404
// putIndexEntry adds an entry to the cache recording that executing the action
376
405
// with the given id produces an output with the given output id (hash) and size.
377
- func (c * Cache ) putIndexEntry (id ActionID , out OutputID , size int64 , allowVerify bool ) error {
406
+ func (c * DiskCache ) putIndexEntry (id ActionID , out OutputID , size int64 , allowVerify bool ) error {
378
407
// Note: We expect that for one reason or another it may happen
379
408
// that repeating an action produces a different output hash
380
409
// (for example, if the output contains a time stamp or temp dir name).
@@ -428,21 +457,29 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
428
457
return nil
429
458
}
430
459
460
+ // noVerifyReadSeeker is a io.ReadSeeker wrapper sentinel type
461
+ // that says that Cache.Put should skip the verify check
462
+ // (from GODEBUG=goverifycache=1).
463
+ type noVerifyReadSeeker struct {
464
+ io.ReadSeeker
465
+ }
466
+
431
467
// Put stores the given output in the cache as the output for the action ID.
432
468
// It may read file twice. The content of file must not change between the two passes.
433
- func (c * Cache ) Put (id ActionID , file io.ReadSeeker ) (OutputID , int64 , error ) {
434
- return c .put (id , file , true )
469
+ func (c * DiskCache ) Put (id ActionID , file io.ReadSeeker ) (OutputID , int64 , error ) {
470
+ _ , isNoVerify := file .(noVerifyReadSeeker )
471
+ return c .put (id , file , ! isNoVerify )
435
472
}
436
473
437
474
// PutNoVerify is like Put but disables the verify check
438
475
// when GODEBUG=goverifycache=1 is set.
439
476
// It is meant for data that is OK to cache but that we expect to vary slightly from run to run,
440
477
// like test output containing times and the like.
441
- func (c * Cache ) PutNoVerify ( id ActionID , file io.ReadSeeker ) (OutputID , int64 , error ) {
442
- return c .put (id , file , false )
478
+ func PutNoVerify (c Cache , id ActionID , file io.ReadSeeker ) (OutputID , int64 , error ) {
479
+ return c .Put (id , noVerifyReadSeeker { file } )
443
480
}
444
481
445
- func (c * Cache ) put (id ActionID , file io.ReadSeeker , allowVerify bool ) (OutputID , int64 , error ) {
482
+ func (c * DiskCache ) put (id ActionID , file io.ReadSeeker , allowVerify bool ) (OutputID , int64 , error ) {
446
483
// Compute output ID.
447
484
h := sha256 .New ()
448
485
if _ , err := file .Seek (0 , 0 ); err != nil {
@@ -465,14 +502,14 @@ func (c *Cache) put(id ActionID, file io.ReadSeeker, allowVerify bool) (OutputID
465
502
}
466
503
467
504
// PutBytes stores the given bytes in the cache as the output for the action ID.
468
- func (c * Cache ) PutBytes ( id ActionID , data []byte ) error {
505
+ func PutBytes (c Cache , id ActionID , data []byte ) error {
469
506
_ , _ , err := c .Put (id , bytes .NewReader (data ))
470
507
return err
471
508
}
472
509
473
510
// copyFile copies file into the cache, expecting it to have the given
474
511
// output ID and size, if that file is not present already.
475
- func (c * Cache ) copyFile (file io.ReadSeeker , out OutputID , size int64 ) error {
512
+ func (c * DiskCache ) copyFile (file io.ReadSeeker , out OutputID , size int64 ) error {
476
513
name := c .fileName (out , "d" )
477
514
info , err := os .Stat (name )
478
515
if err == nil && info .Size () == size {
@@ -562,6 +599,6 @@ func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error {
562
599
// They may be removed with 'go clean -fuzzcache'.
563
600
//
564
601
// TODO(#48526): make Trim remove unused files from this directory.
565
- func (c * Cache ) FuzzDir () string {
602
+ func (c * DiskCache ) FuzzDir () string {
566
603
return filepath .Join (c .dir , "fuzz" )
567
604
}
0 commit comments