aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-01-18 10:49:01 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-02-09 15:01:34 +0000
commit6214be07c2bf82f90361f058ab0c7178b634ecf9 (patch)
tree34a1e85e4f6bfca99e4207f102c5c0d208a00289
parentbf981fc8738ec5910efd54117677f8eacb7ca37e (diff)
downloadpodman-6214be07c2bf82f90361f058ab0c7178b634ecf9.tar.gz
podman-6214be07c2bf82f90361f058ab0c7178b634ecf9.tar.bz2
podman-6214be07c2bf82f90361f058ab0c7178b634ecf9.zip
Tear out pod containers map. Instead rely on state
This ensures that there is only one canonical place where containers in a pod are stored, in the state itself. Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #268 Approved by: rhatdan
-rw-r--r--libpod/in_memory_state.go149
-rw-r--r--libpod/pod.go87
-rw-r--r--libpod/runtime_pod.go2
-rw-r--r--libpod/sql_state.go19
-rw-r--r--libpod/state.go14
5 files changed, 154 insertions, 117 deletions
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 55162e6c8..2f0d2ec70 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -8,15 +8,20 @@ import (
"github.com/projectatomic/libpod/pkg/registrar"
)
+// TODO: unified name/ID registry to ensure no name and ID conflicts between
+// containers and pods
+// This can probably be used to replace the existing trunc index and registrars
+
// An InMemoryState is a purely in-memory state store
type InMemoryState struct {
- pods map[string]*Pod
- containers map[string]*Container
- ctrDepends map[string][]string
- podNameIndex *registrar.Registrar
- podIDIndex *truncindex.TruncIndex
- ctrNameIndex *registrar.Registrar
- ctrIDIndex *truncindex.TruncIndex
+ pods map[string]*Pod
+ containers map[string]*Container
+ ctrDepends map[string][]string
+ podContainers map[string]map[string]*Container
+ podNameIndex *registrar.Registrar
+ podIDIndex *truncindex.TruncIndex
+ ctrNameIndex *registrar.Registrar
+ ctrIDIndex *truncindex.TruncIndex
}
// NewInMemoryState initializes a new, empty in-memory state
@@ -28,6 +33,8 @@ func NewInMemoryState() (State, error) {
state.ctrDepends = make(map[string][]string)
+ state.podContainers = make(map[string]map[string]*Container)
+
state.podNameIndex = registrar.NewRegistrar()
state.ctrNameIndex = registrar.NewRegistrar()
@@ -293,22 +300,73 @@ func (s *InMemoryState) HasPod(id string) (bool, error) {
return ok, nil
}
-// PodContainers retrieves the containers from a pod given the pod's full ID
-func (s *InMemoryState) PodContainers(id string) ([]*Container, error) {
- if id == "" {
- return nil, ErrEmptyID
+// PodHasContainer checks if the given pod has a container with the given ID
+func (s *InMemoryState) PodHasContainer(pod *Pod, ctrID string) (bool, error) {
+ if !pod.valid {
+ return false, errors.Wrapf(ErrPodRemoved, "pod %s is not valid")
}
- pod, ok := s.pods[id]
+ podCtrs, ok := s.podContainers[pod.ID()]
+ if !ok {
+ pod.valid = false
+ return false, errors.Wrapf(ErrNoSuchPod, "no pod with ID %s found in state", pod.ID())
+ }
+
+ _, ok = podCtrs[ctrID]
+ return ok, nil
+}
+
+// PodContainersByID returns the IDs of all containers in the given pod
+func (s *InMemoryState) PodContainersByID(pod *Pod) ([]string, error) {
+ if !pod.valid {
+ return nil, errors.Wrapf(ErrPodRemoved, "pod %s is not valid")
+ }
+
+ podCtrs, ok := s.podContainers[pod.ID()]
if !ok {
- return nil, errors.Wrapf(ErrNoSuchPod, "no pod with ID %s found", id)
+ pod.valid = false
+ return nil, errors.Wrapf(ErrNoSuchPod, "no pod with ID %s found in state", pod.ID())
+ }
+
+ length := len(podCtrs)
+ if length == 0 {
+ return []string{}, nil
}
- return pod.GetContainers()
+ ctrs := make([]string, 0, length)
+ for _, ctr := range podCtrs {
+ ctrs = append(ctrs, ctr.ID())
+ }
+
+ return ctrs, nil
+}
+
+// PodContainers retrieves the containers from a pod
+func (s *InMemoryState) PodContainers(pod *Pod) ([]*Container, error) {
+ if !pod.valid {
+ return nil, errors.Wrapf(ErrPodRemoved, "pod %s is not valid")
+ }
+
+ podCtrs, ok := s.podContainers[pod.ID()]
+ if !ok {
+ pod.valid = false
+ return nil, errors.Wrapf(ErrNoSuchPod, "no pod with ID %s found in state", pod.ID())
+ }
+
+ length := len(podCtrs)
+ if length == 0 {
+ return []*Container{}, nil
+ }
+
+ ctrs := make([]*Container, 0, length)
+ for _, ctr := range podCtrs {
+ ctrs = append(ctrs, ctr)
+ }
+
+ return ctrs, nil
}
// AddPod adds a given pod to the state
-// Only empty pods can be added to the state
func (s *InMemoryState) AddPod(pod *Pod) error {
if !pod.valid {
return errors.Wrapf(ErrPodRemoved, "pod %s is not valid and cannot be added", pod.ID())
@@ -318,8 +376,8 @@ func (s *InMemoryState) AddPod(pod *Pod) error {
return errors.Wrapf(ErrPodExists, "pod with ID %s already exists in state", pod.ID())
}
- if len(pod.containers) != 0 {
- return errors.Wrapf(ErrInternal, "only empty pods can be added to the state")
+ if _, ok := s.podContainers[pod.ID()]; ok {
+ return errors.Wrapf(ErrPodExists, "pod with ID %s already exists in state", pod.ID())
}
if err := s.podNameIndex.Reserve(pod.Name(), pod.ID()); err != nil {
@@ -333,11 +391,13 @@ func (s *InMemoryState) AddPod(pod *Pod) error {
s.pods[pod.ID()] = pod
+ s.podContainers[pod.ID()] = make(map[string]*Container)
+
return nil
}
// RemovePod removes a given pod from the state
-// Containers within the pod will not be removed or changed
+// Only empty pods can be removed
func (s *InMemoryState) RemovePod(pod *Pod) error {
// Don't make many validity checks to ensure we can kick badly formed
// pods out of the state
@@ -345,22 +405,24 @@ func (s *InMemoryState) RemovePod(pod *Pod) error {
if _, ok := s.pods[pod.ID()]; !ok {
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
}
+ podCtrs, ok := s.podContainers[pod.ID()]
+ if !ok {
+ return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
+ }
+ if len(podCtrs) != 0 {
+ return errors.Wrapf(ErrCtrExists, "pod %s is not empty and cannot be removed", pod.ID())
+ }
if err := s.podIDIndex.Delete(pod.ID()); err != nil {
return errors.Wrapf(err, "error removing pod ID %s from index", pod.ID())
}
delete(s.pods, pod.ID())
+ delete(s.podContainers, pod.ID())
s.podNameIndex.Release(pod.Name())
return nil
}
-// UpdatePod updates a pod's state from the backing database
-// As in-memory states have no database this is a no-op
-func (s *InMemoryState) UpdatePod(pod *Pod) error {
- return nil
-}
-
// AddContainerToPod adds a container to the given pod, also adding it to the
// state
func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
@@ -375,13 +437,20 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
return errors.Wrapf(ErrInvalidArg, "container %s is not in pod %s", ctr.ID(), pod.ID())
}
- // Add container to pod
- if err := pod.addContainer(ctr); err != nil {
- return err
+ // Retrieve pod containers list
+ podCtrs, ok := s.podContainers[pod.ID()]
+ if !ok {
+ pod.valid = false
+ return errors.Wrapf(ErrPodRemoved, "pod %s not found in state", pod.ID())
+ }
+
+ // Is the container already in the pod?
+ if _, ok := podCtrs[ctr.ID()]; ok {
+ return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), pod.ID())
}
// Add container to state
- _, ok := s.containers[ctr.ID()]
+ _, ok = s.containers[ctr.ID()]
if ok {
return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in state", ctr.ID())
}
@@ -397,6 +466,9 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
s.containers[ctr.ID()] = ctr
+ // Add container to pod containers
+ podCtrs[ctr.ID()] = ctr
+
return nil
}
@@ -410,18 +482,16 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
return errors.Wrapf(ErrCtrRemoved, "container %s is not valid and cannot be removed from the pod", ctr.ID())
}
- // Is the container in the pod?
- exists, err := pod.HasContainer(ctr.ID())
- if err != nil {
- return errors.Wrapf(err, "error checking for container %s in pod %s", ctr.ID(), pod.ID())
- }
- if !exists {
- return errors.Wrapf(ErrNoSuchCtr, "no container %s in pod %s", ctr.ID(), pod.ID())
+ // Retrieve pod containers
+ podCtrs, ok := s.podContainers[pod.ID()]
+ if !ok {
+ pod.valid = false
+ return errors.Wrapf(ErrPodRemoved, "pod %s has been removed", pod.ID())
}
- // Remove container from pod
- if err := pod.removeContainer(ctr); err != nil {
- return err
+ // Is the container in the pod?
+ if _, ok := podCtrs[ctr.ID()]; !ok {
+ return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in pod %s", ctr.ID(), pod.ID())
}
// Remove container from state
@@ -435,6 +505,9 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
delete(s.containers, ctr.ID())
s.ctrNameIndex.Release(ctr.Name())
+ // Remove the container from the pod
+ delete(podCtrs, ctr.ID())
+
return nil
}
diff --git a/libpod/pod.go b/libpod/pod.go
index 15899930b..91636546d 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -15,10 +15,9 @@ type Pod struct {
name string
labels map[string]string
- containers map[string]*Container
-
- valid bool
- lock storage.Locker
+ valid bool
+ runtime *Runtime
+ lock storage.Locker
}
// ID retrieves the pod's ID
@@ -42,17 +41,11 @@ func (p *Pod) Labels() map[string]string {
}
// Creates a new, empty pod
-func newPod(lockDir string) (*Pod, error) {
+func newPod(lockDir string, runtime *Runtime) (*Pod, error) {
pod := new(Pod)
pod.id = stringid.GenerateNonCryptoID()
pod.name = namesgenerator.GetRandomName(0)
-
- pod.containers = make(map[string]*Container)
-
- // TODO: containers and pods share a locks folder, but not tables in the
- // database
- // As the locks are 256-bit pseudorandom integers, collision is unlikely
- // But it's something worth looking into
+ pod.runtime = runtime
// Path our lock file will reside at
lockPath := filepath.Join(lockDir, pod.id)
@@ -66,47 +59,9 @@ func newPod(lockDir string) (*Pod, error) {
return pod, nil
}
-// Adds a container to the pod
-// Does not check that container's pod ID is set correctly, or attempt to set
-// pod ID after adding
-func (p *Pod) addContainer(ctr *Container) error {
- p.lock.Lock()
- defer p.lock.Unlock()
-
- if !p.valid {
- return ErrPodRemoved
- }
-
- if !ctr.valid {
- return ErrCtrRemoved
- }
-
- if _, ok := p.containers[ctr.ID()]; ok {
- return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), p.id)
- }
-
- p.containers[ctr.ID()] = ctr
-
- return nil
-}
-
-// Removes a container from the pod
-// Does not perform any checks on the container
-func (p *Pod) removeContainer(ctr *Container) error {
- p.lock.Lock()
- defer p.lock.Unlock()
-
- if !p.valid {
- return ErrPodRemoved
- }
-
- if _, ok := p.containers[ctr.ID()]; !ok {
- return errors.Wrapf(ErrNoSuchCtr, "no container with id %s in pod %s", ctr.ID(), p.id)
- }
-
- delete(p.containers, ctr.ID())
-
- return nil
+// Init() initializes all containers within a pod that have not been initialized
+func (p *Pod) Init() error {
+ return ErrNotImplemented
}
// Start starts all containers within a pod that are not already running
@@ -126,20 +81,15 @@ func (p *Pod) Kill(signal uint) error {
// HasContainer checks if a container is present in the pod
func (p *Pod) HasContainer(id string) (bool, error) {
- p.lock.Lock()
- defer p.lock.Unlock()
-
if !p.valid {
return false, ErrPodRemoved
}
- _, ok := p.containers[id]
-
- return ok, nil
+ return p.runtime.state.PodHasContainer(p, id)
}
-// GetContainers retrieves the containers in the pod
-func (p *Pod) GetContainers() ([]*Container, error) {
+// AllContainersID returns the container IDs of all the containers in the pod
+func (p *Pod) AllContainersByID() ([]string, error) {
p.lock.Lock()
defer p.lock.Unlock()
@@ -147,12 +97,19 @@ func (p *Pod) GetContainers() ([]*Container, error) {
return nil, ErrPodRemoved
}
- ctrs := make([]*Container, 0, len(p.containers))
- for _, ctr := range p.containers {
- ctrs = append(ctrs, ctr)
+ return p.runtime.state.PodContainersByID(p)
+}
+
+// AllContainers retrieves the containers in the pod
+func (p *Pod) AllContainers() ([]*Container, error) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ if !p.valid {
+ return nil, ErrPodRemoved
}
- return ctrs, nil
+ return p.runtime.state.PodContainers(p)
}
// Status gets the status of all containers in the pod
diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go
index 35c7f0642..d471b903f 100644
--- a/libpod/runtime_pod.go
+++ b/libpod/runtime_pod.go
@@ -24,7 +24,7 @@ func (r *Runtime) NewPod(options ...PodCreateOption) (*Pod, error) {
return nil, ErrRuntimeStopped
}
- pod, err := newPod(r.lockDir)
+ pod, err := newPod(r.lockDir, r)
if err != nil {
return nil, errors.Wrapf(err, "error creating pod")
}
diff --git a/libpod/sql_state.go b/libpod/sql_state.go
index c10975d47..5c843ad6f 100644
--- a/libpod/sql_state.go
+++ b/libpod/sql_state.go
@@ -839,8 +839,20 @@ func (s *SQLState) HasPod(id string) (bool, error) {
return false, ErrNotImplemented
}
+// PodHasContainer checks if the given pod containers a container with the given
+// ID
+func (s *SQLState) PodHasContainer(pod *Pod, ctrID string) (bool, error) {
+ return false, ErrNotImplemented
+}
+
+// PodContainersByID returns the container IDs of all containers in the given
+// pod
+func (s *SQLState) PodContainersByID(pod *Pod) ([]string, error) {
+ return nil, ErrNotImplemented
+}
+
// PodContainers returns all the containers in a pod given the pod's full ID
-func (s *SQLState) PodContainers(id string) ([]*Container, error) {
+func (s *SQLState) PodContainers(pod *Pod) ([]*Container, error) {
return nil, ErrNotImplemented
}
@@ -856,11 +868,6 @@ func (s *SQLState) RemovePod(pod *Pod) error {
return ErrNotImplemented
}
-// UpdatePod updates a pod from the database
-func (s *SQLState) UpdatePod(pod *Pod) error {
- return ErrNotImplemented
-}
-
// AddContainerToPod adds a container to the given pod
func (s *SQLState) AddContainerToPod(pod *Pod, ctr *Container) error {
return ErrNotImplemented
diff --git a/libpod/state.go b/libpod/state.go
index 01ae58bd1..3e5da9306 100644
--- a/libpod/state.go
+++ b/libpod/state.go
@@ -42,17 +42,17 @@ type State interface {
LookupPod(idOrName string) (*Pod, error)
// Checks if a pod with the given ID is present in the state
HasPod(id string) (bool, error)
- // Get all the containers in a pod. Accepts full ID of pod.
- PodContainers(id string) ([]*Container, error)
+ // Check if a pod has a container with the given ID
+ PodHasContainer(pod *Pod, ctrID string) (bool, error)
+ // Get the IDs of all containers in a pod
+ PodContainersByID(pod *Pod) ([]string, error)
+ // Get all the containers in a pod
+ PodContainers(pod *Pod) ([]*Container, error)
// Adds pod to state
- // Only empty pods can be added to the state
AddPod(pod *Pod) error
// Removes pod from state
- // Containers within a pod will not be removed from the state, and will
- // not be changed to remove them from the now-removed pod
+ // Only empty pods can be removed from the state
RemovePod(pod *Pod) error
- // UpdatePod updates a pod's state from the backing store
- UpdatePod(pod *Pod) error
// AddContainerToPod adds a container to an existing pod
// The container given will be added to the state and the pod
AddContainerToPod(pod *Pod, ctr *Container) error