// A Cache is a package cache, backed by a file system directory tree.
type Cache struct {
dir string
- log *os.File
now func() time.Time
}
return nil, err
}
}
- f, err := os.OpenFile(filepath.Join(dir, "log.txt"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
- if err != nil {
- return nil, err
- }
c := &Cache{
dir: dir,
- log: f,
now: time.Now,
}
return c, nil
// get is Get but does not respect verify mode, so that Put can use it.
func (c *Cache) get(id ActionID) (Entry, error) {
missing := func() (Entry, error) {
- fmt.Fprintf(c.log, "%d miss %x\n", c.now().Unix(), id)
return Entry{}, errMissing
}
f, err := os.Open(c.fileName(id, "a"))
return missing()
}
- fmt.Fprintf(c.log, "%d get %x\n", c.now().Unix(), id)
-
c.used(c.fileName(id, "a"))
return Entry{buf, size, time.Unix(0, tm)}, nil
}
os.Chtimes(file, c.now(), c.now()) // mainly for tests
- fmt.Fprintf(c.log, "%d put %x %x %d\n", c.now().Unix(), id, out, size)
return nil
}
t.Fatal("mismatched Put did not panic in verify mode")
}
-func TestCacheLog(t *testing.T) {
- dir, err := ioutil.TempDir("", "cachetest-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
-
- c, err := Open(dir)
- if err != nil {
- t.Fatalf("Open: %v", err)
- }
- c.now = func() time.Time { return time.Unix(1e9, 0) }
-
- id := ActionID(dummyID(1))
- c.Get(id)
- c.PutBytes(id, []byte("abc"))
- c.Get(id)
-
- c, err = Open(dir)
- if err != nil {
- t.Fatalf("Open #2: %v", err)
- }
- c.now = func() time.Time { return time.Unix(1e9+1, 0) }
- c.Get(id)
-
- id2 := ActionID(dummyID(2))
- c.Get(id2)
- c.PutBytes(id2, []byte("abc"))
- c.Get(id2)
- c.Get(id)
-
- data, err := ioutil.ReadFile(filepath.Join(dir, "log.txt"))
- if err != nil {
- t.Fatal(err)
- }
- want := `1000000000 miss 0100000000000000000000000000000000000000000000000000000000000000
-1000000000 put 0100000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3
-1000000000 get 0100000000000000000000000000000000000000000000000000000000000000
-1000000001 get 0100000000000000000000000000000000000000000000000000000000000000
-1000000001 miss 0200000000000000000000000000000000000000000000000000000000000000
-1000000001 put 0200000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3
-1000000001 get 0200000000000000000000000000000000000000000000000000000000000000
-1000000001 get 0100000000000000000000000000000000000000000000000000000000000000
-`
- if string(data) != want {
- t.Fatalf("log:\n%s\nwant:\n%s", string(data), want)
- }
-}
-
func dummyID(x int) [HashSize]byte {
var out [HashSize]byte
binary.LittleEndian.PutUint64(out[:], uint64(x))
// and not something that we want to remove. Also, we'd like to preserve
// the access log for future analysis, even if the cache is cleared.
subdirs, _ := filepath.Glob(filepath.Join(dir, "[0-9a-f][0-9a-f]"))
+ printedErrors := false
if len(subdirs) > 0 {
if cfg.BuildN || cfg.BuildX {
b.Showcmd("", "rm -r %s", strings.Join(subdirs, " "))
}
- printedErrors := false
for _, d := range subdirs {
// Only print the first error - there may be many.
// This also mimics what os.RemoveAll(dir) would do.
}
}
}
+
+ logFile := filepath.Join(dir, "log.txt")
+ if err := os.RemoveAll(logFile); err != nil && !printedErrors {
+ printedErrors = true
+ base.Errorf("go clean -cache: %v", err)
+ }
}
}