From b1bde8932db5bb285116f15b78cb273d294ba971 Mon Sep 17 00:00:00 2001 From: ulrfa Date: Thu, 30 Apr 2020 16:47:15 +0200 Subject: [PATCH] Consistent handling of empty files There have been inconsistencies where some functions expected empty blobs to be available on disk, but other functions avoided writing them. Those inconsistencies were probably corrected in commit 9945963. This commit moves all logic for empty blobs into disk.go in order to prevent future inconsistencies. A size parameter is added to disk.Get and disk.Contains, mainly for the empty blob handling. As a side effect, the expected size is checked against the found size. --- cache/disk/disk.go | 90 ++++++++++++++++------- cache/disk/disk_test.go | 116 ++++++++++++++++++++++++++---- cache/httpproxy/httpproxy_test.go | 16 ++--- server/grpc_ac.go | 8 ++- server/grpc_asset.go | 4 +- server/grpc_bytestream.go | 13 +--- server/grpc_cas.go | 10 +-- server/grpc_test.go | 2 +- server/http.go | 27 +------ 9 files changed, 189 insertions(+), 97 deletions(-) diff --git a/cache/disk/disk.go b/cache/disk/disk.go index c30aab6b5..8976f6d6b 100644 --- a/cache/disk/disk.go +++ b/cache/disk/disk.go @@ -1,6 +1,7 @@ package disk import ( + "bytes" "crypto/sha256" "encoding/hex" "fmt" @@ -59,6 +60,7 @@ type nameAndInfo struct { } const sha256HashStrSize = sha256.Size * 2 // Two hex characters per byte. +const emptySha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" // New returns a new instance of a filesystem-based cache rooted at `dir`, // with a maximum size of `maxSizeBytes` bytes and an optional backend `proxy`. @@ -257,6 +259,11 @@ func (c *Cache) Put(kind cache.EntryKind, hash string, expectedSize int64, r io. len(hash), sha256.Size) } + if kind == cache.CAS && expectedSize == 0 && hash == emptySha256 { + io.Copy(ioutil.Discard, r) + return nil + } + key := cacheKey(kind, hash) c.mu.Lock() @@ -403,8 +410,9 @@ func (c *Cache) availableOrTryProxy(key string) (available bool, tryProxy bool) // Get returns an io.ReadCloser with the content of the cache item stored under `hash` // and the number of bytes that can be read from it. If the item is not found, the // io.ReadCloser will be nil. If some error occurred when processing the request, then -// it is returned. -func (c *Cache) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, error) { +// it is returned. The 'size' of the content to be retreived shall be provided when +// known, or as -1 when unknown. +func (c *Cache) Get(kind cache.EntryKind, hash string, size int64) (io.ReadCloser, int64, error) { // The hash format is checked properly in the http/grpc code. // Just perform a simple/fast check here, to catch bad tests. @@ -413,6 +421,11 @@ func (c *Cache) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, er len(hash), sha256.Size) } + if kind == cache.CAS && size <= 0 && hash == emptySha256 { + cacheHits.Inc() + return ioutil.NopCloser(bytes.NewReader([]byte{})), 0, nil + } + var err error key := cacheKey(kind, hash) @@ -423,11 +436,16 @@ func (c *Cache) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, er var fileInfo os.FileInfo fileInfo, err = os.Stat(blobPath) if err == nil { + foundSize := fileInfo.Size() + if isSizeMismatch(size, foundSize) { + cacheMisses.Inc() + return nil, -1, nil + } var f *os.File f, err = os.Open(blobPath) if err == nil { cacheHits.Inc() - return f, fileInfo.Size(), nil + return f, foundSize, nil } } @@ -483,6 +501,9 @@ func (c *Cache) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, er if err != nil || r == nil { return nil, -1, err } + if isSizeMismatch(size, foundSize) { + return nil, -1, nil + } f, err = os.Create(tmpFilePath) if err != nil { @@ -529,7 +550,10 @@ func (c *Cache) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, er // // If there is a local cache miss, the proxy backend (if there is // one) will be checked. -func (c *Cache) Contains(kind cache.EntryKind, hash string) (bool, int64) { +// +// The 'size' of the potential content, shall be provided when known, +// or as -1 when unknown. +func (c *Cache) Contains(kind cache.EntryKind, hash string, size int64) (bool, int64) { // The hash format is checked properly in the http/grpc code. // Just perform a simple/fast check here, to catch bad tests. @@ -537,26 +561,37 @@ func (c *Cache) Contains(kind cache.EntryKind, hash string) (bool, int64) { return false, int64(-1) } - var foundLocally bool - size := int64(-1) + if kind == cache.CAS && size <= 0 && hash == emptySha256 { + return true, 0 + } + + var found bool + foundSize := int64(-1) key := cacheKey(kind, hash) c.mu.Lock() - val, found := c.lru.Get(key) + val, isInLru := c.lru.Get(key) // Uncommitted (i.e. uploading items) should be reported as not ok - if found { + if isInLru { item := val.(*lruItem) - foundLocally = item.committed - size = item.size + found = item.committed + foundSize = item.size } c.mu.Unlock() - if foundLocally { - return true, size + if found { + if isSizeMismatch(size, foundSize) { + return false, int64(-1) + } + return true, foundSize } if c.proxy != nil { - return c.proxy.Contains(kind, hash) + found, foundSize = c.proxy.Contains(kind, hash) + if isSizeMismatch(size, foundSize) { + return false, int64(-1) + } + return found, foundSize } return false, int64(-1) @@ -577,6 +612,10 @@ func (c *Cache) Stats() (currentSize int64, numItems int) { return c.lru.CurrentSize(), c.lru.Len() } +func isSizeMismatch(requestedSize int64, foundSize int64) bool { + return requestedSize > -1 && foundSize > -1 && requestedSize != foundSize +} + func ensureDirExists(path string) { if _, err := os.Stat(path); os.IsNotExist(err) { err = os.MkdirAll(path, os.ModePerm) @@ -599,7 +638,8 @@ func cacheFilePath(kind cache.EntryKind, cacheDir string, hash string) string { // not, nil values are returned. If something unexpected went wrong, return // an error. func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, error) { - rdr, sizeBytes, err := c.Get(cache.AC, hash) + + rdr, sizeBytes, err := c.Get(cache.AC, hash, -1) if err != nil { return nil, nil, err } @@ -620,8 +660,8 @@ func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, } for _, f := range result.OutputFiles { - if len(f.Contents) == 0 && f.Digest.SizeBytes > 0 { - found, _ := c.Contains(cache.CAS, f.Digest.Hash) + if len(f.Contents) == 0 { + found, _ := c.Contains(cache.CAS, f.Digest.Hash, f.Digest.SizeBytes) if !found { return nil, nil, nil // aka "not found" } @@ -629,7 +669,7 @@ func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, } for _, d := range result.OutputDirectories { - r, size, err := c.Get(cache.CAS, d.TreeDigest.Hash) + r, size, err := c.Get(cache.CAS, d.TreeDigest.Hash, d.TreeDigest.SizeBytes) if r == nil { return nil, nil, err // aka "not found", or an err if non-nil } @@ -657,10 +697,10 @@ func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, } for _, f := range tree.Root.GetFiles() { - if f.Digest == nil || f.Digest.SizeBytes == 0 { + if f.Digest == nil { continue } - found, _ := c.Contains(cache.CAS, f.Digest.Hash) + found, _ := c.Contains(cache.CAS, f.Digest.Hash, f.Digest.SizeBytes) if !found { return nil, nil, nil // aka "not found" } @@ -668,10 +708,10 @@ func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, for _, child := range tree.GetChildren() { for _, f := range child.GetFiles() { - if f.Digest == nil || f.Digest.SizeBytes == 0 { + if f.Digest == nil { continue } - found, _ := c.Contains(cache.CAS, f.Digest.Hash) + found, _ := c.Contains(cache.CAS, f.Digest.Hash, f.Digest.SizeBytes) if !found { return nil, nil, nil // aka "not found" } @@ -679,15 +719,15 @@ func (c *Cache) GetValidatedActionResult(hash string) (*pb.ActionResult, []byte, } } - if result.StdoutDigest != nil && result.StdoutDigest.SizeBytes > 0 { - found, _ := c.Contains(cache.CAS, result.StdoutDigest.Hash) + if result.StdoutDigest != nil { + found, _ := c.Contains(cache.CAS, result.StdoutDigest.Hash, result.StdoutDigest.SizeBytes) if !found { return nil, nil, nil // aka "not found" } } - if result.StderrDigest != nil && result.StderrDigest.SizeBytes > 0 { - found, _ := c.Contains(cache.CAS, result.StderrDigest.Hash) + if result.StderrDigest != nil { + found, _ := c.Contains(cache.CAS, result.StderrDigest.Hash, result.StderrDigest.SizeBytes) if !found { return nil, nil, nil // aka "not found" } diff --git a/cache/disk/disk_test.go b/cache/disk/disk_test.go index 566050a07..7930a11c9 100644 --- a/cache/disk/disk_test.go +++ b/cache/disk/disk_test.go @@ -72,6 +72,7 @@ func checkItems(cache *Cache, expSize int64, expNum int) error { const KEY = "a-key" const contents = "hello" const contentsHash = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" +const contentsLength = int64(len(contents)) func TestCacheBasics(t *testing.T) { cacheDir := tempDir(t) @@ -84,7 +85,7 @@ func TestCacheBasics(t *testing.T) { } // Non-existing item - rdr, _, err := testCache.Get(cache.CAS, contentsHash) + rdr, _, err := testCache.Get(cache.CAS, contentsHash, contentsLength) if err != nil { t.Fatal(err) } @@ -106,7 +107,7 @@ func TestCacheBasics(t *testing.T) { } // Get the item back - rdr, sizeBytes, err := testCache.Get(cache.CAS, contentsHash) + rdr, sizeBytes, err := testCache.Get(cache.CAS, contentsHash, contentsLength) if err != nil { t.Fatal(err) } @@ -183,6 +184,91 @@ func TestCachePutWrongSize(t *testing.T) { } } +func TestCacheGetContainsWrongSize(t *testing.T) { + + cacheDir := tempDir(t) + defer os.RemoveAll(cacheDir) + testCache := New(cacheDir, 100, nil) + + var found bool + var rdr io.ReadCloser + + err := testCache.Put(cache.CAS, contentsHash, contentsLength, strings.NewReader(contents)) + if err != nil { + t.Fatal("Expected success", err) + } + + found, _ = testCache.Contains(cache.CAS, contentsHash, contentsLength+1) + if found { + t.Error("Expected not found, due to size being different") + } + + rdr, _, _ = testCache.Get(cache.CAS, contentsHash, contentsLength+1) + if rdr != nil { + t.Error("Expected not found, due to size being different") + } + + found, _ = testCache.Contains(cache.CAS, contentsHash, -1) + if !found { + t.Error("Expected found, when unknown size") + } + + rdr, _, _ = testCache.Get(cache.CAS, contentsHash, -1) + if rdr == nil { + t.Error("Expected found, when unknown size") + } +} + +func TestCacheGetContainsWrongSizeWithProxy(t *testing.T) { + + cacheDir := tempDir(t) + defer os.RemoveAll(cacheDir) + testCache := New(cacheDir, 100, new(proxyStub)) + + var found bool + var rdr io.ReadCloser + + // The proxyStub contains the digest {contentsHash, contentsLength}. + + found, _ = testCache.Contains(cache.CAS, contentsHash, contentsLength+1) + if found { + t.Error("Expected not found, due to size being different") + } + + rdr, _, _ = testCache.Get(cache.CAS, contentsHash, contentsLength+1) + if rdr != nil { + t.Error("Expected not found, due to size being different") + } + if err := checkItems(testCache, 0, 0); err != nil { + t.Fatal(err) + } + + found, _ = testCache.Contains(cache.CAS, contentsHash, -1) + if !found { + t.Error("Expected found, when unknown size") + } + + rdr, _, _ = testCache.Get(cache.CAS, contentsHash, -1) + if rdr == nil { + t.Error("Expected found, when unknown size") + } + if err := checkItems(testCache, contentsLength, 1); err != nil { + t.Fatal(err) + } +} + +type proxyStub struct{} + +func (d proxyStub) Put(kind cache.EntryKind, hash string, size int64, rdr io.Reader) {} + +func (d proxyStub) Get(kind cache.EntryKind, hash string) (io.ReadCloser, int64, error) { + return ioutil.NopCloser(strings.NewReader(contents)), contentsLength, nil +} + +func (d proxyStub) Contains(kind cache.EntryKind, hash string) (bool, int64) { + return true, contentsLength +} + func expectContentEquals(rdr io.ReadCloser, sizeBytes int64, expectedContent []byte) error { if rdr == nil { return fmt.Errorf("expected the item to exist") @@ -216,7 +302,7 @@ func putGetCompareBytes(kind cache.EntryKind, hash string, data []byte, testCach return err } - rdr, sizeBytes, err := testCache.Get(kind, hash) + rdr, sizeBytes, err := testCache.Get(kind, hash, int64(len(data))) if err != nil { return err } @@ -307,7 +393,7 @@ func TestCacheExistingFiles(t *testing.T) { if err != nil { t.Fatal(err) } - found, _ := testCache.Contains(cache.CAS, "f53b46209596d170f7659a414c9ff9f6b545cf77ffd6e1cbe9bcc57e1afacfbd") + found, _ := testCache.Contains(cache.CAS, "f53b46209596d170f7659a414c9ff9f6b545cf77ffd6e1cbe9bcc57e1afacfbd", contentsLength) if found { t.Fatalf("%s should have been evicted", items[0]) } @@ -390,17 +476,17 @@ func TestMigrateFromOldDirectoryStructure(t *testing.T) { } var found bool - found, _ = testCache.Contains(cache.AC, acHash) + found, _ = testCache.Contains(cache.AC, acHash, 512) if !found { t.Fatalf("Expected cache to contain AC entry '%s'", acHash) } - found, _ = testCache.Contains(cache.CAS, casHash1) + found, _ = testCache.Contains(cache.CAS, casHash1, 1024) if !found { t.Fatalf("Expected cache to contain CAS entry '%s'", casHash1) } - found, _ = testCache.Contains(cache.CAS, casHash2) + found, _ = testCache.Contains(cache.CAS, casHash2, 1024) if !found { t.Fatalf("Expected cache to contain CAS entry '%s'", casHash2) } @@ -436,17 +522,17 @@ func TestLoadExistingEntries(t *testing.T) { var found bool - found, _ = testCache.Contains(cache.AC, acHash) + found, _ = testCache.Contains(cache.AC, acHash, blobSize) if !found { t.Fatalf("Expected cache to contain AC entry '%s'", acHash) } - found, _ = testCache.Contains(cache.CAS, casHash) + found, _ = testCache.Contains(cache.CAS, casHash, blobSize) if !found { t.Fatalf("Expected cache to contain CAS entry '%s'", casHash) } - found, _ = testCache.Contains(cache.RAW, rawHash) + found, _ = testCache.Contains(cache.RAW, rawHash, blobSize) if !found { t.Fatalf("Expected cache to contain RAW entry '%s'", rawHash) } @@ -580,7 +666,7 @@ func TestHttpProxyBackend(t *testing.T) { blob, casHash := testutils.RandomDataAndHash(blobSize) // Non-existing item - r, _, err := testCache.Get(cache.CAS, casHash) + r, _, err := testCache.Get(cache.CAS, casHash, blobSize) if err != nil { t.Fatal(err) } @@ -614,12 +700,12 @@ func TestHttpProxyBackend(t *testing.T) { // Confirm that it does not contain the item we added to the // first testCache and the proxy backend. - found, _ := testCache.Contains(cache.CAS, casHash) + found, _ := testCache.Contains(cache.CAS, casHash, blobSize) if found { t.Fatalf("Expected the cache not to contain %s", casHash) } - r, _, err = testCache.Get(cache.CAS, casHash) + r, _, err = testCache.Get(cache.CAS, casHash, blobSize) if err != nil { t.Fatal(err) } @@ -630,13 +716,13 @@ func TestHttpProxyBackend(t *testing.T) { // Add the proxy backend and check that we can Get the item. testCache.proxy = proxy - found, _ = testCache.Contains(cache.CAS, casHash) + found, _ = testCache.Contains(cache.CAS, casHash, blobSize) if !found { t.Fatalf("Expected the cache to contain %s (via the proxy)", casHash) } - r, fetchedSize, err := testCache.Get(cache.CAS, casHash) + r, fetchedSize, err := testCache.Get(cache.CAS, casHash, blobSize) if err != nil { t.Fatal(err) } diff --git a/cache/httpproxy/httpproxy_test.go b/cache/httpproxy/httpproxy_test.go index 35073e7be..5ffee0779 100644 --- a/cache/httpproxy/httpproxy_test.go +++ b/cache/httpproxy/httpproxy_test.go @@ -157,7 +157,7 @@ func TestEverything(t *testing.T) { var found bool var size int64 - found, size = diskCache.Contains(cache.AC, hash) + found, size = diskCache.Contains(cache.AC, hash, int64(len(acData))) if !found { t.Fatalf("Expected to find AC item %s", hash) } @@ -166,7 +166,7 @@ func TestEverything(t *testing.T) { len(acData), size) } - found, size = diskCache.Contains(cache.CAS, hash) + found, size = diskCache.Contains(cache.CAS, hash, int64(len(casData))) if !found { t.Fatalf("Expected to find CAS item %s", hash) } @@ -180,7 +180,7 @@ func TestEverything(t *testing.T) { var data []byte var rc io.ReadCloser - rc, size, err = diskCache.Get(cache.AC, hash) + rc, size, err = diskCache.Get(cache.AC, hash, int64(len(acData))) if err != nil { t.Error(err) } @@ -200,7 +200,7 @@ func TestEverything(t *testing.T) { } rc.Close() - rc, size, err = diskCache.Get(cache.CAS, hash) + rc, size, err = diskCache.Get(cache.CAS, hash, int64(len(casData))) if err != nil { t.Error(err) } @@ -235,7 +235,7 @@ func TestEverything(t *testing.T) { // Confirm that we can HEAD both values successfully. - found, size = diskCache.Contains(cache.AC, hash) + found, size = diskCache.Contains(cache.AC, hash, int64(len(acData))) if !found { t.Fatalf("Expected to find AC item %s", hash) } @@ -244,7 +244,7 @@ func TestEverything(t *testing.T) { len(acData), size) } - found, size = diskCache.Contains(cache.CAS, hash) + found, size = diskCache.Contains(cache.CAS, hash, int64(len(casData))) if !found { t.Fatalf("Expected to find CAS item %s", hash) } @@ -255,7 +255,7 @@ func TestEverything(t *testing.T) { // Confirm that we can GET both values successfully. - rc, size, err = diskCache.Get(cache.AC, hash) + rc, size, err = diskCache.Get(cache.AC, hash, int64(len(acData))) if err != nil { t.Error(err) } @@ -275,7 +275,7 @@ func TestEverything(t *testing.T) { } rc.Close() - rc, size, err = diskCache.Get(cache.CAS, hash) + rc, size, err = diskCache.Get(cache.CAS, hash, int64(len(casData))) if err != nil { t.Error(err) } diff --git a/server/grpc_ac.go b/server/grpc_ac.go index 9f7b2d34f..09b789250 100644 --- a/server/grpc_ac.go +++ b/server/grpc_ac.go @@ -44,10 +44,14 @@ func (s *grpcServer) GetActionResult(ctx context.Context, return nil, err } + // Clients provides hash and size of the Action, but not size of the ActionResult + // checked by the the disk cache. + const unknownActionResultSize = -1 + if !s.depsCheck { logPrefix = "GRPC AC GET NODEPSCHECK" - rdr, sizeBytes, err := s.cache.Get(cache.AC, req.ActionDigest.Hash) + rdr, sizeBytes, err := s.cache.Get(cache.AC, req.ActionDigest.Hash, unknownActionResultSize) if err != nil { s.accessLogger.Printf("%s %s %s", logPrefix, req.ActionDigest.Hash, err) return nil, status.Error(codes.Unknown, err.Error()) @@ -145,7 +149,7 @@ func (s *grpcServer) maybeInline(inline bool, slice *[]byte, digest **pb.Digest, } } - found, _ := s.cache.Contains(cache.CAS, (*digest).Hash) + found, _ := s.cache.Contains(cache.CAS, (*digest).Hash, (*digest).SizeBytes) if !found { err := s.cache.Put(cache.CAS, (*digest).Hash, (*digest).SizeBytes, bytes.NewReader(*slice)) diff --git a/server/grpc_asset.go b/server/grpc_asset.go index 6cc2f8ea4..1a8a493b6 100644 --- a/server/grpc_asset.go +++ b/server/grpc_asset.go @@ -64,14 +64,14 @@ func (s *grpcServer) FetchBlob(ctx context.Context, req *asset.FetchBlobRequest) sha256Str = hex.EncodeToString(decoded) - found, size := s.cache.Contains(cache.CAS, sha256Str) + found, size := s.cache.Contains(cache.CAS, sha256Str, -1) if !found { continue } if size < 0 { // We don't know the size yet (bad http backend?). - r, size, err := s.cache.Get(cache.CAS, sha256Str) + r, size, err := s.cache.Get(cache.CAS, sha256Str, -1) if r != nil { defer r.Close() } diff --git a/server/grpc_bytestream.go b/server/grpc_bytestream.go index fc3307c98..c85582b78 100644 --- a/server/grpc_bytestream.go +++ b/server/grpc_bytestream.go @@ -87,17 +87,6 @@ func (s *grpcServer) Read(req *bytestream.ReadRequest, return err } - if size == 0 { - // While not technically an error, clients really shouldn't be - // asking for empty data with the bytestream API (IMO). - err = resp.Send(&bytestream.ReadResponse{Data: []byte{}}) - if err != nil { - s.accessLogger.Printf("GRPC BYTESTREAM READ FAILED TO SEND RESPONSE: %s", err) - return status.Error(codes.Unknown, err.Error()) - } - return nil - } - if req.ReadOffset > size { msg := fmt.Sprintf("ReadOffset %d larger than expected data size %d resource: %s", req.ReadOffset, size, req.ResourceName) @@ -105,7 +94,7 @@ func (s *grpcServer) Read(req *bytestream.ReadRequest, return status.Error(codes.OutOfRange, msg) } - rdr, sizeBytes, err := s.cache.Get(cache.CAS, hash) + rdr, sizeBytes, err := s.cache.Get(cache.CAS, hash, size) if err != nil { msg := fmt.Sprintf("GRPC BYTESTREAM READ FAILED: %v", err) s.accessLogger.Printf(msg) diff --git a/server/grpc_cas.go b/server/grpc_cas.go index 8f3423463..7e9dcc0c6 100644 --- a/server/grpc_cas.go +++ b/server/grpc_cas.go @@ -37,13 +37,7 @@ func (s *grpcServer) FindMissingBlobs(ctx context.Context, return nil, err } - if digest.SizeBytes == 0 { - // The hash was validated, so we know it's OK. - s.accessLogger.Printf("GRPC CAS HEAD %s OK", hash) - continue - } - - found, _ := s.cache.Contains(cache.CAS, hash) + found, _ := s.cache.Contains(cache.CAS, hash, digest.GetSizeBytes()) if !found { s.accessLogger.Printf("GRPC CAS HEAD %s NOT FOUND", hash) resp.MissingBlobDigests = append(resp.MissingBlobDigests, digest) @@ -106,7 +100,7 @@ func (s *grpcServer) getBlobData(hash string, size int64) ([]byte, error) { return []byte{}, nil } - rdr, sizeBytes, err := s.cache.Get(cache.CAS, hash) + rdr, sizeBytes, err := s.cache.Get(cache.CAS, hash, size) if err != nil { rdr.Close() return []byte{}, err diff --git a/server/grpc_test.go b/server/grpc_test.go index f17147c28..e2a7f0a38 100644 --- a/server/grpc_test.go +++ b/server/grpc_test.go @@ -573,7 +573,7 @@ func TestGrpcByteStreamDeadline(t *testing.T) { t.Fatal(err) } - _, sz, err := diskCache.Get(cache.CAS, testBlobHash) + _, sz, err := diskCache.Get(cache.CAS, testBlobHash, testBlobSize) if err != nil { t.Fatalf("get error: %v\n", err) } diff --git a/server/http.go b/server/http.go index 5d9a821f5..6a9c87d76 100644 --- a/server/http.go +++ b/server/http.go @@ -193,15 +193,7 @@ func (h *httpCache) CacheHandler(w http.ResponseWriter, r *http.Request) { return } - if kind == cache.CAS && hash == emptySha256 { - w.Header().Set("Content-Type", "application/octet-stream") - w.Header().Set("Content-Length", "0") - w.Write([]byte{}) - h.logResponse(http.StatusOK, r) - return - } - - rdr, sizeBytes, err := h.cache.Get(kind, hash) + rdr, sizeBytes, err := h.cache.Get(kind, hash, -1) if err != nil { if e, ok := err.(*cache.Error); ok { http.Error(w, e.Error(), e.Code) @@ -236,13 +228,7 @@ func (h *httpCache) CacheHandler(w http.ResponseWriter, r *http.Request) { return } - if contentLength == 0 && kind == cache.CAS { - if hash == emptySha256 { - w.WriteHeader(http.StatusOK) - h.logResponse(http.StatusOK, r) - return - } - + if contentLength == 0 && kind == cache.CAS && hash != emptySha256 { msg := fmt.Sprintf("Invalid empty blob hash: \"%s\"", hash) http.Error(w, msg, http.StatusBadRequest) h.errorLogger.Printf("PUT %s: %s", path(kind, hash), msg) @@ -303,16 +289,9 @@ func (h *httpCache) CacheHandler(w http.ResponseWriter, r *http.Request) { return } - if kind == cache.CAS && hash == emptySha256 { - w.Header().Set("Content-Length", "0") - w.WriteHeader(http.StatusOK) - h.logResponse(http.StatusOK, r) - return - } - // Unvalidated path: - ok, size := h.cache.Contains(kind, hash) + ok, size := h.cache.Contains(kind, hash, -1) if !ok { http.Error(w, "Not found", http.StatusNotFound) h.logResponse(http.StatusNotFound, r)