summaryrefslogtreecommitdiff
path: root/vendor/github.com/docker/distribution/registry/storage/cache
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /vendor/github.com/docker/distribution/registry/storage/cache
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'vendor/github.com/docker/distribution/registry/storage/cache')
-rw-r--r--vendor/github.com/docker/distribution/registry/storage/cache/cache.go35
-rw-r--r--vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go101
-rw-r--r--vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go179
3 files changed, 315 insertions, 0 deletions
diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cache.go b/vendor/github.com/docker/distribution/registry/storage/cache/cache.go
new file mode 100644
index 000000000..10a390919
--- /dev/null
+++ b/vendor/github.com/docker/distribution/registry/storage/cache/cache.go
@@ -0,0 +1,35 @@
+// Package cache provides facilities to speed up access to the storage
+// backend.
+package cache
+
+import (
+ "fmt"
+
+ "github.com/docker/distribution"
+)
+
+// BlobDescriptorCacheProvider provides repository scoped
+// BlobDescriptorService cache instances and a global descriptor cache.
+type BlobDescriptorCacheProvider interface {
+ distribution.BlobDescriptorService
+
+ RepositoryScoped(repo string) (distribution.BlobDescriptorService, error)
+}
+
+// ValidateDescriptor provides a helper function to ensure that caches have
+// common criteria for admitting descriptors.
+func ValidateDescriptor(desc distribution.Descriptor) error {
+ if err := desc.Digest.Validate(); err != nil {
+ return err
+ }
+
+ if desc.Size < 0 {
+ return fmt.Errorf("cache: invalid length in descriptor: %v < 0", desc.Size)
+ }
+
+ if desc.MediaType == "" {
+ return fmt.Errorf("cache: empty mediatype on descriptor: %v", desc)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go b/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go
new file mode 100644
index 000000000..f647616bc
--- /dev/null
+++ b/vendor/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go
@@ -0,0 +1,101 @@
+package cache
+
+import (
+ "github.com/docker/distribution/context"
+ "github.com/opencontainers/go-digest"
+
+ "github.com/docker/distribution"
+)
+
+// Metrics is used to hold metric counters
+// related to the number of times a cache was
+// hit or missed.
+type Metrics struct {
+ Requests uint64
+ Hits uint64
+ Misses uint64
+}
+
+// MetricsTracker represents a metric tracker
+// which simply counts the number of hits and misses.
+type MetricsTracker interface {
+ Hit()
+ Miss()
+ Metrics() Metrics
+}
+
+type cachedBlobStatter struct {
+ cache distribution.BlobDescriptorService
+ backend distribution.BlobDescriptorService
+ tracker MetricsTracker
+}
+
+// NewCachedBlobStatter creates a new statter which prefers a cache and
+// falls back to a backend.
+func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService) distribution.BlobDescriptorService {
+ return &cachedBlobStatter{
+ cache: cache,
+ backend: backend,
+ }
+}
+
+// NewCachedBlobStatterWithMetrics creates a new statter which prefers a cache and
+// falls back to a backend. Hits and misses will send to the tracker.
+func NewCachedBlobStatterWithMetrics(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService, tracker MetricsTracker) distribution.BlobStatter {
+ return &cachedBlobStatter{
+ cache: cache,
+ backend: backend,
+ tracker: tracker,
+ }
+}
+
+func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
+ desc, err := cbds.cache.Stat(ctx, dgst)
+ if err != nil {
+ if err != distribution.ErrBlobUnknown {
+ context.GetLogger(ctx).Errorf("error retrieving descriptor from cache: %v", err)
+ }
+
+ goto fallback
+ }
+
+ if cbds.tracker != nil {
+ cbds.tracker.Hit()
+ }
+ return desc, nil
+fallback:
+ if cbds.tracker != nil {
+ cbds.tracker.Miss()
+ }
+ desc, err = cbds.backend.Stat(ctx, dgst)
+ if err != nil {
+ return desc, err
+ }
+
+ if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
+ context.GetLogger(ctx).Errorf("error adding descriptor %v to cache: %v", desc.Digest, err)
+ }
+
+ return desc, err
+
+}
+
+func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
+ err := cbds.cache.Clear(ctx, dgst)
+ if err != nil {
+ return err
+ }
+
+ err = cbds.backend.Clear(ctx, dgst)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
+ if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
+ context.GetLogger(ctx).Errorf("error adding descriptor %v to cache: %v", desc.Digest, err)
+ }
+ return nil
+}
diff --git a/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go b/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go
new file mode 100644
index 000000000..b2fcaf4e8
--- /dev/null
+++ b/vendor/github.com/docker/distribution/registry/storage/cache/memory/memory.go
@@ -0,0 +1,179 @@
+package memory
+
+import (
+ "sync"
+
+ "github.com/docker/distribution"
+ "github.com/docker/distribution/context"
+ "github.com/docker/distribution/reference"
+ "github.com/docker/distribution/registry/storage/cache"
+ "github.com/opencontainers/go-digest"
+)
+
+type inMemoryBlobDescriptorCacheProvider struct {
+ global *mapBlobDescriptorCache
+ repositories map[string]*mapBlobDescriptorCache
+ mu sync.RWMutex
+}
+
+// NewInMemoryBlobDescriptorCacheProvider returns a new mapped-based cache for
+// storing blob descriptor data.
+func NewInMemoryBlobDescriptorCacheProvider() cache.BlobDescriptorCacheProvider {
+ return &inMemoryBlobDescriptorCacheProvider{
+ global: newMapBlobDescriptorCache(),
+ repositories: make(map[string]*mapBlobDescriptorCache),
+ }
+}
+
+func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) {
+ if _, err := reference.ParseNormalizedNamed(repo); err != nil {
+ return nil, err
+ }
+
+ imbdcp.mu.RLock()
+ defer imbdcp.mu.RUnlock()
+
+ return &repositoryScopedInMemoryBlobDescriptorCache{
+ repo: repo,
+ parent: imbdcp,
+ repository: imbdcp.repositories[repo],
+ }, nil
+}
+
+func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
+ return imbdcp.global.Stat(ctx, dgst)
+}
+
+func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dgst digest.Digest) error {
+ return imbdcp.global.Clear(ctx, dgst)
+}
+
+func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
+ _, err := imbdcp.Stat(ctx, dgst)
+ if err == distribution.ErrBlobUnknown {
+
+ if dgst.Algorithm() != desc.Digest.Algorithm() && dgst != desc.Digest {
+ // if the digests differ, set the other canonical mapping
+ if err := imbdcp.global.SetDescriptor(ctx, desc.Digest, desc); err != nil {
+ return err
+ }
+ }
+
+ // unknown, just set it
+ return imbdcp.global.SetDescriptor(ctx, dgst, desc)
+ }
+
+ // we already know it, do nothing
+ return err
+}
+
+// repositoryScopedInMemoryBlobDescriptorCache provides the request scoped
+// repository cache. Instances are not thread-safe but the delegated
+// operations are.
+type repositoryScopedInMemoryBlobDescriptorCache struct {
+ repo string
+ parent *inMemoryBlobDescriptorCacheProvider // allows lazy allocation of repo's map
+ repository *mapBlobDescriptorCache
+}
+
+func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
+ rsimbdcp.parent.mu.Lock()
+ repo := rsimbdcp.repository
+ rsimbdcp.parent.mu.Unlock()
+
+ if repo == nil {
+ return distribution.Descriptor{}, distribution.ErrBlobUnknown
+ }
+
+ return repo.Stat(ctx, dgst)
+}
+
+func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
+ rsimbdcp.parent.mu.Lock()
+ repo := rsimbdcp.repository
+ rsimbdcp.parent.mu.Unlock()
+
+ if repo == nil {
+ return distribution.ErrBlobUnknown
+ }
+
+ return repo.Clear(ctx, dgst)
+}
+
+func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
+ rsimbdcp.parent.mu.Lock()
+ repo := rsimbdcp.repository
+ if repo == nil {
+ // allocate map since we are setting it now.
+ var ok bool
+ // have to read back value since we may have allocated elsewhere.
+ repo, ok = rsimbdcp.parent.repositories[rsimbdcp.repo]
+ if !ok {
+ repo = newMapBlobDescriptorCache()
+ rsimbdcp.parent.repositories[rsimbdcp.repo] = repo
+ }
+ rsimbdcp.repository = repo
+ }
+ rsimbdcp.parent.mu.Unlock()
+
+ if err := repo.SetDescriptor(ctx, dgst, desc); err != nil {
+ return err
+ }
+
+ return rsimbdcp.parent.SetDescriptor(ctx, dgst, desc)
+}
+
+// mapBlobDescriptorCache provides a simple map-based implementation of the
+// descriptor cache.
+type mapBlobDescriptorCache struct {
+ descriptors map[digest.Digest]distribution.Descriptor
+ mu sync.RWMutex
+}
+
+var _ distribution.BlobDescriptorService = &mapBlobDescriptorCache{}
+
+func newMapBlobDescriptorCache() *mapBlobDescriptorCache {
+ return &mapBlobDescriptorCache{
+ descriptors: make(map[digest.Digest]distribution.Descriptor),
+ }
+}
+
+func (mbdc *mapBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
+ if err := dgst.Validate(); err != nil {
+ return distribution.Descriptor{}, err
+ }
+
+ mbdc.mu.RLock()
+ defer mbdc.mu.RUnlock()
+
+ desc, ok := mbdc.descriptors[dgst]
+ if !ok {
+ return distribution.Descriptor{}, distribution.ErrBlobUnknown
+ }
+
+ return desc, nil
+}
+
+func (mbdc *mapBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
+ mbdc.mu.Lock()
+ defer mbdc.mu.Unlock()
+
+ delete(mbdc.descriptors, dgst)
+ return nil
+}
+
+func (mbdc *mapBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
+ if err := dgst.Validate(); err != nil {
+ return err
+ }
+
+ if err := cache.ValidateDescriptor(desc); err != nil {
+ return err
+ }
+
+ mbdc.mu.Lock()
+ defer mbdc.mu.Unlock()
+
+ mbdc.descriptors[dgst] = desc
+ return nil
+}