Move boltdb implementation to storage package

Removes storage interface and replaces with storage functions.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
Derek McGowan 2017-03-24 17:16:41 -07:00
parent 8affca40bb
commit b319ba7c5a
No known key found for this signature in database
GPG key ID: F58C5D0A4405ACDB
12 changed files with 373 additions and 404 deletions

View file

@ -12,7 +12,6 @@ import (
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage" "github.com/containerd/containerd/snapshot/storage"
"github.com/containerd/containerd/snapshot/storage/boltdb"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stevvooe/go-btrfs" "github.com/stevvooe/go-btrfs"
) )
@ -32,13 +31,7 @@ func init() {
// TODO: check device for root // TODO: check device for root
return nil, errors.Errorf("btrfs requires \"device\" configuration") return nil, errors.Errorf("btrfs requires \"device\" configuration")
} }
return NewSnapshotter(conf.Device, root)
ms, err := boltdb.NewMetaStore(ic.Context, filepath.Join(root, "metadata.db"))
if err != nil {
return nil, err
}
return NewSnapshotter(conf.Device, root, ms)
}, },
}) })
} }
@ -46,10 +39,10 @@ func init() {
type Snapshotter struct { type Snapshotter struct {
device string // maybe we can resolve it with path? device string // maybe we can resolve it with path?
root string // root provides paths for internal storage. root string // root provides paths for internal storage.
ms storage.MetaStore ms *storage.MetaStore
} }
func NewSnapshotter(device, root string, ms storage.MetaStore) (snapshot.Snapshotter, error) { func NewSnapshotter(device, root string) (snapshot.Snapshotter, error) {
var ( var (
active = filepath.Join(root, "active") active = filepath.Join(root, "active")
snapshots = filepath.Join(root, "snapshots") snapshots = filepath.Join(root, "snapshots")
@ -63,6 +56,10 @@ func NewSnapshotter(device, root string, ms storage.MetaStore) (snapshot.Snapsho
return nil, err return nil, err
} }
} }
ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db"))
if err != nil {
return nil, err
}
return &Snapshotter{ return &Snapshotter{
device: device, device: device,
@ -82,7 +79,7 @@ func (b *Snapshotter) Stat(ctx context.Context, key string) (snapshot.Info, erro
return snapshot.Info{}, err return snapshot.Info{}, err
} }
defer t.Rollback() defer t.Rollback()
return b.ms.Stat(ctx, key) return storage.GetInfo(ctx, key)
} }
// Walk the committed snapshots. // Walk the committed snapshots.
@ -92,7 +89,7 @@ func (b *Snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho
return err return err
} }
defer t.Rollback() defer t.Rollback()
return b.ms.Walk(ctx, fn) return storage.WalkInfo(ctx, fn)
} }
func (b *Snapshotter) Prepare(ctx context.Context, key, parent string) ([]containerd.Mount, error) { func (b *Snapshotter) Prepare(ctx context.Context, key, parent string) ([]containerd.Mount, error) {
@ -116,7 +113,7 @@ func (b *Snapshotter) makeActive(ctx context.Context, key, parent string, readon
} }
}() }()
a, err := b.ms.CreateActive(ctx, key, parent, readonly) a, err := storage.CreateActive(ctx, key, parent, readonly)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -187,7 +184,7 @@ func (b *Snapshotter) Commit(ctx context.Context, name, key string) (err error)
} }
}() }()
id, err := b.ms.Commit(ctx, key, name) id, err := storage.CommitActive(ctx, key, name)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to commit") return errors.Wrap(err, "failed to commit")
} }
@ -225,7 +222,7 @@ func (b *Snapshotter) Mounts(ctx context.Context, key string) ([]containerd.Moun
if err != nil { if err != nil {
return nil, err return nil, err
} }
a, err := b.ms.GetActive(ctx, key) a, err := storage.GetActive(ctx, key)
t.Rollback() t.Rollback()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to get active snapshot") return nil, errors.Wrap(err, "failed to get active snapshot")
@ -260,7 +257,7 @@ func (b *Snapshotter) Remove(ctx context.Context, key string) (err error) {
} }
}() }()
id, k, err := b.ms.Remove(ctx, key) id, k, err := storage.Remove(ctx, key)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to remove snapshot") return errors.Wrap(err, "failed to remove snapshot")
} }

View file

@ -11,7 +11,6 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage/boltdb"
"github.com/containerd/containerd/snapshot/testsuite" "github.com/containerd/containerd/snapshot/testsuite"
"github.com/containerd/containerd/testutil" "github.com/containerd/containerd/testutil"
) )
@ -23,11 +22,7 @@ const (
func boltSnapshotter(t *testing.T) func(context.Context, string) (snapshot.Snapshotter, func(), error) { func boltSnapshotter(t *testing.T) func(context.Context, string) (snapshot.Snapshotter, func(), error) {
return func(ctx context.Context, root string) (snapshot.Snapshotter, func(), error) { return func(ctx context.Context, root string) (snapshot.Snapshotter, func(), error) {
device := setupBtrfsLoopbackDevice(t, root) device := setupBtrfsLoopbackDevice(t, root)
store, err := boltdb.NewMetaStore(ctx, filepath.Join(root, "metadata.db")) snapshotter, err := NewSnapshotter(device.deviceName, root)
if err != nil {
return nil, nil, err
}
snapshotter, err := NewSnapshotter(device.deviceName, root, store)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -13,7 +13,6 @@ import (
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage" "github.com/containerd/containerd/snapshot/storage"
"github.com/containerd/containerd/snapshot/storage/boltdb"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -21,19 +20,14 @@ func init() {
plugin.Register("snapshot-overlay", &plugin.Registration{ plugin.Register("snapshot-overlay", &plugin.Registration{
Type: plugin.SnapshotPlugin, Type: plugin.SnapshotPlugin,
Init: func(ic *plugin.InitContext) (interface{}, error) { Init: func(ic *plugin.InitContext) (interface{}, error) {
root := filepath.Join(ic.Root, "snapshot", "overlay") return NewSnapshotter(filepath.Join(ic.Root, "snapshot", "overlay"))
ms, err := boltdb.NewMetaStore(ic.Context, filepath.Join(root, "metadata.db"))
if err != nil {
return nil, err
}
return NewSnapshotter(root, ms)
}, },
}) })
} }
type Snapshotter struct { type Snapshotter struct {
root string root string
ms storage.MetaStore ms *storage.MetaStore
} }
type activeSnapshot struct { type activeSnapshot struct {
@ -43,11 +37,16 @@ type activeSnapshot struct {
readonly bool readonly bool
} }
func NewSnapshotter(root string, ms storage.MetaStore) (snapshot.Snapshotter, error) { func NewSnapshotter(root string) (snapshot.Snapshotter, error) {
if err := os.MkdirAll(root, 0700); err != nil { if err := os.MkdirAll(root, 0700); err != nil {
return nil, err return nil, err
} }
if err := os.MkdirAll(filepath.Join(root, "snapshots"), 0700); err != nil { ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db"))
if err != nil {
return nil, err
}
if err := os.Mkdir(filepath.Join(root, "snapshots"), 0700); err != nil {
return nil, err return nil, err
} }
@ -68,7 +67,7 @@ func (o *Snapshotter) Stat(ctx context.Context, key string) (snapshot.Info, erro
return snapshot.Info{}, err return snapshot.Info{}, err
} }
defer t.Rollback() defer t.Rollback()
return o.ms.Stat(ctx, key) return storage.GetInfo(ctx, key)
} }
func (o *Snapshotter) Prepare(ctx context.Context, key, parent string) ([]containerd.Mount, error) { func (o *Snapshotter) Prepare(ctx context.Context, key, parent string) ([]containerd.Mount, error) {
@ -88,7 +87,7 @@ func (o *Snapshotter) Mounts(ctx context.Context, key string) ([]containerd.Moun
if err != nil { if err != nil {
return nil, err return nil, err
} }
active, err := o.ms.GetActive(ctx, key) active, err := storage.GetActive(ctx, key)
t.Rollback() t.Rollback()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to get active mount") return nil, errors.Wrap(err, "failed to get active mount")
@ -101,7 +100,7 @@ func (o *Snapshotter) Commit(ctx context.Context, name, key string) error {
if err != nil { if err != nil {
return err return err
} }
if _, err := o.ms.Commit(ctx, key, name); err != nil { if _, err := storage.CommitActive(ctx, key, name); err != nil {
if rerr := t.Rollback(); rerr != nil { if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
} }
@ -125,7 +124,7 @@ func (o *Snapshotter) Remove(ctx context.Context, key string) (err error) {
} }
}() }()
id, _, err := o.ms.Remove(ctx, key) id, _, err := storage.Remove(ctx, key)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to remove") return errors.Wrap(err, "failed to remove")
} }
@ -160,7 +159,7 @@ func (o *Snapshotter) Walk(ctx context.Context, fn func(context.Context, snapsho
return err return err
} }
defer t.Rollback() defer t.Rollback()
return o.ms.Walk(ctx, fn) return storage.WalkInfo(ctx, fn)
} }
func (o *Snapshotter) createActive(ctx context.Context, key, parent string, readonly bool) ([]containerd.Mount, error) { func (o *Snapshotter) createActive(ctx context.Context, key, parent string, readonly bool) ([]containerd.Mount, error) {
@ -202,7 +201,7 @@ func (o *Snapshotter) createActive(ctx context.Context, key, parent string, read
return nil, err return nil, err
} }
active, err := o.ms.CreateActive(ctx, key, parent, readonly) active, err := storage.CreateActive(ctx, key, parent, readonly)
if err != nil { if err != nil {
if rerr := t.Rollback(); rerr != nil { if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
@ -211,7 +210,7 @@ func (o *Snapshotter) createActive(ctx context.Context, key, parent string, read
} }
path = filepath.Join(snapshotDir, active.ID) path = filepath.Join(snapshotDir, active.ID)
if err := os.Rename(td, path); err != nil { if err = os.Rename(td, path); err != nil {
if rerr := t.Rollback(); rerr != nil { if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction") log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
} }
@ -219,7 +218,7 @@ func (o *Snapshotter) createActive(ctx context.Context, key, parent string, read
} }
td = "" td = ""
if err := t.Commit(); err != nil { if err = t.Commit(); err != nil {
return nil, errors.Wrap(err, "commit failed") return nil, errors.Wrap(err, "commit failed")
} }

View file

@ -11,17 +11,13 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage/boltdb" "github.com/containerd/containerd/snapshot/storage"
"github.com/containerd/containerd/snapshot/testsuite" "github.com/containerd/containerd/snapshot/testsuite"
"github.com/containerd/containerd/testutil" "github.com/containerd/containerd/testutil"
) )
func boltSnapshotter(ctx context.Context, root string) (snapshot.Snapshotter, func(), error) { func newSnapshotter(ctx context.Context, root string) (snapshot.Snapshotter, func(), error) {
store, err := boltdb.NewMetaStore(ctx, filepath.Join(root, "metadata.db")) snapshotter, err := NewSnapshotter(root)
if err != nil {
return nil, nil, err
}
snapshotter, err := NewSnapshotter(root, store)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -31,7 +27,7 @@ func boltSnapshotter(ctx context.Context, root string) (snapshot.Snapshotter, fu
func TestOverlay(t *testing.T) { func TestOverlay(t *testing.T) {
testutil.RequiresRoot(t) testutil.RequiresRoot(t)
testsuite.SnapshotterSuite(t, "Overlay", boltSnapshotter) testsuite.SnapshotterSuite(t, "Overlay", newSnapshotter)
} }
func TestOverlayMounts(t *testing.T) { func TestOverlayMounts(t *testing.T) {
@ -41,7 +37,7 @@ func TestOverlayMounts(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(root) defer os.RemoveAll(root)
o, _, err := boltSnapshotter(ctx, root) o, _, err := newSnapshotter(ctx, root)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -77,7 +73,7 @@ func TestOverlayCommit(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(root) defer os.RemoveAll(root)
o, _, err := boltSnapshotter(ctx, root) o, _, err := newSnapshotter(ctx, root)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -106,7 +102,7 @@ func TestOverlayOverlayMount(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(root) defer os.RemoveAll(root)
o, _, err := boltSnapshotter(ctx, root) o, _, err := newSnapshotter(ctx, root)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -160,7 +156,7 @@ func getBasePath(ctx context.Context, sn snapshot.Snapshotter, root, key string)
} }
defer t.Rollback() defer t.Rollback()
active, err := o.ms.GetActive(ctx, key) active, err := storage.GetActive(ctx, key)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -175,7 +171,7 @@ func getParents(ctx context.Context, sn snapshot.Snapshotter, root, key string)
panic(err) panic(err)
} }
defer t.Rollback() defer t.Rollback()
active, err := o.ms.GetActive(ctx, key) active, err := storage.GetActive(ctx, key)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -194,7 +190,7 @@ func TestOverlayOverlayRead(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(root) defer os.RemoveAll(root)
o, _, err := boltSnapshotter(ctx, root) o, _, err := newSnapshotter(ctx, root)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -246,7 +242,7 @@ func TestOverlayView(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(root) defer os.RemoveAll(root)
o, _, err := boltSnapshotter(ctx, root) o, _, err := newSnapshotter(ctx, root)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -1,4 +1,4 @@
package boltdb package storage
import ( import (
"context" "context"
@ -7,7 +7,7 @@ import (
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage" db "github.com/containerd/containerd/snapshot/storage/proto"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -23,91 +23,14 @@ type boltFileTransactor struct {
tx *bolt.Tx tx *bolt.Tx
} }
type boltMetastore struct { func (bft *boltFileTransactor) Rollback() error {
dbfile string defer bft.db.Close()
return bft.tx.Rollback()
} }
// NewMetaStore returns a snapshot MetaStore for storage of metadata related to func (bft *boltFileTransactor) Commit() error {
// a snapshot driver backed by a bolt file database. This implementation is defer bft.db.Close()
// strongly consistent and does all metadata changes in a transaction to prevent return bft.tx.Commit()
// against process crashes causing inconsistent metadata state.
func NewMetaStore(ctx context.Context, dbfile string) (storage.MetaStore, error) {
return &boltMetastore{
dbfile: dbfile,
}, nil
}
func (ms *boltFileTransactor) Rollback() error {
defer ms.db.Close()
return ms.tx.Rollback()
}
func (ms *boltFileTransactor) Commit() error {
defer ms.db.Close()
return ms.tx.Commit()
}
type transactionKey struct{}
func (ms *boltMetastore) TransactionContext(ctx context.Context, writable bool) (context.Context, storage.Transactor, error) {
db, err := bolt.Open(ms.dbfile, 0600, nil)
if err != nil {
return ctx, nil, errors.Wrap(err, "failed to open database file")
}
tx, err := db.Begin(writable)
if err != nil {
return ctx, nil, errors.Wrap(err, "failed to start transaction")
}
t := &boltFileTransactor{
db: db,
tx: tx,
}
ctx = context.WithValue(ctx, transactionKey{}, t)
return ctx, t, nil
}
func (ms *boltMetastore) withBucket(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok {
return errors.Errorf("no transaction in context")
}
bkt := t.tx.Bucket(bucketKeyStorageVersion)
if bkt == nil {
return errors.Wrap(snapshot.ErrSnapshotNotExist, "bucket does not exist")
}
return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents))
}
func (ms *boltMetastore) createBucketIfNotExists(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok {
return errors.Errorf("no transaction in context")
}
bkt, err := t.tx.CreateBucketIfNotExists(bucketKeyStorageVersion)
if err != nil {
return errors.Wrap(err, "failed to create version bucket")
}
sbkt, err := bkt.CreateBucketIfNotExists(bucketKeySnapshot)
if err != nil {
return errors.Wrap(err, "failed to create snapshots bucket")
}
pbkt, err := bkt.CreateBucketIfNotExists(bucketKeyParents)
if err != nil {
return errors.Wrap(err, "failed to create snapshots bucket")
}
return fn(ctx, sbkt, pbkt)
}
func fromProtoKind(k Kind) snapshot.Kind {
if k == KindActive {
return snapshot.KindActive
}
return snapshot.KindCommitted
} }
// parentKey returns a composite key of the parent and child identifiers. The // parentKey returns a composite key of the parent and child identifiers. The
@ -134,9 +57,11 @@ func getParentPrefix(b []byte) uint64 {
return parent return parent
} }
func (ms *boltMetastore) Stat(ctx context.Context, key string) (snapshot.Info, error) { // GetInfo returns the snapshot Info directly from the metadata. Requires a
var ss Snapshot // context with a storage transaction.
err := ms.withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { func GetInfo(ctx context.Context, key string) (snapshot.Info, error) {
var ss db.Snapshot
err := withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
return getSnapshot(bkt, key, &ss) return getSnapshot(bkt, key, &ss)
}) })
if err != nil { if err != nil {
@ -151,14 +76,17 @@ func (ms *boltMetastore) Stat(ctx context.Context, key string) (snapshot.Info, e
}, nil }, nil
} }
func (ms *boltMetastore) Walk(ctx context.Context, fn func(context.Context, snapshot.Info) error) error { // WalkInfo iterates through all metadata Info for the stored snapshots and
return ms.withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { // calls the provided function for each. Requires a context with a storage
// transaction.
func WalkInfo(ctx context.Context, fn func(context.Context, snapshot.Info) error) error {
return withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
return bkt.ForEach(func(k, v []byte) error { return bkt.ForEach(func(k, v []byte) error {
// skip nested buckets // skip nested buckets
if v == nil { if v == nil {
return nil return nil
} }
var ss Snapshot var ss db.Snapshot
if err := proto.Unmarshal(v, &ss); err != nil { if err := proto.Unmarshal(v, &ss); err != nil {
return errors.Wrap(err, "failed to unmarshal snapshot") return errors.Wrap(err, "failed to unmarshal snapshot")
} }
@ -174,18 +102,23 @@ func (ms *boltMetastore) Walk(ctx context.Context, fn func(context.Context, snap
}) })
} }
func (ms *boltMetastore) CreateActive(ctx context.Context, key, parent string, readonly bool) (a storage.Active, err error) { // CreateActive creates a new active snapshot transaction referenced by
err = ms.createBucketIfNotExists(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { // the provided key. The new active snapshot will have the provided
// parent. If the readonly option is given, the active snapshot will be
// marked as readonly and can only be removed, and not committed. The
// provided context must contain a writable transaction.
func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Active, err error) {
err = createBucketIfNotExists(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
var ( var (
parentS *Snapshot parentS *db.Snapshot
) )
if parent != "" { if parent != "" {
parentS = new(Snapshot) parentS = new(db.Snapshot)
if err := getSnapshot(bkt, parent, parentS); err != nil { if err := getSnapshot(bkt, parent, parentS); err != nil {
return errors.Wrap(err, "failed to get parent snapshot") return errors.Wrap(err, "failed to get parent snapshot")
} }
if parentS.Kind != KindCommitted { if parentS.Kind != db.KindCommitted {
return errors.Wrap(snapshot.ErrSnapshotNotCommitted, "parent is not committed snapshot") return errors.Wrap(snapshot.ErrSnapshotNotCommitted, "parent is not committed snapshot")
} }
} }
@ -199,10 +132,10 @@ func (ms *boltMetastore) CreateActive(ctx context.Context, key, parent string, r
return errors.Wrap(err, "unable to get identifier") return errors.Wrap(err, "unable to get identifier")
} }
ss := Snapshot{ ss := db.Snapshot{
ID: id, ID: id,
Parent: parent, Parent: parent,
Kind: KindActive, Kind: db.KindActive,
Readonly: readonly, Readonly: readonly,
} }
if err := putSnapshot(bkt, key, &ss); err != nil { if err := putSnapshot(bkt, key, &ss); err != nil {
@ -216,7 +149,7 @@ func (ms *boltMetastore) CreateActive(ctx context.Context, key, parent string, r
return errors.Wrap(err, "failed to write parent link") return errors.Wrap(err, "failed to write parent link")
} }
a.ParentIDs, err = ms.parents(bkt, parentS) a.ParentIDs, err = parents(bkt, parentS)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get parent chain") return errors.Wrap(err, "failed to get parent chain")
} }
@ -228,24 +161,26 @@ func (ms *boltMetastore) CreateActive(ctx context.Context, key, parent string, r
return nil return nil
}) })
if err != nil { if err != nil {
return storage.Active{}, err return Active{}, err
} }
return return
} }
func (ms *boltMetastore) GetActive(ctx context.Context, key string) (a storage.Active, err error) { // GetActive returns the metadata for the active snapshot transaction referenced
err = ms.withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { // by the given key. Requires a context with a storage transaction.
func GetActive(ctx context.Context, key string) (a Active, err error) {
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
b := bkt.Get([]byte(key)) b := bkt.Get([]byte(key))
if len(b) == 0 { if len(b) == 0 {
return snapshot.ErrSnapshotNotExist return snapshot.ErrSnapshotNotExist
} }
var ss Snapshot var ss db.Snapshot
if err := proto.Unmarshal(b, &ss); err != nil { if err := proto.Unmarshal(b, &ss); err != nil {
return errors.Wrap(err, "failed to unmarshal snapshot") return errors.Wrap(err, "failed to unmarshal snapshot")
} }
if ss.Kind != KindActive { if ss.Kind != db.KindActive {
return snapshot.ErrSnapshotNotActive return snapshot.ErrSnapshotNotActive
} }
@ -253,12 +188,12 @@ func (ms *boltMetastore) GetActive(ctx context.Context, key string) (a storage.A
a.Readonly = ss.Readonly a.Readonly = ss.Readonly
if ss.Parent != "" { if ss.Parent != "" {
var parent Snapshot var parent db.Snapshot
if err := getSnapshot(bkt, ss.Parent, &parent); err != nil { if err := getSnapshot(bkt, ss.Parent, &parent); err != nil {
return errors.Wrap(err, "failed to get parent snapshot") return errors.Wrap(err, "failed to get parent snapshot")
} }
a.ParentIDs, err = ms.parents(bkt, &parent) a.ParentIDs, err = parents(bkt, &parent)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to get parent chain") return errors.Wrap(err, "failed to get parent chain")
} }
@ -266,33 +201,18 @@ func (ms *boltMetastore) GetActive(ctx context.Context, key string) (a storage.A
return nil return nil
}) })
if err != nil { if err != nil {
return storage.Active{}, err return Active{}, err
} }
return return
} }
func (ms *boltMetastore) parents(bkt *bolt.Bucket, parent *Snapshot) (parents []string, err error) { // Remove removes a snapshot from the metastore. The string identifier for the
for { // snapshot is returned as well as the kind. The provided context must contain a
parents = append(parents, fmt.Sprintf("%d", parent.ID)) // writable transaction.
func Remove(ctx context.Context, key string) (id string, k snapshot.Kind, err error) {
if parent.Parent == "" { err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
return var ss db.Snapshot
}
var ps Snapshot
if err := getSnapshot(bkt, parent.Parent, &ps); err != nil {
return nil, errors.Wrap(err, "failed to get parent snapshot")
}
parent = &ps
}
return
}
func (ms *boltMetastore) Remove(ctx context.Context, key string) (id string, k snapshot.Kind, err error) {
err = ms.withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
var ss Snapshot
b := bkt.Get([]byte(key)) b := bkt.Get([]byte(key))
if len(b) == 0 { if len(b) == 0 {
return snapshot.ErrSnapshotNotExist return snapshot.ErrSnapshotNotExist
@ -309,7 +229,7 @@ func (ms *boltMetastore) Remove(ctx context.Context, key string) (id string, k s
} }
if ss.Parent != "" { if ss.Parent != "" {
var ps Snapshot var ps db.Snapshot
if err := getSnapshot(bkt, ss.Parent, &ps); err != nil { if err := getSnapshot(bkt, ss.Parent, &ps); err != nil {
return errors.Wrap(err, "failed to get parent snapshot") return errors.Wrap(err, "failed to get parent snapshot")
} }
@ -333,25 +253,31 @@ func (ms *boltMetastore) Remove(ctx context.Context, key string) (id string, k s
return return
} }
func (ms *boltMetastore) Commit(ctx context.Context, key, name string) (id string, err error) { // CommitActive renames the active snapshot transaction referenced by `key`
err = ms.withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error { // as a committed snapshot referenced by `Name`. The resulting snapshot will be
// committed and readonly. The `key` reference will no longer be available for
// lookup or removal. The returned string identifier for the committed snapshot
// is the same identifier of the original active snapshot. The provided context
// must contain a writable transaction.
func CommitActive(ctx context.Context, key, name string) (id string, err error) {
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
b := bkt.Get([]byte(name)) b := bkt.Get([]byte(name))
if len(b) != 0 { if len(b) != 0 {
return errors.Wrap(snapshot.ErrSnapshotExist, "committed name already exists") return errors.Wrap(snapshot.ErrSnapshotExist, "committed name already exists")
} }
var ss Snapshot var ss db.Snapshot
if err := getSnapshot(bkt, key, &ss); err != nil { if err := getSnapshot(bkt, key, &ss); err != nil {
return errors.Wrap(err, "failed to get active snapshot") return errors.Wrap(err, "failed to get active snapshot")
} }
if ss.Kind != KindActive { if ss.Kind != db.KindActive {
return snapshot.ErrSnapshotNotActive return snapshot.ErrSnapshotNotActive
} }
if ss.Readonly { if ss.Readonly {
return errors.Errorf("active snapshot is readonly") return errors.Errorf("active snapshot is readonly")
} }
ss.Kind = KindCommitted ss.Kind = db.KindCommitted
ss.Readonly = true ss.Readonly = true
if err := putSnapshot(bkt, name, &ss); err != nil { if err := putSnapshot(bkt, name, &ss); err != nil {
@ -372,7 +298,65 @@ func (ms *boltMetastore) Commit(ctx context.Context, key, name string) (id strin
return return
} }
func getSnapshot(bkt *bolt.Bucket, key string, ss *Snapshot) error { func withBucket(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok {
return errors.Errorf("no transaction in context")
}
bkt := t.tx.Bucket(bucketKeyStorageVersion)
if bkt == nil {
return errors.Wrap(snapshot.ErrSnapshotNotExist, "bucket does not exist")
}
return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents))
}
func createBucketIfNotExists(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bolt.Bucket) error) error {
t, ok := ctx.Value(transactionKey{}).(*boltFileTransactor)
if !ok {
return errors.Errorf("no transaction in context")
}
bkt, err := t.tx.CreateBucketIfNotExists(bucketKeyStorageVersion)
if err != nil {
return errors.Wrap(err, "failed to create version bucket")
}
sbkt, err := bkt.CreateBucketIfNotExists(bucketKeySnapshot)
if err != nil {
return errors.Wrap(err, "failed to create snapshots bucket")
}
pbkt, err := bkt.CreateBucketIfNotExists(bucketKeyParents)
if err != nil {
return errors.Wrap(err, "failed to create snapshots bucket")
}
return fn(ctx, sbkt, pbkt)
}
func fromProtoKind(k db.Kind) snapshot.Kind {
if k == db.KindActive {
return snapshot.KindActive
}
return snapshot.KindCommitted
}
func parents(bkt *bolt.Bucket, parent *db.Snapshot) (parents []string, err error) {
for {
parents = append(parents, fmt.Sprintf("%d", parent.ID))
if parent.Parent == "" {
return
}
var ps db.Snapshot
if err := getSnapshot(bkt, parent.Parent, &ps); err != nil {
return nil, errors.Wrap(err, "failed to get parent snapshot")
}
parent = &ps
}
return
}
func getSnapshot(bkt *bolt.Bucket, key string, ss *db.Snapshot) error {
b := bkt.Get([]byte(key)) b := bkt.Get([]byte(key))
if len(b) == 0 { if len(b) == 0 {
return snapshot.ErrSnapshotNotExist return snapshot.ErrSnapshotNotExist
@ -383,7 +367,7 @@ func getSnapshot(bkt *bolt.Bucket, key string, ss *Snapshot) error {
return nil return nil
} }
func putSnapshot(bkt *bolt.Bucket, key string, ss *Snapshot) error { func putSnapshot(bkt *bolt.Bucket, key string, ss *db.Snapshot) error {
b, err := proto.Marshal(ss) b, err := proto.Marshal(ss)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to marshal snapshot") return errors.Wrap(err, "failed to marshal snapshot")

View file

@ -0,0 +1,21 @@
package storage
import (
"path/filepath"
"testing"
// Does not require root but flag must be defined for snapshot tests
_ "github.com/containerd/containerd/testutil"
)
func TestMetastore(t *testing.T) {
MetaStoreSuite(t, "Metastore", func(root string) (*MetaStore, error) {
return NewMetaStore(filepath.Join(root, "metadata.db"))
})
}
func BenchmarkSuite(b *testing.B) {
Benchmarks(b, "BoltDBBench", func(root string) (*MetaStore, error) {
return NewMetaStore(filepath.Join(root, "metadata.db"))
})
}

View file

@ -1,25 +0,0 @@
package boltdb
import (
"context"
"path/filepath"
"testing"
"github.com/containerd/containerd/snapshot/storage"
"github.com/containerd/containerd/snapshot/storage/testsuite"
// Does not require root but flag must be defined for snapshot tests
_ "github.com/containerd/containerd/testutil"
)
func TestBoltDB(t *testing.T) {
testsuite.MetaStoreSuite(t, "BoltDB", func(ctx context.Context, root string) (storage.MetaStore, error) {
return NewMetaStore(ctx, filepath.Join(root, "metadata.db"))
})
}
func BenchmarkSuite(b *testing.B) {
testsuite.Benchmarks(b, "BoltDBBench", func(ctx context.Context, root string) (storage.MetaStore, error) {
return NewMetaStore(ctx, filepath.Join(root, "metadata.db"))
})
}

View file

@ -3,51 +3,10 @@ package storage
import ( import (
"context" "context"
"github.com/containerd/containerd/snapshot" "github.com/boltdb/bolt"
"github.com/pkg/errors"
) )
// MetaStore is used to store metadata related to a snapshot driver. The
// MetaStore is intended to store metadata related to name, state and
// parentage. Using the MetaStore is not required to implement a snapshot
// driver but can be used to handle the persistence and transactional
// complexities of a driver implementation.
type MetaStore interface {
// TransactionContext creates a new transaction context.
TransactionContext(ctx context.Context, writable bool) (context.Context, Transactor, error)
// Stat returns the snapshot stat Info directly from
// the metadata.
Stat(ctx context.Context, key string) (snapshot.Info, error)
// Walk iterates through all metadata for the stored
// snapshots and calls the provided function for each.
Walk(ctx context.Context, fn func(context.Context, snapshot.Info) error) error
// CreateActive creates a new active snapshot transaction referenced by
// the provided key. The new active snapshot will have the provided
// parent. If the readonly option is given, the active snapshot will be
// marked as readonly and can only be removed, and not committed. The
// provided context must contain a writable transaction.
CreateActive(ctx context.Context, key, parent string, readonly bool) (Active, error)
// GetActive returns the metadata for the active snapshot transaction
// referenced by the given key.
GetActive(ctx context.Context, key string) (Active, error)
// Remove removes a snapshot from the metastore. The provided context
// must contain a writable transaction. The string identifier for the
// snapshot is returned as well as the kind.
Remove(ctx context.Context, key string) (string, snapshot.Kind, error)
// Commit renames the active snapshot transaction referenced by `key`
// as a committed snapshot referenced by `Name`. The resulting snapshot
// will be committed and readonly. The `key` reference will no longer
// be available for lookup or removal. The returned string identifier
// for the committed snapshot is the same identifier of the original
// active snapshot.
Commit(ctx context.Context, key, name string) (string, error)
}
// Transactor is used to finalize an active transaction. // Transactor is used to finalize an active transaction.
type Transactor interface { type Transactor interface {
// Commit commits any changes made during the transaction. // Commit commits any changes made during the transaction.
@ -67,3 +26,46 @@ type Active struct {
ParentIDs []string ParentIDs []string
Readonly bool Readonly bool
} }
// MetaStore is used to store metadata related to a snapshot driver. The
// MetaStore is intended to store metadata related to name, state and
// parentage. Using the MetaStore is not required to implement a snapshot
// driver but can be used to handle the persistence and transactional
// complexities of a driver implementation.
type MetaStore struct {
dbfile string
}
// NewMetaStore returns a snapshot MetaStore for storage of metadata related to
// a snapshot driver backed by a bolt file database. This implementation is
// strongly consistent and does all metadata changes in a transaction to prevent
// against process crashes causing inconsistent metadata state.
func NewMetaStore(dbfile string) (*MetaStore, error) {
return &MetaStore{
dbfile: dbfile,
}, nil
}
type transactionKey struct{}
// TransactionContext creates a new transaction context.
func (ms *MetaStore) TransactionContext(ctx context.Context, writable bool) (context.Context, Transactor, error) {
db, err := bolt.Open(ms.dbfile, 0600, nil)
if err != nil {
return ctx, nil, errors.Wrap(err, "failed to open database file")
}
tx, err := db.Begin(writable)
if err != nil {
return ctx, nil, errors.Wrap(err, "failed to start transaction")
}
t := &boltFileTransactor{
db: db,
tx: tx,
}
ctx = context.WithValue(ctx, transactionKey{}, t)
return ctx, t, nil
}

View file

@ -1,4 +1,4 @@
package testsuite package storage
import ( import (
"context" "context"
@ -6,13 +6,11 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
"github.com/containerd/containerd/snapshot/storage"
) )
// Benchmarks returns a benchmark suite using the provided metadata store // Benchmarks returns a benchmark suite using the provided metadata store
// creation method // creation method
func Benchmarks(b *testing.B, name string, metaFn func(context.Context, string) (storage.MetaStore, error)) { func Benchmarks(b *testing.B, name string, metaFn metaFactory) {
b.Run("StatActive", makeBench(b, name, metaFn, statActiveBenchmark)) b.Run("StatActive", makeBench(b, name, metaFn, statActiveBenchmark))
b.Run("StatCommitted", makeBench(b, name, metaFn, statCommittedBenchmark)) b.Run("StatCommitted", makeBench(b, name, metaFn, statCommittedBenchmark))
b.Run("CreateActive", makeBench(b, name, metaFn, createActiveBenchmark)) b.Run("CreateActive", makeBench(b, name, metaFn, createActiveBenchmark))
@ -24,7 +22,7 @@ func Benchmarks(b *testing.B, name string, metaFn func(context.Context, string)
} }
// makeBench creates a benchmark with a writable transaction // makeBench creates a benchmark with a writable transaction
func makeBench(b *testing.B, name string, metaFn func(context.Context, string) (storage.MetaStore, error), fn func(context.Context, *testing.B, storage.MetaStore)) func(b *testing.B) { func makeBench(b *testing.B, name string, metaFn metaFactory, fn func(context.Context, *testing.B, *MetaStore)) func(b *testing.B) {
return func(b *testing.B) { return func(b *testing.B) {
ctx := context.Background() ctx := context.Background()
tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-") tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-")
@ -33,7 +31,7 @@ func makeBench(b *testing.B, name string, metaFn func(context.Context, string) (
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
ms, err := metaFn(ctx, tmpDir) ms, err := metaFn(tmpDir)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -49,7 +47,7 @@ func makeBench(b *testing.B, name string, metaFn func(context.Context, string) (
} }
} }
func openCloseWritable(b *testing.B, name string, metaFn func(context.Context, string) (storage.MetaStore, error)) func(b *testing.B) { func openCloseWritable(b *testing.B, name string, metaFn metaFactory) func(b *testing.B) {
return func(b *testing.B) { return func(b *testing.B) {
ctx := context.Background() ctx := context.Background()
tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-") tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-")
@ -58,7 +56,7 @@ func openCloseWritable(b *testing.B, name string, metaFn func(context.Context, s
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
ms, err := metaFn(ctx, tmpDir) ms, err := metaFn(tmpDir)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -77,7 +75,7 @@ func openCloseWritable(b *testing.B, name string, metaFn func(context.Context, s
} }
} }
func openCloseReadonly(b *testing.B, name string, metaFn func(context.Context, string) (storage.MetaStore, error)) func(b *testing.B) { func openCloseReadonly(b *testing.B, name string, metaFn metaFactory) func(b *testing.B) {
return func(b *testing.B) { return func(b *testing.B) {
ctx := context.Background() ctx := context.Background()
tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-") tmpDir, err := ioutil.TempDir("", "metastore-bench-"+name+"-")
@ -86,7 +84,7 @@ func openCloseReadonly(b *testing.B, name string, metaFn func(context.Context, s
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
ms, err := metaFn(ctx, tmpDir) ms, err := metaFn(tmpDir)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -105,112 +103,112 @@ func openCloseReadonly(b *testing.B, name string, metaFn func(context.Context, s
} }
} }
func createActiveFromBase(ctx context.Context, ms storage.MetaStore, active, base string) error { func createActiveFromBase(ctx context.Context, ms *MetaStore, active, base string) error {
if _, err := ms.CreateActive(ctx, "bottom", "", false); err != nil { if _, err := CreateActive(ctx, "bottom", "", false); err != nil {
return err return err
} }
if _, err := ms.Commit(ctx, "bottom", base); err != nil { if _, err := CommitActive(ctx, "bottom", base); err != nil {
return err return err
} }
_, err := ms.CreateActive(ctx, active, base, false) _, err := CreateActive(ctx, active, base, false)
return err return err
} }
func statActiveBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func statActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
if err := createActiveFromBase(ctx, ms, "active", "base"); err != nil { if err := createActiveFromBase(ctx, ms, "active", "base"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := ms.Stat(ctx, "active") _, err := GetInfo(ctx, "active")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
} }
func statCommittedBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func statCommittedBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
if err := createActiveFromBase(ctx, ms, "active", "base"); err != nil { if err := createActiveFromBase(ctx, ms, "active", "base"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
if _, err := ms.Commit(ctx, "active", "committed"); err != nil { if _, err := CommitActive(ctx, "active", "committed"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, err := ms.Stat(ctx, "committed") _, err := GetInfo(ctx, "committed")
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
} }
func createActiveBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func createActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := ms.CreateActive(ctx, "active", "", false); err != nil { if _, err := CreateActive(ctx, "active", "", false); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StopTimer() b.StopTimer()
if _, _, err := ms.Remove(ctx, "active"); err != nil { if _, _, err := Remove(ctx, "active"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StartTimer() b.StartTimer()
} }
} }
func removeBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func removeBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
b.StopTimer() b.StopTimer()
if _, err := ms.CreateActive(ctx, "active", "", false); err != nil { if _, err := CreateActive(ctx, "active", "", false); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StartTimer() b.StartTimer()
if _, _, err := ms.Remove(ctx, "active"); err != nil { if _, _, err := Remove(ctx, "active"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
} }
func commitBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func commitBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
b.StopTimer() b.StopTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := ms.CreateActive(ctx, "active", "", false); err != nil { if _, err := CreateActive(ctx, "active", "", false); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StartTimer() b.StartTimer()
if _, err := ms.Commit(ctx, "active", "committed"); err != nil { if _, err := CommitActive(ctx, "active", "committed"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StopTimer() b.StopTimer()
if _, _, err := ms.Remove(ctx, "committed"); err != nil { if _, _, err := Remove(ctx, "committed"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
} }
func getActiveBenchmark(ctx context.Context, b *testing.B, ms storage.MetaStore) { func getActiveBenchmark(ctx context.Context, b *testing.B, ms *MetaStore) {
var base string var base string
for i := 1; i <= 10; i++ { for i := 1; i <= 10; i++ {
if _, err := ms.CreateActive(ctx, "tmp", base, false); err != nil { if _, err := CreateActive(ctx, "tmp", base, false); err != nil {
b.Fatalf("create active failed: %+v", err) b.Fatalf("create active failed: %+v", err)
} }
base = fmt.Sprintf("base-%d", i) base = fmt.Sprintf("base-%d", i)
if _, err := ms.Commit(ctx, "tmp", base); err != nil { if _, err := CommitActive(ctx, "tmp", base); err != nil {
b.Fatalf("commit failed: %+v", err) b.Fatalf("commit failed: %+v", err)
} }
} }
if _, err := ms.CreateActive(ctx, "active", base, false); err != nil { if _, err := CreateActive(ctx, "active", base, false); err != nil {
b.Fatalf("create active failed: %+v", err) b.Fatalf("create active failed: %+v", err)
} }
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := ms.GetActive(ctx, "active"); err != nil { if _, err := GetActive(ctx, "active"); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }

View file

@ -1,4 +1,4 @@
package testsuite package storage
import ( import (
"context" "context"
@ -7,22 +7,21 @@ import (
"testing" "testing"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/snapshot/storage"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
type testFunc func(context.Context, *testing.T, storage.MetaStore) type testFunc func(context.Context, *testing.T, *MetaStore)
type metaFactory func(context.Context, string) (storage.MetaStore, error) type metaFactory func(string) (*MetaStore, error)
type populateFunc func(context.Context, storage.MetaStore) error type populateFunc func(context.Context, *MetaStore) error
// MetaStoreSuite runs a test suite on the metastore given a factory function. // MetaStoreSuite runs a test suite on the metastore given a factory function.
func MetaStoreSuite(t *testing.T, name string, meta func(ctx context.Context, root string) (storage.MetaStore, error)) { func MetaStoreSuite(t *testing.T, name string, meta func(root string) (*MetaStore, error)) {
t.Run("Stat", makeTest(t, name, meta, inReadTransaction(testStat, basePopulate))) t.Run("GetInfo", makeTest(t, name, meta, inReadTransaction(testGetInfo, basePopulate)))
t.Run("StatNotExist", makeTest(t, name, meta, inReadTransaction(testStatNotExist, basePopulate))) t.Run("GetInfoNotExist", makeTest(t, name, meta, inReadTransaction(testGetInfoNotExist, basePopulate)))
t.Run("StatEmptyDB", makeTest(t, name, meta, inReadTransaction(testStatNotExist, nil))) t.Run("GetInfoEmptyDB", makeTest(t, name, meta, inReadTransaction(testGetInfoNotExist, nil)))
t.Run("Walk", makeTest(t, name, meta, inReadTransaction(testWalk, basePopulate))) t.Run("Walk", makeTest(t, name, meta, inReadTransaction(testWalk, basePopulate)))
t.Run("GetActive", makeTest(t, name, meta, testGetActive)) t.Run("GetActive", makeTest(t, name, meta, testGetActive))
t.Run("GetActiveNotExist", makeTest(t, name, meta, inReadTransaction(testGetActiveNotExist, basePopulate))) t.Run("GetActiveNotExist", makeTest(t, name, meta, inReadTransaction(testGetActiveNotExist, basePopulate)))
@ -52,7 +51,7 @@ func makeTest(t *testing.T, name string, metaFn metaFactory, fn testFunc) func(t
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
ms, err := metaFn(ctx, tmpDir) ms, err := metaFn(tmpDir)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -62,7 +61,7 @@ func makeTest(t *testing.T, name string, metaFn metaFactory, fn testFunc) func(t
} }
func inReadTransaction(fn testFunc, pf populateFunc) testFunc { func inReadTransaction(fn testFunc, pf populateFunc) testFunc {
return func(ctx context.Context, t *testing.T, ms storage.MetaStore) { return func(ctx context.Context, t *testing.T, ms *MetaStore) {
if pf != nil { if pf != nil {
ctx, tx, err := ms.TransactionContext(ctx, true) ctx, tx, err := ms.TransactionContext(ctx, true)
if err != nil { if err != nil {
@ -97,7 +96,7 @@ func inReadTransaction(fn testFunc, pf populateFunc) testFunc {
} }
func inWriteTransaction(fn testFunc) testFunc { func inWriteTransaction(fn testFunc) testFunc {
return func(ctx context.Context, t *testing.T, ms storage.MetaStore) { return func(ctx context.Context, t *testing.T, ms *MetaStore) {
ctx, tx, err := ms.TransactionContext(ctx, true) ctx, tx, err := ms.TransactionContext(ctx, true)
if err != nil { if err != nil {
t.Fatal("Failed to start transaction: %+v", err) t.Fatal("Failed to start transaction: %+v", err)
@ -125,32 +124,32 @@ func inWriteTransaction(fn testFunc) testFunc {
// - "active-3": active with parent "committed-2" // - "active-3": active with parent "committed-2"
// - "active-4": readonly active without parent" // - "active-4": readonly active without parent"
// - "active-5": readonly active with parent "committed-2" // - "active-5": readonly active with parent "committed-2"
func basePopulate(ctx context.Context, ms storage.MetaStore) error { func basePopulate(ctx context.Context, ms *MetaStore) error {
if _, err := ms.CreateActive(ctx, "committed-tmp-1", "", false); err != nil { if _, err := CreateActive(ctx, "committed-tmp-1", "", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.Commit(ctx, "committed-tmp-1", "committed-1"); err != nil { if _, err := CommitActive(ctx, "committed-tmp-1", "committed-1"); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "committed-tmp-2", "committed-1", false); err != nil { if _, err := CreateActive(ctx, "committed-tmp-2", "committed-1", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.Commit(ctx, "committed-tmp-2", "committed-2"); err != nil { if _, err := CommitActive(ctx, "committed-tmp-2", "committed-2"); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "active-1", "", false); err != nil { if _, err := CreateActive(ctx, "active-1", "", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "active-2", "committed-1", false); err != nil { if _, err := CreateActive(ctx, "active-2", "committed-1", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "active-3", "committed-2", false); err != nil { if _, err := CreateActive(ctx, "active-3", "committed-2", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "active-4", "", true); err != nil { if _, err := CreateActive(ctx, "active-4", "", true); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.CreateActive(ctx, "active-5", "committed-2", true); err != nil { if _, err := CreateActive(ctx, "active-5", "committed-2", true); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
return nil return nil
@ -237,24 +236,24 @@ func assertExist(t *testing.T, err error) {
} }
} }
func testStat(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testGetInfo(ctx context.Context, t *testing.T, ms *MetaStore) {
for key, expected := range baseInfo { for key, expected := range baseInfo {
info, err := ms.Stat(ctx, key) info, err := GetInfo(ctx, key)
if err != nil { if err != nil {
t.Fatalf("Stat on %v failed: %+v", key, err) t.Fatalf("GetInfo on %v failed: %+v", key, err)
} }
assert.Equal(t, expected, info) assert.Equal(t, expected, info)
} }
} }
func testStatNotExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testGetInfoNotExist(ctx context.Context, t *testing.T, ms *MetaStore) {
_, err := ms.Stat(ctx, "active-not-exist") _, err := GetInfo(ctx, "active-not-exist")
assertNotExist(t, err) assertNotExist(t, err)
} }
func testWalk(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testWalk(ctx context.Context, t *testing.T, ms *MetaStore) {
found := map[string]snapshot.Info{} found := map[string]snapshot.Info{}
err := ms.Walk(ctx, func(ctx context.Context, info snapshot.Info) error { err := WalkInfo(ctx, func(ctx context.Context, info snapshot.Info) error {
if _, ok := found[info.Name]; ok { if _, ok := found[info.Name]; ok {
return errors.Errorf("entry already encountered") return errors.Errorf("entry already encountered")
} }
@ -267,13 +266,13 @@ func testWalk(ctx context.Context, t *testing.T, ms storage.MetaStore) {
assert.Equal(t, baseInfo, found) assert.Equal(t, baseInfo, found)
} }
func testGetActive(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testGetActive(ctx context.Context, t *testing.T, ms *MetaStore) {
activeMap := map[string]storage.Active{} activeMap := map[string]Active{}
populate := func(ctx context.Context, ms storage.MetaStore) error { populate := func(ctx context.Context, ms *MetaStore) error {
if _, err := ms.CreateActive(ctx, "committed-tmp-1", "", false); err != nil { if _, err := CreateActive(ctx, "committed-tmp-1", "", false); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
if _, err := ms.Commit(ctx, "committed-tmp-1", "committed-1"); err != nil { if _, err := CommitActive(ctx, "committed-tmp-1", "committed-1"); err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
@ -299,7 +298,7 @@ func testGetActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
Readonly: true, Readonly: true,
}, },
} { } {
active, err := ms.CreateActive(ctx, opts.Name, opts.Parent, opts.Readonly) active, err := CreateActive(ctx, opts.Name, opts.Parent, opts.Readonly)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create active") return errors.Wrap(err, "failed to create active")
} }
@ -308,9 +307,9 @@ func testGetActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
return nil return nil
} }
test := func(ctx context.Context, t *testing.T, ms storage.MetaStore) { test := func(ctx context.Context, t *testing.T, ms *MetaStore) {
for key, expected := range activeMap { for key, expected := range activeMap {
active, err := ms.GetActive(ctx, key) active, err := GetActive(ctx, key)
if err != nil { if err != nil {
t.Fatal("Failed to get active: %+v", err) t.Fatal("Failed to get active: %+v", err)
} }
@ -321,18 +320,18 @@ func testGetActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
inReadTransaction(test, populate)(ctx, t, ms) inReadTransaction(test, populate)(ctx, t, ms)
} }
func testGetActiveCommitted(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testGetActiveCommitted(ctx context.Context, t *testing.T, ms *MetaStore) {
_, err := ms.GetActive(ctx, "committed-1") _, err := GetActive(ctx, "committed-1")
assertNotActive(t, err) assertNotActive(t, err)
} }
func testGetActiveNotExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testGetActiveNotExist(ctx context.Context, t *testing.T, ms *MetaStore) {
_, err := ms.GetActive(ctx, "active-not-exist") _, err := GetActive(ctx, "active-not-exist")
assertNotExist(t, err) assertNotExist(t, err)
} }
func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCreateActive(ctx context.Context, t *testing.T, ms *MetaStore) {
a1, err := ms.CreateActive(ctx, "active-1", "", false) a1, err := CreateActive(ctx, "active-1", "", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -340,7 +339,7 @@ func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected writable active") t.Fatal("Expected writable active")
} }
a2, err := ms.CreateActive(ctx, "active-2", "", true) a2, err := CreateActive(ctx, "active-2", "", true)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -351,7 +350,7 @@ func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected readonly active") t.Fatal("Expected readonly active")
} }
commitID, err := ms.Commit(ctx, "active-1", "committed-1") commitID, err := CommitActive(ctx, "active-1", "committed-1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -359,7 +358,7 @@ func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Snapshot identifier must not change on commit") t.Fatal("Snapshot identifier must not change on commit")
} }
a3, err := ms.CreateActive(ctx, "active-3", "committed-1", false) a3, err := CreateActive(ctx, "active-3", "committed-1", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -376,7 +375,7 @@ func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected writable active") t.Fatal("Expected writable active")
} }
a4, err := ms.CreateActive(ctx, "active-4", "committed-1", true) a4, err := CreateActive(ctx, "active-4", "committed-1", true)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -394,31 +393,31 @@ func testCreateActive(ctx context.Context, t *testing.T, ms storage.MetaStore) {
} }
} }
func testCreateActiveExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCreateActiveExist(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, err := ms.CreateActive(ctx, "active-1", "", false) _, err := CreateActive(ctx, "active-1", "", false)
assertExist(t, err) assertExist(t, err)
_, err = ms.CreateActive(ctx, "committed-1", "", false) _, err = CreateActive(ctx, "committed-1", "", false)
assertExist(t, err) assertExist(t, err)
} }
func testCreateActiveNotExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCreateActiveNotExist(ctx context.Context, t *testing.T, ms *MetaStore) {
_, err := ms.CreateActive(ctx, "active-1", "does-not-exist", false) _, err := CreateActive(ctx, "active-1", "does-not-exist", false)
assertNotExist(t, err) assertNotExist(t, err)
} }
func testCreateActiveFromActive(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCreateActiveFromActive(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, err := ms.CreateActive(ctx, "active-new", "active-1", false) _, err := CreateActive(ctx, "active-new", "active-1", false)
assertNotCommitted(t, err) assertNotCommitted(t, err)
} }
func testCommit(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCommit(ctx context.Context, t *testing.T, ms *MetaStore) {
a1, err := ms.CreateActive(ctx, "active-1", "", false) a1, err := CreateActive(ctx, "active-1", "", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -426,7 +425,7 @@ func testCommit(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected writable active") t.Fatal("Expected writable active")
} }
commitID, err := ms.Commit(ctx, "active-1", "committed-1") commitID, err := CommitActive(ctx, "active-1", "committed-1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -434,50 +433,50 @@ func testCommit(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Snapshot identifier must not change on commit") t.Fatal("Snapshot identifier must not change on commit")
} }
_, err = ms.GetActive(ctx, "active-1") _, err = GetActive(ctx, "active-1")
assertNotExist(t, err) assertNotExist(t, err)
_, err = ms.GetActive(ctx, "committed-1") _, err = GetActive(ctx, "committed-1")
assertNotActive(t, err) assertNotActive(t, err)
} }
func testCommitNotExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCommitNotExist(ctx context.Context, t *testing.T, ms *MetaStore) {
_, err := ms.Commit(ctx, "active-not-exist", "committed-1") _, err := CommitActive(ctx, "active-not-exist", "committed-1")
assertNotExist(t, err) assertNotExist(t, err)
} }
func testCommitExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCommitExist(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, err := ms.Commit(ctx, "active-1", "committed-1") _, err := CommitActive(ctx, "active-1", "committed-1")
assertExist(t, err) assertExist(t, err)
} }
func testCommitCommitted(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCommitCommitted(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, err := ms.Commit(ctx, "committed-1", "committed-3") _, err := CommitActive(ctx, "committed-1", "committed-3")
assertNotActive(t, err) assertNotActive(t, err)
} }
func testCommitReadonly(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testCommitReadonly(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, err := ms.Commit(ctx, "active-5", "committed-3") _, err := CommitActive(ctx, "active-5", "committed-3")
if err == nil { if err == nil {
t.Fatal("Expected error committing readonly active") t.Fatal("Expected error committing readonly active")
} }
} }
func testRemove(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testRemove(ctx context.Context, t *testing.T, ms *MetaStore) {
a1, err := ms.CreateActive(ctx, "active-1", "", false) a1, err := CreateActive(ctx, "active-1", "", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
commitID, err := ms.Commit(ctx, "active-1", "committed-1") commitID, err := CommitActive(ctx, "active-1", "committed-1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -485,20 +484,20 @@ func testRemove(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Snapshot identifier must not change on commit") t.Fatal("Snapshot identifier must not change on commit")
} }
a2, err := ms.CreateActive(ctx, "active-2", "committed-1", true) a2, err := CreateActive(ctx, "active-2", "committed-1", true)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
a3, err := ms.CreateActive(ctx, "active-3", "committed-1", true) a3, err := CreateActive(ctx, "active-3", "committed-1", true)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, _, err = ms.Remove(ctx, "active-1") _, _, err = Remove(ctx, "active-1")
assertNotExist(t, err) assertNotExist(t, err)
r3, k3, err := ms.Remove(ctx, "active-3") r3, k3, err := Remove(ctx, "active-3")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -509,7 +508,7 @@ func testRemove(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected active kind, got %v", k3) t.Fatal("Expected active kind, got %v", k3)
} }
r2, k2, err := ms.Remove(ctx, "active-2") r2, k2, err := Remove(ctx, "active-2")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -520,7 +519,7 @@ func testRemove(ctx context.Context, t *testing.T, ms storage.MetaStore) {
t.Fatal("Expected active kind, got %v", k2) t.Fatal("Expected active kind, got %v", k2)
} }
r1, k1, err := ms.Remove(ctx, "committed-1") r1, k1, err := Remove(ctx, "committed-1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -532,21 +531,21 @@ func testRemove(ctx context.Context, t *testing.T, ms storage.MetaStore) {
} }
} }
func testRemoveWithChildren(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testRemoveWithChildren(ctx context.Context, t *testing.T, ms *MetaStore) {
if err := basePopulate(ctx, ms); err != nil { if err := basePopulate(ctx, ms); err != nil {
t.Fatalf("Populate failed: %+v", err) t.Fatalf("Populate failed: %+v", err)
} }
_, _, err := ms.Remove(ctx, "committed-1") _, _, err := Remove(ctx, "committed-1")
if err == nil { if err == nil {
t.Fatalf("Expected removal of snapshot with children to error") t.Fatalf("Expected removal of snapshot with children to error")
} }
_, _, err = ms.Remove(ctx, "committed-1") _, _, err = Remove(ctx, "committed-1")
if err == nil { if err == nil {
t.Fatalf("Expected removal of snapshot with children to error") t.Fatalf("Expected removal of snapshot with children to error")
} }
} }
func testRemoveNotExist(ctx context.Context, t *testing.T, ms storage.MetaStore) { func testRemoveNotExist(ctx context.Context, t *testing.T, ms *MetaStore) {
_, _, err := ms.Remove(ctx, "does-not-exist") _, _, err := Remove(ctx, "does-not-exist")
assertNotExist(t, err) assertNotExist(t, err)
} }

View file

@ -1,19 +1,19 @@
// Code generated by protoc-gen-gogo. // Code generated by protoc-gen-gogo.
// source: github.com/containerd/containerd/snapshot/storage/boltdb/record.proto // source: github.com/containerd/containerd/snapshot/storage/proto/record.proto
// DO NOT EDIT! // DO NOT EDIT!
/* /*
Package boltdb is a generated protocol buffer package. Package proto is a generated protocol buffer package.
It is generated from these files: It is generated from these files:
github.com/containerd/containerd/snapshot/storage/boltdb/record.proto github.com/containerd/containerd/snapshot/storage/proto/record.proto
It has these top-level messages: It has these top-level messages:
Snapshot Snapshot
*/ */
package boltdb package proto
import proto "github.com/gogo/protobuf/proto" import proto1 "github.com/gogo/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import _ "github.com/gogo/protobuf/gogoproto" import _ "github.com/gogo/protobuf/gogoproto"
@ -24,7 +24,7 @@ import reflect "reflect"
import io "io" import io "io"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto1.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
@ -32,7 +32,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the // A compilation error at this line likely means your copy of the
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package const _ = proto1.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// Kind defines the kind of snapshot. // Kind defines the kind of snapshot.
type Kind int32 type Kind int32
@ -54,10 +54,12 @@ var Kind_value = map[string]int32{
} }
func (x Kind) String() string { func (x Kind) String() string {
return proto.EnumName(Kind_name, int32(x)) return proto1.EnumName(Kind_name, int32(x))
} }
func (Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptorRecord, []int{0} } func (Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptorRecord, []int{0} }
// Snapshot defines the storage type for a snapshot in the
// metadata store.
type Snapshot struct { type Snapshot struct {
ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"` Parent string `protobuf:"bytes,2,opt,name=parent,proto3" json:"parent,omitempty"`
@ -70,8 +72,8 @@ func (*Snapshot) ProtoMessage() {}
func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorRecord, []int{0} } func (*Snapshot) Descriptor() ([]byte, []int) { return fileDescriptorRecord, []int{0} }
func init() { func init() {
proto.RegisterType((*Snapshot)(nil), "containerd.v1.Snapshot") proto1.RegisterType((*Snapshot)(nil), "containerd.v1.Snapshot")
proto.RegisterEnum("containerd.v1.Kind", Kind_name, Kind_value) proto1.RegisterEnum("containerd.v1.Kind", Kind_name, Kind_value)
} }
func (m *Snapshot) Marshal() (dAtA []byte, err error) { func (m *Snapshot) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
@ -440,29 +442,28 @@ var (
) )
func init() { func init() {
proto.RegisterFile("github.com/containerd/containerd/snapshot/storage/boltdb/record.proto", fileDescriptorRecord) proto1.RegisterFile("github.com/containerd/containerd/snapshot/storage/proto/record.proto", fileDescriptorRecord)
} }
var fileDescriptorRecord = []byte{ var fileDescriptorRecord = []byte{
// 309 bytes of a gzipped FileDescriptorProto // 304 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x4d, 0xcf, 0x2c, 0xc9, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x72, 0x49, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
0x4a, 0x41, 0x66, 0x16, 0xe7, 0x25, 0x16, 0x14, 0x67, 0xe4, 0x97, 0xe8, 0x17, 0x97, 0xe4, 0x17, 0x4a, 0x41, 0x66, 0x16, 0xe7, 0x25, 0x16, 0x14, 0x67, 0xe4, 0x97, 0xe8, 0x17, 0x97, 0xe4, 0x17,
0x25, 0xa6, 0xa7, 0xea, 0x27, 0xe5, 0xe7, 0x94, 0xa4, 0x24, 0xe9, 0x17, 0xa5, 0x26, 0xe7, 0x17, 0x25, 0xa6, 0xa7, 0xea, 0x17, 0x14, 0xe5, 0x97, 0xe4, 0xeb, 0x17, 0xa5, 0x26, 0xe7, 0x17, 0xa5,
0xa5, 0xe8, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0xf1, 0x22, 0x34, 0xe8, 0x95, 0x19, 0x4a, 0x89, 0xe8, 0x81, 0x39, 0x42, 0xbc, 0x08, 0xf5, 0x7a, 0x65, 0x86, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9,
0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x65, 0xf4, 0x41, 0x2c, 0x88, 0x22, 0xa5, 0x7a, 0x2e, 0x8e, 0x60, 0x10, 0x65, 0x20, 0x16, 0x44, 0x91, 0x52, 0x3d, 0x17, 0x47, 0x30, 0xd4, 0x2c, 0x21, 0x31, 0x2e,
0xa8, 0x61, 0x42, 0x62, 0x5c, 0x4c, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x2c, 0x4e, 0x6c, 0xa6, 0xcc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x16, 0x27, 0xb6, 0x47, 0xf7, 0xe4, 0x99, 0x3c,
0x8f, 0xee, 0xc9, 0x33, 0x79, 0xba, 0x04, 0x31, 0x65, 0xa6, 0x08, 0x89, 0x71, 0xb1, 0x15, 0x24, 0x5d, 0x82, 0x98, 0x32, 0x53, 0x84, 0xc4, 0xb8, 0xd8, 0x0a, 0x12, 0x8b, 0x52, 0xf3, 0x4a, 0x24,
0x16, 0xa5, 0xe6, 0x95, 0x48, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x79, 0x42, 0xea, 0x5c, 0x98, 0x14, 0x18, 0x35, 0x38, 0x83, 0xa0, 0x3c, 0x21, 0x75, 0x2e, 0x96, 0xec, 0xcc, 0xbc, 0x14,
0x2c, 0xd9, 0x99, 0x79, 0x29, 0x12, 0x2c, 0x0a, 0x8c, 0x1a, 0x7c, 0x46, 0xc2, 0x7a, 0x28, 0xf6, 0x09, 0x16, 0x05, 0x46, 0x0d, 0x3e, 0x23, 0x61, 0x3d, 0x14, 0xfb, 0xf4, 0xbc, 0x33, 0xf3, 0x52,
0xe9, 0x79, 0x67, 0xe6, 0xa5, 0x04, 0x81, 0x15, 0x08, 0x49, 0x71, 0x71, 0x14, 0xa5, 0x26, 0xa6, 0x82, 0xc0, 0x0a, 0x84, 0xa4, 0xb8, 0x38, 0x8a, 0x52, 0x13, 0x53, 0xf2, 0xf3, 0x72, 0x2a, 0x25,
0xe4, 0xe7, 0xe5, 0x54, 0x4a, 0xb0, 0x2a, 0x30, 0x6a, 0x70, 0x04, 0xc1, 0xf9, 0x5a, 0x41, 0x5c, 0x58, 0x15, 0x18, 0x35, 0x38, 0x82, 0xe0, 0x7c, 0xad, 0x20, 0x2e, 0x16, 0x6f, 0x88, 0x1a, 0x36,
0x2c, 0xde, 0x10, 0x35, 0x6c, 0x8e, 0xce, 0x21, 0x9e, 0x61, 0xae, 0x02, 0x0c, 0x52, 0x7c, 0x5d, 0x47, 0xe7, 0x10, 0xcf, 0x30, 0x57, 0x01, 0x06, 0x29, 0xbe, 0xae, 0xb9, 0x0a, 0x5c, 0x20, 0x51,
0x73, 0x15, 0xb8, 0x40, 0xa2, 0x8e, 0xc9, 0x25, 0x99, 0x65, 0xa9, 0x42, 0x0a, 0x5c, 0x9c, 0xce, 0xc7, 0xe4, 0x92, 0xcc, 0xb2, 0x54, 0x21, 0x05, 0x2e, 0x4e, 0x67, 0x7f, 0x5f, 0x5f, 0xcf, 0x90,
0xfe, 0xbe, 0xbe, 0x9e, 0x21, 0x21, 0xae, 0x2e, 0x02, 0x8c, 0x52, 0x82, 0x5d, 0x73, 0x15, 0x78, 0x10, 0x57, 0x17, 0x01, 0x46, 0x29, 0xc1, 0xae, 0xb9, 0x0a, 0xbc, 0x20, 0x69, 0xe7, 0xfc, 0xdc,
0x41, 0xd2, 0xce, 0xf9, 0xb9, 0xb9, 0x99, 0x25, 0x25, 0xa9, 0x29, 0x52, 0x3c, 0x1d, 0x8b, 0xe5, 0xdc, 0xcc, 0x92, 0x92, 0xd4, 0x14, 0x29, 0x9e, 0x8e, 0xc5, 0x72, 0x0c, 0xbb, 0x96, 0xc8, 0x81,
0x18, 0x76, 0x2d, 0x91, 0x03, 0x9b, 0xe5, 0x24, 0x71, 0xe2, 0xa1, 0x1c, 0xc3, 0x8d, 0x87, 0x72, 0xcd, 0x72, 0x92, 0x38, 0xf1, 0x50, 0x8e, 0xe1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c,
0x0c, 0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x12, 0x1b, 0xd8,
0x39, 0xc6, 0x24, 0x36, 0xb0, 0xaf, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x73, 0x89, 0x2b, 0xd7, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x89, 0x2c, 0x37, 0x62, 0x01, 0x00, 0x00,
0x02, 0x63, 0x01, 0x00, 0x00,
} }

View file

@ -16,6 +16,8 @@ enum Kind {
COMMITTED = 1 [(gogoproto.enumvalue_customname) = "KindCommitted"]; COMMITTED = 1 [(gogoproto.enumvalue_customname) = "KindCommitted"];
} }
// Snapshot defines the storage type for a snapshot in the
// metadata store.
message Snapshot { message Snapshot {
uint64 id = 1 [(gogoproto.customname) = "ID"]; uint64 id = 1 [(gogoproto.customname) = "ID"];
string parent = 2; string parent = 2;