github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/cache/cache.go (about) 1 // Package cache provides facilities to speed up access to the storage 2 // backend. Typically cache implementations deal with internal implementation 3 // details at the backend level, rather than generalized caches for 4 // distribution related interfaces. In other words, unless the cache is 5 // specific to the storage package, it belongs in another package. 6 package cache 7 8 import ( 9 "fmt" 10 11 "github.com/docker/distribution/digest" 12 "golang.org/x/net/context" 13 ) 14 15 // ErrNotFound is returned when a meta item is not found. 16 var ErrNotFound = fmt.Errorf("not found") 17 18 // LayerMeta describes the backend location and length of layer data. 19 type LayerMeta struct { 20 Path string 21 Length int64 22 } 23 24 // LayerInfoCache is a driver-aware cache of layer metadata. Basically, it 25 // provides a fast cache for checks against repository metadata, avoiding 26 // round trips to backend storage. Note that this is different from a pure 27 // layer cache, which would also provide access to backing data, as well. Such 28 // a cache should be implemented as a middleware, rather than integrated with 29 // the storage backend. 30 // 31 // Note that most implementations rely on the caller to do strict checks on on 32 // repo and dgst arguments, since these are mostly used behind existing 33 // implementations. 34 type LayerInfoCache interface { 35 // Contains returns true if the repository with name contains the layer. 36 Contains(ctx context.Context, repo string, dgst digest.Digest) (bool, error) 37 38 // Add includes the layer in the given repository cache. 39 Add(ctx context.Context, repo string, dgst digest.Digest) error 40 41 // Meta provides the location of the layer on the backend and its size. Membership of a 42 // repository should be tested before using the result, if required. 43 Meta(ctx context.Context, dgst digest.Digest) (LayerMeta, error) 44 45 // SetMeta sets the meta data for the given layer. 46 SetMeta(ctx context.Context, dgst digest.Digest, meta LayerMeta) error 47 } 48 49 // base implements common checks between cache implementations. Note that 50 // these are not full checks of input, since that should be done by the 51 // caller. 52 type base struct { 53 LayerInfoCache 54 } 55 56 func (b *base) Contains(ctx context.Context, repo string, dgst digest.Digest) (bool, error) { 57 if repo == "" { 58 return false, fmt.Errorf("cache: cannot check for empty repository name") 59 } 60 61 if dgst == "" { 62 return false, fmt.Errorf("cache: cannot check for empty digests") 63 } 64 65 return b.LayerInfoCache.Contains(ctx, repo, dgst) 66 } 67 68 func (b *base) Add(ctx context.Context, repo string, dgst digest.Digest) error { 69 if repo == "" { 70 return fmt.Errorf("cache: cannot add empty repository name") 71 } 72 73 if dgst == "" { 74 return fmt.Errorf("cache: cannot add empty digest") 75 } 76 77 return b.LayerInfoCache.Add(ctx, repo, dgst) 78 } 79 80 func (b *base) Meta(ctx context.Context, dgst digest.Digest) (LayerMeta, error) { 81 if dgst == "" { 82 return LayerMeta{}, fmt.Errorf("cache: cannot get meta for empty digest") 83 } 84 85 return b.LayerInfoCache.Meta(ctx, dgst) 86 } 87 88 func (b *base) SetMeta(ctx context.Context, dgst digest.Digest, meta LayerMeta) error { 89 if dgst == "" { 90 return fmt.Errorf("cache: cannot set meta for empty digest") 91 } 92 93 if meta.Path == "" { 94 return fmt.Errorf("cache: cannot set empty path for meta") 95 } 96 97 return b.LayerInfoCache.SetMeta(ctx, dgst, meta) 98 }