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:
parent
f53692a632
commit
511a909ae6
5 changed files with 30 additions and 47 deletions
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue