forked from TrueCloudLab/distribution
9c88801a12
Back in the before time, the best practices surrounding usage of Context weren't quite worked out. We defined our own type to make usage easier. As this packaged was used elsewhere, it make it more and more challenging to integrate with the forked `Context` type. Now that it is available in the standard library, we can just use that one directly. To make usage more consistent, we now use `dcontext` when referring to the distribution context package. Signed-off-by: Stephen J Day <stephen.day@docker.com>
102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
package cache
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/docker/distribution"
|
|
dcontext "github.com/docker/distribution/context"
|
|
"github.com/opencontainers/go-digest"
|
|
)
|
|
|
|
// 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 {
|
|
dcontext.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 {
|
|
dcontext.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 {
|
|
dcontext.GetLogger(ctx).Errorf("error adding descriptor %v to cache: %v", desc.Digest, err)
|
|
}
|
|
return nil
|
|
}
|