20318: Fix DiskCacheSize not propagated by (*KeepClient)Clone().
[arvados.git] / sdk / go / keepclient / gateway_shim.go
index 262d61264091169fb7cbd2a98651bd7dddf29f59..260824453dd57f04119b97cbeae27e49297984fb 100644 (file)
@@ -6,13 +6,23 @@ package keepclient
 
 import (
        "context"
+       "fmt"
        "io"
+       "net/http"
+       "strings"
+       "time"
 
        "git.arvados.org/arvados.git/sdk/go/arvados"
 )
 
 // keepViaHTTP implements arvados.KeepGateway by using a KeepClient to
 // do upstream requests to keepstore and keepproxy.
+//
+// This enables KeepClient to use KeepGateway wrappers (like
+// arvados.DiskCache) to wrap its own HTTP client back-end methods
+// (getOrHead, httpBlockWrite).
+//
+// See (*KeepClient)upstreamGateway() for the relevant glue.
 type keepViaHTTP struct {
        *KeepClient
 }
@@ -36,32 +46,33 @@ func (kvh *keepViaHTTP) BlockRead(ctx context.Context, opts arvados.BlockReadOpt
        if err != nil {
                return 0, err
        }
-       defer rdr.Close()
        n, err := io.Copy(opts.WriteTo, rdr)
+       errClose := rdr.Close()
+       if err == nil {
+               err = errClose
+       }
        return int(n), err
 }
 
-// keepViaBlockCache implements arvados.KeepGateway by using the given
-// KeepClient's BlockCache with the wrapped KeepGateway.
-//
-// Note the whole KeepClient gets passed in instead of just its
-// cache. This ensures the new BlockCache gets used if it changes
-// after keepViaBlockCache is initialized.
-type keepViaBlockCache struct {
-       kc *KeepClient
-       arvados.KeepGateway
-}
-
-func (kvbc *keepViaBlockCache) ReadAt(locator string, dst []byte, offset int) (int, error) {
-       return kvbc.kc.cache().ReadAt(kvbc.KeepGateway, locator, dst, offset)
+func (kvh *keepViaHTTP) BlockWrite(ctx context.Context, req arvados.BlockWriteOptions) (arvados.BlockWriteResponse, error) {
+       return kvh.httpBlockWrite(ctx, req)
 }
 
-func (kvbc *keepViaBlockCache) BlockRead(ctx context.Context, opts arvados.BlockReadOptions) (int, error) {
-       rdr, _, _, _, err := kvbc.kc.getOrHead("GET", opts.Locator, nil)
+func (kvh *keepViaHTTP) LocalLocator(locator string) (string, error) {
+       if !strings.Contains(locator, "+R") {
+               // Either it has +A, or it's unsigned and we assume
+               // it's a local locator on a site with signatures
+               // disabled.
+               return locator, nil
+       }
+       sighdr := fmt.Sprintf("local, time=%s", time.Now().UTC().Format(time.RFC3339))
+       _, _, url, hdr, err := kvh.KeepClient.getOrHead("HEAD", locator, http.Header{"X-Keep-Signature": []string{sighdr}})
        if err != nil {
-               return 0, err
+               return "", err
        }
-       defer rdr.Close()
-       n, err := io.Copy(opts.WriteTo, rdr)
-       return int(n), err
+       loc := hdr.Get("X-Keep-Locator")
+       if loc == "" {
+               return "", fmt.Errorf("missing X-Keep-Locator header in HEAD response from %s", url)
+       }
+       return loc, nil
 }