1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package base
39
40 import (
41 "context"
42 "io"
43 "time"
44
45 dcontext "github.com/docker/distribution/context"
46 prometheus "github.com/docker/distribution/metrics"
47 storagedriver "github.com/docker/distribution/registry/storage/driver"
48 "github.com/docker/go-metrics"
49 )
50
51 var (
52
53 storageAction = prometheus.StorageNamespace.NewLabeledTimer("action", "The number of seconds that the storage action takes", "driver", "action")
54 )
55
56 func init() {
57 metrics.Register(prometheus.StorageNamespace)
58 }
59
60
61
62 type Base struct {
63 storagedriver.StorageDriver
64 }
65
66
67 func (base *Base) setDriverName(e error) error {
68 switch actual := e.(type) {
69 case nil:
70 return nil
71 case storagedriver.ErrUnsupportedMethod:
72 actual.DriverName = base.StorageDriver.Name()
73 return actual
74 case storagedriver.PathNotFoundError:
75 actual.DriverName = base.StorageDriver.Name()
76 return actual
77 case storagedriver.InvalidPathError:
78 actual.DriverName = base.StorageDriver.Name()
79 return actual
80 case storagedriver.InvalidOffsetError:
81 actual.DriverName = base.StorageDriver.Name()
82 return actual
83 default:
84 storageError := storagedriver.Error{
85 DriverName: base.StorageDriver.Name(),
86 Enclosed: e,
87 }
88
89 return storageError
90 }
91 }
92
93
94 func (base *Base) GetContent(ctx context.Context, path string) ([]byte, error) {
95 ctx, done := dcontext.WithTrace(ctx)
96 defer done("%s.GetContent(%q)", base.Name(), path)
97
98 if !storagedriver.PathRegexp.MatchString(path) {
99 return nil, storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
100 }
101
102 start := time.Now()
103 b, e := base.StorageDriver.GetContent(ctx, path)
104 storageAction.WithValues(base.Name(), "GetContent").UpdateSince(start)
105 return b, base.setDriverName(e)
106 }
107
108
109 func (base *Base) PutContent(ctx context.Context, path string, content []byte) error {
110 ctx, done := dcontext.WithTrace(ctx)
111 defer done("%s.PutContent(%q)", base.Name(), path)
112
113 if !storagedriver.PathRegexp.MatchString(path) {
114 return storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
115 }
116
117 start := time.Now()
118 err := base.setDriverName(base.StorageDriver.PutContent(ctx, path, content))
119 storageAction.WithValues(base.Name(), "PutContent").UpdateSince(start)
120 return err
121 }
122
123
124 func (base *Base) Reader(ctx context.Context, path string, offset int64) (io.ReadCloser, error) {
125 ctx, done := dcontext.WithTrace(ctx)
126 defer done("%s.Reader(%q, %d)", base.Name(), path, offset)
127
128 if offset < 0 {
129 return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset, DriverName: base.StorageDriver.Name()}
130 }
131
132 if !storagedriver.PathRegexp.MatchString(path) {
133 return nil, storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
134 }
135
136 rc, e := base.StorageDriver.Reader(ctx, path, offset)
137 return rc, base.setDriverName(e)
138 }
139
140
141 func (base *Base) Writer(ctx context.Context, path string, append bool) (storagedriver.FileWriter, error) {
142 ctx, done := dcontext.WithTrace(ctx)
143 defer done("%s.Writer(%q, %v)", base.Name(), path, append)
144
145 if !storagedriver.PathRegexp.MatchString(path) {
146 return nil, storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
147 }
148
149 writer, e := base.StorageDriver.Writer(ctx, path, append)
150 return writer, base.setDriverName(e)
151 }
152
153
154 func (base *Base) Stat(ctx context.Context, path string) (storagedriver.FileInfo, error) {
155 ctx, done := dcontext.WithTrace(ctx)
156 defer done("%s.Stat(%q)", base.Name(), path)
157
158 if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
159 return nil, storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
160 }
161
162 start := time.Now()
163 fi, e := base.StorageDriver.Stat(ctx, path)
164 storageAction.WithValues(base.Name(), "Stat").UpdateSince(start)
165 return fi, base.setDriverName(e)
166 }
167
168
169 func (base *Base) List(ctx context.Context, path string) ([]string, error) {
170 ctx, done := dcontext.WithTrace(ctx)
171 defer done("%s.List(%q)", base.Name(), path)
172
173 if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
174 return nil, storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
175 }
176
177 start := time.Now()
178 str, e := base.StorageDriver.List(ctx, path)
179 storageAction.WithValues(base.Name(), "List").UpdateSince(start)
180 return str, base.setDriverName(e)
181 }
182
183
184 func (base *Base) Move(ctx context.Context, sourcePath string, destPath string) error {
185 ctx, done := dcontext.WithTrace(ctx)
186 defer done("%s.Move(%q, %q", base.Name(), sourcePath, destPath)
187
188 if !storagedriver.PathRegexp.MatchString(sourcePath) {
189 return storagedriver.InvalidPathError{Path: sourcePath, DriverName: base.StorageDriver.Name()}
190 } else if !storagedriver.PathRegexp.MatchString(destPath) {
191 return storagedriver.InvalidPathError{Path: destPath, DriverName: base.StorageDriver.Name()}
192 }
193
194 start := time.Now()
195 err := base.setDriverName(base.StorageDriver.Move(ctx, sourcePath, destPath))
196 storageAction.WithValues(base.Name(), "Move").UpdateSince(start)
197 return err
198 }
199
200
201 func (base *Base) Delete(ctx context.Context, path string) error {
202 ctx, done := dcontext.WithTrace(ctx)
203 defer done("%s.Delete(%q)", base.Name(), path)
204
205 if !storagedriver.PathRegexp.MatchString(path) {
206 return storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
207 }
208
209 start := time.Now()
210 err := base.setDriverName(base.StorageDriver.Delete(ctx, path))
211 storageAction.WithValues(base.Name(), "Delete").UpdateSince(start)
212 return err
213 }
214
215
216 func (base *Base) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) {
217 ctx, done := dcontext.WithTrace(ctx)
218 defer done("%s.URLFor(%q)", base.Name(), path)
219
220 if !storagedriver.PathRegexp.MatchString(path) {
221 return "", storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
222 }
223
224 start := time.Now()
225 str, e := base.StorageDriver.URLFor(ctx, path, options)
226 storageAction.WithValues(base.Name(), "URLFor").UpdateSince(start)
227 return str, base.setDriverName(e)
228 }
229
230
231 func (base *Base) Walk(ctx context.Context, path string, f storagedriver.WalkFn) error {
232 ctx, done := dcontext.WithTrace(ctx)
233 defer done("%s.Walk(%q)", base.Name(), path)
234
235 if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
236 return storagedriver.InvalidPathError{Path: path, DriverName: base.StorageDriver.Name()}
237 }
238
239 return base.setDriverName(base.StorageDriver.Walk(ctx, path, f))
240 }
241
View as plain text