Skip to content

Commit d04746b

Browse files
committed
Update metadata image store to be initialized once
The boltdb image store now manages its own transactions when one is not provided, but allows the caller to pass in a transaction through the context. This makes the image store more similar to the content and snapshot stores. Additionally, use the reference to the metadata database to mark the content store as dirty after an image has been deleted. The deletion of an image means a reference to a piece of content is gone and therefore garbage collection should be run to check if any resources can be cleaned up as a result. Signed-off-by: Derek McGowan <[email protected]>
1 parent 5a67161 commit d04746b

4 files changed

Lines changed: 183 additions & 212 deletions

File tree

metadata/db_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ func TestMetadataCollector(t *testing.T) {
222222

223223
if err := mdb.Update(func(tx *bolt.Tx) error {
224224
for _, obj := range objects {
225-
node, err := create(obj, tx, cs, sn)
225+
node, err := create(obj, tx, NewImageStore(mdb), cs, sn)
226226
if err != nil {
227227
return err
228228
}
@@ -297,7 +297,7 @@ func benchmarkTrigger(n int) func(b *testing.B) {
297297

298298
if err := mdb.Update(func(tx *bolt.Tx) error {
299299
for _, obj := range objects {
300-
node, err := create(obj, tx, cs, sn)
300+
node, err := create(obj, tx, NewImageStore(mdb), cs, sn)
301301
if err != nil {
302302
return err
303303
}
@@ -377,7 +377,7 @@ type object struct {
377377
labels map[string]string
378378
}
379379

380-
func create(obj object, tx *bolt.Tx, cs content.Store, sn snapshots.Snapshotter) (*gc.Node, error) {
380+
func create(obj object, tx *bolt.Tx, is images.Store, cs content.Store, sn snapshots.Snapshotter) (*gc.Node, error) {
381381
var (
382382
node *gc.Node
383383
namespace = "test"
@@ -430,12 +430,14 @@ func create(obj object, tx *bolt.Tx, cs content.Store, sn snapshots.Snapshotter)
430430
}
431431
}
432432
case testImage:
433+
ctx := WithTransactionContext(ctx, tx)
434+
433435
image := images.Image{
434436
Name: v.name,
435437
Target: v.target,
436438
Labels: obj.labels,
437439
}
438-
_, err := NewImageStore(tx).Create(ctx, image)
440+
_, err := is.Create(ctx, image)
439441
if err != nil {
440442
return nil, errors.Wrap(err, "failed to create image")
441443
}

metadata/images.go

Lines changed: 83 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import (
2020
)
2121

2222
type imageStore struct {
23-
tx *bolt.Tx
23+
db *DB
2424
}
2525

2626
// NewImageStore returns a store backed by a bolt DB
27-
func NewImageStore(tx *bolt.Tx) images.Store {
28-
return &imageStore{tx: tx}
27+
func NewImageStore(db *DB) images.Store {
28+
return &imageStore{db: db}
2929
}
3030

3131
func (s *imageStore) Get(ctx context.Context, name string) (images.Image, error) {
@@ -36,19 +36,25 @@ func (s *imageStore) Get(ctx context.Context, name string) (images.Image, error)
3636
return images.Image{}, err
3737
}
3838

39-
bkt := getImagesBucket(s.tx, namespace)
40-
if bkt == nil {
41-
return images.Image{}, errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
42-
}
39+
if err := view(ctx, s.db, func(tx *bolt.Tx) error {
40+
bkt := getImagesBucket(tx, namespace)
41+
if bkt == nil {
42+
return errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
43+
}
4344

44-
ibkt := bkt.Bucket([]byte(name))
45-
if ibkt == nil {
46-
return images.Image{}, errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
47-
}
45+
ibkt := bkt.Bucket([]byte(name))
46+
if ibkt == nil {
47+
return errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
48+
}
4849

49-
image.Name = name
50-
if err := readImage(&image, ibkt); err != nil {
51-
return images.Image{}, errors.Wrapf(err, "image %q", name)
50+
image.Name = name
51+
if err := readImage(&image, ibkt); err != nil {
52+
return errors.Wrapf(err, "image %q", name)
53+
}
54+
55+
return nil
56+
}); err != nil {
57+
return images.Image{}, err
5258
}
5359

5460
return image, nil
@@ -65,28 +71,30 @@ func (s *imageStore) List(ctx context.Context, fs ...string) ([]images.Image, er
6571
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error())
6672
}
6773

68-
bkt := getImagesBucket(s.tx, namespace)
69-
if bkt == nil {
70-
return nil, nil // empty store
71-
}
72-
7374
var m []images.Image
74-
if err := bkt.ForEach(func(k, v []byte) error {
75-
var (
76-
image = images.Image{
77-
Name: string(k),
78-
}
79-
kbkt = bkt.Bucket(k)
80-
)
81-
82-
if err := readImage(&image, kbkt); err != nil {
83-
return err
75+
if err := view(ctx, s.db, func(tx *bolt.Tx) error {
76+
bkt := getImagesBucket(tx, namespace)
77+
if bkt == nil {
78+
return nil // empty store
8479
}
8580

86-
if filter.Match(adaptImage(image)) {
87-
m = append(m, image)
88-
}
89-
return nil
81+
return bkt.ForEach(func(k, v []byte) error {
82+
var (
83+
image = images.Image{
84+
Name: string(k),
85+
}
86+
kbkt = bkt.Bucket(k)
87+
)
88+
89+
if err := readImage(&image, kbkt); err != nil {
90+
return err
91+
}
92+
93+
if filter.Match(adaptImage(image)) {
94+
m = append(m, image)
95+
}
96+
return nil
97+
})
9098
}); err != nil {
9199
return nil, err
92100
}
@@ -100,11 +108,16 @@ func (s *imageStore) Create(ctx context.Context, image images.Image) (images.Ima
100108
return images.Image{}, err
101109
}
102110

103-
if err := validateImage(&image); err != nil {
104-
return images.Image{}, err
105-
}
111+
if err := update(ctx, s.db, func(tx *bolt.Tx) error {
112+
if err := validateImage(&image); err != nil {
113+
return err
114+
}
115+
116+
bkt, err := createImagesBucket(tx, namespace)
117+
if err != nil {
118+
return err
119+
}
106120

107-
return image, withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
108121
ibkt, err := bkt.CreateBucket([]byte(image.Name))
109122
if err != nil {
110123
if err != bolt.ErrBucketExists {
@@ -117,7 +130,11 @@ func (s *imageStore) Create(ctx context.Context, image images.Image) (images.Ima
117130
image.CreatedAt = time.Now().UTC()
118131
image.UpdatedAt = image.CreatedAt
119132
return writeImage(ibkt, &image)
120-
})
133+
}); err != nil {
134+
return images.Image{}, err
135+
}
136+
137+
return image, nil
121138
}
122139

123140
func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths ...string) (images.Image, error) {
@@ -131,7 +148,13 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths
131148
}
132149

133150
var updated images.Image
134-
return updated, withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
151+
152+
if err := update(ctx, s.db, func(tx *bolt.Tx) error {
153+
bkt, err := createImagesBucket(tx, namespace)
154+
if err != nil {
155+
return err
156+
}
157+
135158
ibkt := bkt.Bucket([]byte(image.Name))
136159
if ibkt == nil {
137160
return errors.Wrapf(errdefs.ErrNotFound, "image %q", image.Name)
@@ -180,7 +203,12 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths
180203
updated.CreatedAt = createdat
181204
updated.UpdatedAt = time.Now().UTC()
182205
return writeImage(ibkt, &updated)
183-
})
206+
}); err != nil {
207+
return images.Image{}, err
208+
}
209+
210+
return updated, nil
211+
184212
}
185213

186214
func (s *imageStore) Delete(ctx context.Context, name string, opts ...images.DeleteOpt) error {
@@ -189,11 +217,24 @@ func (s *imageStore) Delete(ctx context.Context, name string, opts ...images.Del
189217
return err
190218
}
191219

192-
return withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
193-
err := bkt.DeleteBucket([]byte(name))
220+
return update(ctx, s.db, func(tx *bolt.Tx) error {
221+
bkt := getImagesBucket(tx, namespace)
222+
if bkt == nil {
223+
return errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
224+
}
225+
226+
err = bkt.DeleteBucket([]byte(name))
194227
if err == bolt.ErrBucketNotFound {
195228
return errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
196229
}
230+
231+
// A reference to a piece of content has been removed,
232+
// mark content store as dirty for triggering garbage
233+
// collection
234+
s.db.dirtyL.Lock()
235+
s.db.dirtyCS = true
236+
s.db.dirtyL.Unlock()
237+
197238
return err
198239
})
199240
}

0 commit comments

Comments
 (0)