1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

container: remove ViewDB and View interfaces, use concrete types

These interfaces were added in aacddda89d, with
no clear motivation, other than "Also hide ViewDB behind an interface".

This patch removes the interface in favor of using a concrete implementation;
There's currently only one implementation of this interface, and if we would
decide to change to an alternative implementation, we could define relevant
interfaces on the receiver side.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-09-21 12:20:13 +02:00
parent f53692a632
commit 511a909ae6
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
5 changed files with 30 additions and 47 deletions

View file

@ -193,7 +193,7 @@ func (container *Container) toDisk() (*Container, error) {
// CheckpointTo makes the Container's current state visible to queries, and persists state. // CheckpointTo makes the Container's current state visible to queries, and persists state.
// Callers must hold a Container lock. // Callers must hold a Container lock.
func (container *Container) CheckpointTo(store ViewDB) error { func (container *Container) CheckpointTo(store *ViewDB) error {
deepCopy, err := container.toDisk() deepCopy, err := container.toDisk()
if err != nil { if err != nil {
return err return err

View file

@ -77,27 +77,6 @@ type nameAssociation struct {
containerID string containerID string
} }
// ViewDB provides an in-memory transactional (ACID) container Store
type ViewDB interface {
Snapshot() View
Save(*Container) error
Delete(*Container) error
GetByPrefix(string) (string, error)
ReserveName(name, containerID string) error
ReleaseName(name string) error
}
// View can be used by readers to avoid locking
type View interface {
All() ([]Snapshot, error)
Get(id string) (*Snapshot, error)
GetID(name string) (string, error)
GetAllNames() map[string][]string
}
var schema = &memdb.DBSchema{ var schema = &memdb.DBSchema{
Tables: map[string]*memdb.TableSchema{ Tables: map[string]*memdb.TableSchema{
memdbContainersTable: { memdbContainersTable: {
@ -128,7 +107,8 @@ var schema = &memdb.DBSchema{
}, },
} }
type memDB struct { // ViewDB provides an in-memory transactional (ACID) container store.
type ViewDB struct {
store *memdb.MemDB store *memdb.MemDB
} }
@ -144,15 +124,17 @@ func (e NoSuchContainerError) Error() string {
} }
// NewViewDB provides the default implementation, with the default schema // NewViewDB provides the default implementation, with the default schema
func NewViewDB() (ViewDB, error) { func NewViewDB() (*ViewDB, error) {
store, err := memdb.NewMemDB(schema) store, err := memdb.NewMemDB(schema)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &memDB{store: store}, nil return &ViewDB{store: store}, nil
} }
func (db *memDB) GetByPrefix(s string) (string, error) { // GetByPrefix returns a container with the given ID prefix. It returns an
// error if an empty prefix was given or if multiple containers match the prefix.
func (db *ViewDB) GetByPrefix(s string) (string, error) {
if s == "" { if s == "" {
return "", ErrEmptyPrefix return "", ErrEmptyPrefix
} }
@ -184,14 +166,14 @@ func (db *memDB) GetByPrefix(s string) (string, error) {
return "", ErrNotExist return "", ErrNotExist
} }
// Snapshot provides a consistent read-only View of the database // Snapshot provides a consistent read-only view of the database.
func (db *memDB) Snapshot() View { func (db *ViewDB) Snapshot() *View {
return &memdbView{ return &View{
txn: db.store.Txn(false), txn: db.store.Txn(false),
} }
} }
func (db *memDB) withTxn(cb func(*memdb.Txn) error) error { func (db *ViewDB) withTxn(cb func(*memdb.Txn) error) error {
txn := db.store.Txn(true) txn := db.store.Txn(true)
err := cb(txn) err := cb(txn)
if err != nil { if err != nil {
@ -204,16 +186,16 @@ func (db *memDB) withTxn(cb func(*memdb.Txn) error) error {
// Save atomically updates the in-memory store state for a Container. // Save atomically updates the in-memory store state for a Container.
// Only read only (deep) copies of containers may be passed in. // Only read only (deep) copies of containers may be passed in.
func (db *memDB) Save(c *Container) error { func (db *ViewDB) Save(c *Container) error {
return db.withTxn(func(txn *memdb.Txn) error { return db.withTxn(func(txn *memdb.Txn) error {
return txn.Insert(memdbContainersTable, c) return txn.Insert(memdbContainersTable, c)
}) })
} }
// Delete removes an item by ID // Delete removes an item by ID
func (db *memDB) Delete(c *Container) error { func (db *ViewDB) Delete(c *Container) error {
return db.withTxn(func(txn *memdb.Txn) error { return db.withTxn(func(txn *memdb.Txn) error {
view := &memdbView{txn: txn} view := &View{txn: txn}
names := view.getNames(c.ID) names := view.getNames(c.ID)
for _, name := range names { for _, name := range names {
@ -231,7 +213,7 @@ func (db *memDB) Delete(c *Container) error {
// ReserveName is idempotent // ReserveName is idempotent
// Attempting to reserve a container ID to a name that already exists results in an `ErrNameReserved` // Attempting to reserve a container ID to a name that already exists results in an `ErrNameReserved`
// A name reservation is globally unique // A name reservation is globally unique
func (db *memDB) ReserveName(name, containerID string) error { func (db *ViewDB) ReserveName(name, containerID string) error {
return db.withTxn(func(txn *memdb.Txn) error { return db.withTxn(func(txn *memdb.Txn) error {
s, err := txn.First(memdbNamesTable, memdbIDIndex, name) s, err := txn.First(memdbNamesTable, memdbIDIndex, name)
if err != nil { if err != nil {
@ -249,18 +231,19 @@ func (db *memDB) ReserveName(name, containerID string) error {
// ReleaseName releases the reserved name // ReleaseName releases the reserved name
// Once released, a name can be reserved again // Once released, a name can be reserved again
func (db *memDB) ReleaseName(name string) error { func (db *ViewDB) ReleaseName(name string) error {
return db.withTxn(func(txn *memdb.Txn) error { return db.withTxn(func(txn *memdb.Txn) error {
return txn.Delete(memdbNamesTable, nameAssociation{name: name}) return txn.Delete(memdbNamesTable, nameAssociation{name: name})
}) })
} }
type memdbView struct { // View provides a consistent read-only view of the database.
type View struct {
txn *memdb.Txn txn *memdb.Txn
} }
// All returns a all items in this snapshot. Returned objects must never be modified. // All returns a all items in this snapshot. Returned objects must never be modified.
func (v *memdbView) All() ([]Snapshot, error) { func (v *View) All() ([]Snapshot, error) {
var all []Snapshot var all []Snapshot
iter, err := v.txn.Get(memdbContainersTable, memdbIDIndex) iter, err := v.txn.Get(memdbContainersTable, memdbIDIndex)
if err != nil { if err != nil {
@ -278,7 +261,7 @@ func (v *memdbView) All() ([]Snapshot, error) {
} }
// Get returns an item by id. Returned objects must never be modified. // Get returns an item by id. Returned objects must never be modified.
func (v *memdbView) Get(id string) (*Snapshot, error) { func (v *View) Get(id string) (*Snapshot, error) {
s, err := v.txn.First(memdbContainersTable, memdbIDIndex, id) s, err := v.txn.First(memdbContainersTable, memdbIDIndex, id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -290,7 +273,7 @@ func (v *memdbView) Get(id string) (*Snapshot, error) {
} }
// getNames lists all the reserved names for the given container ID. // getNames lists all the reserved names for the given container ID.
func (v *memdbView) getNames(containerID string) []string { func (v *View) getNames(containerID string) []string {
iter, err := v.txn.Get(memdbNamesTable, memdbContainerIDIndex, containerID) iter, err := v.txn.Get(memdbNamesTable, memdbContainerIDIndex, containerID)
if err != nil { if err != nil {
return nil return nil
@ -309,7 +292,7 @@ func (v *memdbView) getNames(containerID string) []string {
} }
// GetID returns the container ID that the passed in name is reserved to. // GetID returns the container ID that the passed in name is reserved to.
func (v *memdbView) GetID(name string) (string, error) { func (v *View) GetID(name string) (string, error) {
s, err := v.txn.First(memdbNamesTable, memdbIDIndex, name) s, err := v.txn.First(memdbNamesTable, memdbIDIndex, name)
if err != nil { if err != nil {
return "", err return "", err
@ -321,7 +304,7 @@ func (v *memdbView) GetID(name string) (string, error) {
} }
// GetAllNames returns all registered names. // GetAllNames returns all registered names.
func (v *memdbView) GetAllNames() map[string][]string { func (v *View) GetAllNames() map[string][]string {
iter, err := v.txn.Get(memdbNamesTable, memdbContainerIDIndex) iter, err := v.txn.Get(memdbNamesTable, memdbContainerIDIndex)
if err != nil { if err != nil {
return nil return nil
@ -342,7 +325,7 @@ func (v *memdbView) GetAllNames() map[string][]string {
// transform maps a (deep) copied Container object to what queries need. // transform maps a (deep) copied Container object to what queries need.
// A lock on the Container is not held because these are immutable deep copies. // A lock on the Container is not held because these are immutable deep copies.
func (v *memdbView) transform(container *Container) *Snapshot { func (v *View) transform(container *Container) *Snapshot {
health := types.NoHealthcheck health := types.NoHealthcheck
if container.Health != nil { if container.Health != nil {
health = container.Health.Status() health = container.Health.Status()

View file

@ -373,7 +373,7 @@ func TestTruncIndex(t *testing.T) {
} }
} }
func assertIndexGet(t *testing.T, snapshot ViewDB, input, expectedResult string, expectError bool) { func assertIndexGet(t *testing.T, snapshot *ViewDB, input, expectedResult string, expectError bool) {
if result, err := snapshot.GetByPrefix(input); err != nil && !expectError { if result, err := snapshot.GetByPrefix(input); err != nil && !expectError {
t.Fatalf("Unexpected error getting '%s': %s", input, err) t.Fatalf("Unexpected error getting '%s': %s", input, err)
} else if err == nil && expectError { } else if err == nil && expectError {

View file

@ -73,7 +73,7 @@ type Daemon struct {
id string id string
repository string repository string
containers container.Store containers container.Store
containersReplica container.ViewDB containersReplica *container.ViewDB
execCommands *container.ExecStore execCommands *container.ExecStore
imageService ImageService imageService ImageService
configStore *config.Config configStore *config.Config

View file

@ -110,7 +110,7 @@ func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.C
return daemon.reduceContainers(config, daemon.refreshImage) return daemon.reduceContainers(config, daemon.refreshImage)
} }
func (daemon *Daemon) filterByNameIDMatches(view container.View, filter *listContext) ([]container.Snapshot, error) { func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listContext) ([]container.Snapshot, error) {
idSearch := false idSearch := false
names := filter.filters.Get("name") names := filter.filters.Get("name")
ids := filter.filters.Get("id") ids := filter.filters.Get("id")
@ -243,7 +243,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
} }
// foldFilter generates the container filter based on the user's filtering options. // foldFilter generates the container filter based on the user's filtering options.
func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerListOptions) (*listContext, error) { func (daemon *Daemon) foldFilter(view *container.View, config *types.ContainerListOptions) (*listContext, error) {
ctx := context.TODO() ctx := context.TODO()
psFilters := config.Filters psFilters := config.Filters
@ -363,7 +363,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis
}, nil }, nil
} }
func idOrNameFilter(view container.View, value string) (*container.Snapshot, error) { func idOrNameFilter(view *container.View, value string) (*container.Snapshot, error) {
filter, err := view.Get(value) filter, err := view.Get(value)
switch err.(type) { switch err.(type) {
case container.NoSuchContainerError: case container.NoSuchContainerError: