+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
package main
import (
- "fmt"
"sync"
"sync/atomic"
"time"
type cachedCollection struct {
expire time.Time
- collection map[string]interface{}
+ collection *arvados.Collection
}
type cachedPermission struct {
}
}
-func (c *cache) Get(arv *arvadosclient.ArvadosClient, targetID string, forceReload bool) (map[string]interface{}, error) {
+func (c *cache) Get(arv *arvadosclient.ArvadosClient, targetID string, forceReload bool) (*arvados.Collection, error) {
c.setupOnce.Do(c.setup)
atomic.AddUint64(&c.stats.Requests, 1)
permOK := false
permKey := arv.ApiToken + "\000" + targetID
- if ent, cached := c.permissions.Get(permKey); cached {
+ if forceReload {
+ } else if ent, cached := c.permissions.Get(permKey); cached {
ent := ent.(*cachedPermission)
if ent.expire.Before(time.Now()) {
c.permissions.Remove(permKey)
}
}
- collection := c.lookupCollection(pdh)
-
- if collection != nil && permOK && !forceReload {
- return collection, nil
+ var collection *arvados.Collection
+ if pdh != "" {
+ collection = c.lookupCollection(arv.ApiToken + "\000" + pdh)
}
- if collection != nil {
+ if collection != nil && permOK {
+ return collection, nil
+ } else if collection != nil {
// Ask API for current PDH for this targetID. Most
// likely, the cached PDH is still correct; if so,
// _and_ the current token has permission, we can
// use our cached manifest.
atomic.AddUint64(&c.stats.APICalls, 1)
- var current map[string]interface{}
+ var current arvados.Collection
err := arv.Get("collections", targetID, selectPDH, ¤t)
if err != nil {
return nil, err
}
- if checkPDH, ok := current["portable_data_hash"].(string); !ok {
- return nil, fmt.Errorf("API response for %q had no PDH", targetID)
- } else if checkPDH == pdh {
+ if current.PortableDataHash == pdh {
exp := time.Now().Add(time.Duration(c.TTL))
c.permissions.Add(permKey, &cachedPermission{
expire: exp,
// PDH changed, but now we know we have
// permission -- and maybe we already have the
// new PDH in the cache.
- if coll := c.lookupCollection(checkPDH); coll != nil {
+ if coll := c.lookupCollection(arv.ApiToken + "\000" + current.PortableDataHash); coll != nil {
return coll, nil
}
}
if err != nil {
return nil, err
}
- pdh, ok := collection["portable_data_hash"].(string)
- if !ok {
- return nil, fmt.Errorf("API response for %q had no PDH", targetID)
- }
exp := time.Now().Add(time.Duration(c.TTL))
c.permissions.Add(permKey, &cachedPermission{
expire: exp,
})
c.pdhs.Add(targetID, &cachedPDH{
expire: exp,
- pdh: pdh,
+ pdh: collection.PortableDataHash,
})
- c.collections.Add(pdh, &cachedCollection{
+ c.collections.Add(arv.ApiToken+"\000"+collection.PortableDataHash, &cachedCollection{
expire: exp,
collection: collection,
})
- if int64(len(collection["manifest_text"].(string))) > c.MaxCollectionBytes/int64(c.MaxCollectionEntries) {
+ if int64(len(collection.ManifestText)) > c.MaxCollectionBytes/int64(c.MaxCollectionEntries) {
go c.pruneCollections()
}
return collection, nil
continue
}
ent := v.(*cachedCollection)
- n := len(ent.collection["manifest_text"].(string))
+ n := len(ent.collection.ManifestText)
size += int64(n)
entsize[i] = n
expired[i] = ent.expire.Before(now)
if !ok {
continue
}
- size += uint64(len(v.(*cachedCollection).collection["manifest_text"].(string)))
+ size += uint64(len(v.(*cachedCollection).collection.ManifestText))
}
return size
}
-func (c *cache) lookupCollection(pdh string) map[string]interface{} {
- if pdh == "" {
- return nil
- } else if ent, cached := c.collections.Get(pdh); !cached {
+func (c *cache) lookupCollection(key string) *arvados.Collection {
+ if ent, cached := c.collections.Get(key); !cached {
return nil
} else {
ent := ent.(*cachedCollection)
if ent.expire.Before(time.Now()) {
- c.collections.Remove(pdh)
+ c.collections.Remove(key)
return nil
} else {
atomic.AddUint64(&c.stats.CollectionHits, 1)