1 package memory
2
3 import (
4 "context"
5 "sync"
6
7 "github.com/distribution/reference"
8 "github.com/docker/distribution"
9 "github.com/docker/distribution/registry/storage/cache"
10 "github.com/opencontainers/go-digest"
11 )
12
13 type inMemoryBlobDescriptorCacheProvider struct {
14 global *mapBlobDescriptorCache
15 repositories map[string]*mapBlobDescriptorCache
16 mu sync.RWMutex
17 }
18
19
20
21 func NewInMemoryBlobDescriptorCacheProvider() cache.BlobDescriptorCacheProvider {
22 return &inMemoryBlobDescriptorCacheProvider{
23 global: newMapBlobDescriptorCache(),
24 repositories: make(map[string]*mapBlobDescriptorCache),
25 }
26 }
27
28 func (imbdcp *inMemoryBlobDescriptorCacheProvider) RepositoryScoped(repo string) (distribution.BlobDescriptorService, error) {
29 if _, err := reference.ParseNormalizedNamed(repo); err != nil {
30 return nil, err
31 }
32
33 imbdcp.mu.RLock()
34 defer imbdcp.mu.RUnlock()
35
36 return &repositoryScopedInMemoryBlobDescriptorCache{
37 repo: repo,
38 parent: imbdcp,
39 repository: imbdcp.repositories[repo],
40 }, nil
41 }
42
43 func (imbdcp *inMemoryBlobDescriptorCacheProvider) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
44 return imbdcp.global.Stat(ctx, dgst)
45 }
46
47 func (imbdcp *inMemoryBlobDescriptorCacheProvider) Clear(ctx context.Context, dgst digest.Digest) error {
48 return imbdcp.global.Clear(ctx, dgst)
49 }
50
51 func (imbdcp *inMemoryBlobDescriptorCacheProvider) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
52 _, err := imbdcp.Stat(ctx, dgst)
53 if err == distribution.ErrBlobUnknown {
54
55 if dgst.Algorithm() != desc.Digest.Algorithm() && dgst != desc.Digest {
56
57 if err := imbdcp.global.SetDescriptor(ctx, desc.Digest, desc); err != nil {
58 return err
59 }
60 }
61
62
63 return imbdcp.global.SetDescriptor(ctx, dgst, desc)
64 }
65
66
67 return err
68 }
69
70
71
72
73 type repositoryScopedInMemoryBlobDescriptorCache struct {
74 repo string
75 parent *inMemoryBlobDescriptorCacheProvider
76 repository *mapBlobDescriptorCache
77 }
78
79 func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
80 rsimbdcp.parent.mu.Lock()
81 repo := rsimbdcp.repository
82 rsimbdcp.parent.mu.Unlock()
83
84 if repo == nil {
85 return distribution.Descriptor{}, distribution.ErrBlobUnknown
86 }
87
88 return repo.Stat(ctx, dgst)
89 }
90
91 func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
92 rsimbdcp.parent.mu.Lock()
93 repo := rsimbdcp.repository
94 rsimbdcp.parent.mu.Unlock()
95
96 if repo == nil {
97 return distribution.ErrBlobUnknown
98 }
99
100 return repo.Clear(ctx, dgst)
101 }
102
103 func (rsimbdcp *repositoryScopedInMemoryBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
104 rsimbdcp.parent.mu.Lock()
105 repo := rsimbdcp.repository
106 if repo == nil {
107
108 var ok bool
109
110 repo, ok = rsimbdcp.parent.repositories[rsimbdcp.repo]
111 if !ok {
112 repo = newMapBlobDescriptorCache()
113 rsimbdcp.parent.repositories[rsimbdcp.repo] = repo
114 }
115 rsimbdcp.repository = repo
116 }
117 rsimbdcp.parent.mu.Unlock()
118
119 if err := repo.SetDescriptor(ctx, dgst, desc); err != nil {
120 return err
121 }
122
123 return rsimbdcp.parent.SetDescriptor(ctx, dgst, desc)
124 }
125
126
127
128 type mapBlobDescriptorCache struct {
129 descriptors map[digest.Digest]distribution.Descriptor
130 mu sync.RWMutex
131 }
132
133 var _ distribution.BlobDescriptorService = &mapBlobDescriptorCache{}
134
135 func newMapBlobDescriptorCache() *mapBlobDescriptorCache {
136 return &mapBlobDescriptorCache{
137 descriptors: make(map[digest.Digest]distribution.Descriptor),
138 }
139 }
140
141 func (mbdc *mapBlobDescriptorCache) Stat(ctx context.Context, dgst digest.Digest) (distribution.Descriptor, error) {
142 if err := dgst.Validate(); err != nil {
143 return distribution.Descriptor{}, err
144 }
145
146 mbdc.mu.RLock()
147 defer mbdc.mu.RUnlock()
148
149 desc, ok := mbdc.descriptors[dgst]
150 if !ok {
151 return distribution.Descriptor{}, distribution.ErrBlobUnknown
152 }
153
154 return desc, nil
155 }
156
157 func (mbdc *mapBlobDescriptorCache) Clear(ctx context.Context, dgst digest.Digest) error {
158 mbdc.mu.Lock()
159 defer mbdc.mu.Unlock()
160
161 delete(mbdc.descriptors, dgst)
162 return nil
163 }
164
165 func (mbdc *mapBlobDescriptorCache) SetDescriptor(ctx context.Context, dgst digest.Digest, desc distribution.Descriptor) error {
166 if err := dgst.Validate(); err != nil {
167 return err
168 }
169
170 if err := cache.ValidateDescriptor(desc); err != nil {
171 return err
172 }
173
174 mbdc.mu.Lock()
175 defer mbdc.mu.Unlock()
176
177 mbdc.descriptors[dgst] = desc
178 return nil
179 }
180
View as plain text