Merge pull request #19383 from calavera/container_store

Extract container store from the daemon.
Upstream-commit: 9ae51b3e0f01111b743c61d8d0811e7061b490df
Component: engine
This commit is contained in:
Brian Goff
2016-01-21 17:20:47 -05:00
10 changed files with 289 additions and 120 deletions
+12 -53
View File
@@ -99,46 +99,11 @@ func (e ErrImageDoesNotExist) Error() string {
return fmt.Sprintf("no such id: %s", e.RefOrID)
}
type contStore struct {
s map[string]*container.Container
sync.Mutex
}
func (c *contStore) Add(id string, cont *container.Container) {
c.Lock()
c.s[id] = cont
c.Unlock()
}
func (c *contStore) Get(id string) *container.Container {
c.Lock()
res := c.s[id]
c.Unlock()
return res
}
func (c *contStore) Delete(id string) {
c.Lock()
delete(c.s, id)
c.Unlock()
}
func (c *contStore) List() []*container.Container {
containers := new(History)
c.Lock()
for _, cont := range c.s {
containers.Add(cont)
}
c.Unlock()
containers.sort()
return *containers
}
// Daemon holds information about the Docker daemon.
type Daemon struct {
ID string
repository string
containers *contStore
containers container.Store
execCommands *exec.Store
referenceStore reference.Store
downloadManager *xfer.LayerDownloadManager
@@ -811,7 +776,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
d.ID = trustKey.PublicKey().KeyID()
d.repository = daemonRepo
d.containers = &contStore{s: make(map[string]*container.Container)}
d.containers = container.NewMemoryStore()
d.execCommands = exec.NewStore()
d.referenceStore = referenceStore
d.distributionMetadataStore = distributionMetadataStore
@@ -890,24 +855,18 @@ func (daemon *Daemon) shutdownContainer(c *container.Container) error {
func (daemon *Daemon) Shutdown() error {
daemon.shutdown = true
if daemon.containers != nil {
group := sync.WaitGroup{}
logrus.Debug("starting clean shutdown of all containers...")
for _, cont := range daemon.List() {
if !cont.IsRunning() {
continue
daemon.containers.ApplyAll(func(c *container.Container) {
if !c.IsRunning() {
return
}
logrus.Debugf("stopping %s", cont.ID)
group.Add(1)
go func(c *container.Container) {
defer group.Done()
if err := daemon.shutdownContainer(c); err != nil {
logrus.Errorf("Stop container error: %v", err)
return
}
logrus.Debugf("container stopped %s", c.ID)
}(cont)
}
group.Wait()
logrus.Debugf("stopping %s", c.ID)
if err := daemon.shutdownContainer(c); err != nil {
logrus.Errorf("Stop container error: %v", err)
return
}
logrus.Debugf("container stopped %s", c.ID)
})
}
// trigger libnetwork Stop only if it's initialized
+6 -9
View File
@@ -61,15 +61,12 @@ func TestGetContainer(t *testing.T) {
},
}
store := &contStore{
s: map[string]*container.Container{
c1.ID: c1,
c2.ID: c2,
c3.ID: c3,
c4.ID: c4,
c5.ID: c5,
},
}
store := container.NewMemoryStore()
store.Add(c1.ID, c1)
store.Add(c2.ID, c2)
store.Add(c3.ID, c3)
store.Add(c4.ID, c4)
store.Add(c5.ID, c5)
index := truncindex.NewTruncIndex([]string{})
index.Add(c1.ID)
+1 -1
View File
@@ -20,7 +20,7 @@ func TestContainerDoubleDelete(t *testing.T) {
repository: tmp,
root: tmp,
}
daemon.containers = &contStore{s: make(map[string]*container.Container)}
daemon.containers = container.NewMemoryStore()
container := &container.Container{
CommonContainer: container.CommonContainer{
-34
View File
@@ -1,34 +0,0 @@
package daemon
import (
"sort"
"github.com/docker/docker/container"
)
// History is a convenience type for storing a list of containers,
// ordered by creation date.
type History []*container.Container
func (history *History) Len() int {
return len(*history)
}
func (history *History) Less(i, j int) bool {
containers := *history
return containers[j].Created.Before(containers[i].Created)
}
func (history *History) Swap(i, j int) {
containers := *history
containers[i], containers[j] = containers[j], containers[i]
}
// Add the given container to history.
func (history *History) Add(container *container.Container) {
*history = append(*history, container)
}
func (history *History) sort() {
sort.Sort(history)
}
+20 -32
View File
@@ -179,13 +179,9 @@ func isImageIDPrefix(imageID, possiblePrefix string) bool {
// getContainerUsingImage returns a container that was created using the given
// imageID. Returns nil if there is no such container.
func (daemon *Daemon) getContainerUsingImage(imageID image.ID) *container.Container {
for _, container := range daemon.List() {
if container.ImageID == imageID {
return container
}
}
return nil
return daemon.containers.First(func(c *container.Container) bool {
return c.ImageID == imageID
})
}
// removeImageRef attempts to parse and remove the given image reference from
@@ -328,19 +324,15 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType
if mask&conflictRunningContainer != 0 {
// Check if any running container is using the image.
for _, container := range daemon.List() {
if !container.IsRunning() {
// Skip this until we check for soft conflicts later.
continue
}
if container.ImageID == imgID {
return &imageDeleteConflict{
imgID: imgID,
hard: true,
used: true,
message: fmt.Sprintf("image is being used by running container %s", stringid.TruncateID(container.ID)),
}
running := func(c *container.Container) bool {
return c.IsRunning() && c.ImageID == imgID
}
if container := daemon.containers.First(running); container != nil {
return &imageDeleteConflict{
imgID: imgID,
hard: true,
used: true,
message: fmt.Sprintf("image is being used by running container %s", stringid.TruncateID(container.ID)),
}
}
}
@@ -355,18 +347,14 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType
if mask&conflictStoppedContainer != 0 {
// Check if any stopped containers reference this image.
for _, container := range daemon.List() {
if container.IsRunning() {
// Skip this as it was checked above in hard conflict conditions.
continue
}
if container.ImageID == imgID {
return &imageDeleteConflict{
imgID: imgID,
used: true,
message: fmt.Sprintf("image is being used by stopped container %s", stringid.TruncateID(container.ID)),
}
stopped := func(c *container.Container) bool {
return !c.IsRunning() && c.ImageID == imgID
}
if container := daemon.containers.First(stopped); container != nil {
return &imageDeleteConflict{
imgID: imgID,
used: true,
message: fmt.Sprintf("image is being used by stopped container %s", stringid.TruncateID(container.ID)),
}
}
}
+12 -10
View File
@@ -4,9 +4,11 @@ import (
"os"
"runtime"
"strings"
"sync/atomic"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/container"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/parsers/kernel"
@@ -54,24 +56,24 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
initPath := utils.DockerInitPath("")
sysInfo := sysinfo.New(true)
var cRunning, cPaused, cStopped int
for _, c := range daemon.List() {
var cRunning, cPaused, cStopped int32
daemon.containers.ApplyAll(func(c *container.Container) {
switch c.StateString() {
case "paused":
cPaused++
atomic.AddInt32(&cPaused, 1)
case "running":
cRunning++
atomic.AddInt32(&cRunning, 1)
default:
cStopped++
atomic.AddInt32(&cStopped, 1)
}
}
})
v := &types.Info{
ID: daemon.ID,
Containers: len(daemon.List()),
ContainersRunning: cRunning,
ContainersPaused: cPaused,
ContainersStopped: cStopped,
Containers: int(cRunning + cPaused + cStopped),
ContainersRunning: int(cRunning),
ContainersPaused: int(cPaused),
ContainersStopped: int(cStopped),
Images: len(daemon.imageStore.Map()),
Driver: daemon.GraphDriverName(),
DriverStatus: daemon.layerStore.DriverStatus(),
+3 -6
View File
@@ -39,12 +39,9 @@ func TestMigrateLegacySqliteLinks(t *testing.T) {
},
}
store := &contStore{
s: map[string]*container.Container{
c1.ID: c1,
c2.ID: c2,
},
}
store := container.NewMemoryStore()
store.Add(c1.ID, c1)
store.Add(c2.ID, c2)
d := &Daemon{root: tmpDir, containers: store}
db, err := graphdb.NewSqliteConn(filepath.Join(d.root, "linkgraph.db"))