...

Source file src/github.com/docker/distribution/registry/storage/cache/cachedblobdescriptorstore.go

Documentation: github.com/docker/distribution/registry/storage/cache

     1  package cache
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/docker/distribution"
     7  	prometheus "github.com/docker/distribution/metrics"
     8  	"github.com/opencontainers/go-digest"
     9  )
    10  
    11  // Metrics is used to hold metric counters
    12  // related to the number of times a cache was
    13  // hit or missed.
    14  type Metrics struct {
    15  	Requests uint64
    16  	Hits     uint64
    17  	Misses   uint64
    18  }
    19  
    20  // Logger can be provided on the MetricsTracker to log errors.
    21  //
    22  // Usually, this is just a proxy to dcontext.GetLogger.
    23  type Logger interface {
    24  	Errorf(format string, args ...interface{})
    25  }
    26  
    27  // MetricsTracker represents a metric tracker
    28  // which simply counts the number of hits and misses.
    29  type MetricsTracker interface {
    30  	Hit()
    31  	Miss()
    32  	Metrics() Metrics
    33  	Logger(context.Context) Logger
    34  }
    35  
    36  type cachedBlobStatter struct {
    37  	cache   distribution.BlobDescriptorService
    38  	backend distribution.BlobDescriptorService
    39  	tracker MetricsTracker
    40  }
    41  
    42  var (
    43  	// cacheCount is the number of total cache request received/hits/misses
    44  	cacheCount = prometheus.StorageNamespace.NewLabeledCounter("cache", "The number of cache request received", "type")
    45  )
    46  
    47  // NewCachedBlobStatter creates a new statter which prefers a cache and
    48  // falls back to a backend.
    49  func NewCachedBlobStatter(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService) distribution.BlobDescriptorService {
    50  	return &cachedBlobStatter{
    51  		cache:   cache,
    52  		backend: backend,
    53  	}
    54  }
    55  
    56  // NewCachedBlobStatterWithMetrics creates a new statter which prefers a cache and
    57  // falls back to a backend. Hits and misses will send to the tracker.
    58  func NewCachedBlobStatterWithMetrics(cache distribution.BlobDescriptorService, backend distribution.BlobDescriptorService, tracker MetricsTracker) distribution.BlobStatter {
    59  	return &cachedBlobStatter{
    60  		cache:   cache,
    61  		backend: backend,
    62  		tracker: tracker,
    63  	}
    64  }
    65  
    66  func (cbds *cachedBlobStatter) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
    67  	cacheCount.WithValues("Request").Inc(1)
    68  	desc, err := cbds.cache.Stat(ctx, dgst)
    69  	if err != nil {
    70  		if err != distribution.ErrBlobUnknown {
    71  			logErrorf(ctx, cbds.tracker, "error retrieving descriptor from cache: %v", err)
    72  		}
    73  
    74  		goto fallback
    75  	}
    76  	cacheCount.WithValues("Hit").Inc(1)
    77  	if cbds.tracker != nil {
    78  		cbds.tracker.Hit()
    79  	}
    80  	return desc, nil
    81  fallback:
    82  	cacheCount.WithValues("Miss").Inc(1)
    83  	if cbds.tracker != nil {
    84  		cbds.tracker.Miss()
    85  	}
    86  	desc, err = cbds.backend.Stat(ctx, dgst)
    87  	if err != nil {
    88  		return desc, err
    89  	}
    90  
    91  	if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
    92  		logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err)
    93  	}
    94  
    95  	return desc, err
    96  
    97  }
    98  
    99  func (cbds *cachedBlobStatter) Clear(ctx context.Context, dgst digest.Digest) error {
   100  	err := cbds.cache.Clear(ctx, dgst)
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	err = cbds.backend.Clear(ctx, dgst)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	return nil
   110  }
   111  
   112  func (cbds *cachedBlobStatter) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
   113  	if err := cbds.cache.SetDescriptor(ctx, dgst, desc); err != nil {
   114  		logErrorf(ctx, cbds.tracker, "error adding descriptor %v to cache: %v", desc.Digest, err)
   115  	}
   116  	return nil
   117  }
   118  
   119  func logErrorf(ctx context.Context, tracker MetricsTracker, format string, args ...interface{}) {
   120  	if tracker == nil {
   121  		return
   122  	}
   123  
   124  	logger := tracker.Logger(ctx)
   125  	if logger == nil {
   126  		return
   127  	}
   128  	logger.Errorf(format, args...)
   129  }
   130  

View as plain text