Refactor the multi-host salt install page.
[arvados.git] / services / keepstore / collision.go
index a4af563729b3cf0e72686a2913fd3664e497e24d..16f2d0923244b138a64eb970fef1a70dc477532e 100644 (file)
@@ -1,7 +1,12 @@
-package main
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+package keepstore
 
 import (
        "bytes"
+       "context"
        "crypto/md5"
        "fmt"
        "io"
@@ -49,7 +54,7 @@ func collisionOrCorrupt(expectMD5 string, buf1, buf2 []byte, rdr io.Reader) erro
        return <-outcome
 }
 
-func compareReaderWithBuf(rdr io.Reader, expect []byte, hash string) error {
+func compareReaderWithBuf(ctx context.Context, rdr io.Reader, expect []byte, hash string) error {
        bufLen := 1 << 20
        if bufLen > len(expect) && len(expect) > 0 {
                // No need for bufLen to be longer than
@@ -67,7 +72,18 @@ func compareReaderWithBuf(rdr io.Reader, expect []byte, hash string) error {
        // expected to equal the next N bytes read from
        // rdr.
        for {
-               n, err := rdr.Read(buf)
+               ready := make(chan bool)
+               var n int
+               var err error
+               go func() {
+                       n, err = rdr.Read(buf)
+                       close(ready)
+               }()
+               select {
+               case <-ready:
+               case <-ctx.Done():
+                       return ctx.Err()
+               }
                if n > len(cmp) || bytes.Compare(cmp[:n], buf[:n]) != 0 {
                        return collisionOrCorrupt(hash, expect[:len(expect)-len(cmp)], buf[:n], rdr)
                }