Disable locking on functions in batch operations

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>

Closes: #222
Approved by: rhatdan
This commit is contained in:
Matthew Heon
2018-01-12 15:48:50 -05:00
committed by Atomic Bot
parent 5599b64e72
commit 149640a4c8
2 changed files with 174 additions and 101 deletions

View File

@ -348,12 +348,14 @@ func (c *Container) LogPath() string {
// IPAddress returns the IP address of the container // IPAddress returns the IP address of the container
// If the container does not have a network namespace, an error will be returned // If the container does not have a network namespace, an error will be returned
func (c *Container) IPAddress() (net.IP, error) { func (c *Container) IPAddress() (net.IP, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return nil, errors.Wrapf(err, "error updating container %s state", c.ID()) return nil, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
if !c.config.CreateNetNS || c.state.NetNS == nil { if !c.config.CreateNetNS || c.state.NetNS == nil {
return nil, errors.Wrapf(ErrInvalidArg, "container %s does not have a network namespace", c.ID()) return nil, errors.Wrapf(ErrInvalidArg, "container %s does not have a network namespace", c.ID())
@ -365,87 +367,103 @@ func (c *Container) IPAddress() (net.IP, error) {
// ExitCode returns the exit code of the container as // ExitCode returns the exit code of the container as
// an int32 // an int32
func (c *Container) ExitCode() (int32, error) { func (c *Container) ExitCode() (int32, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return 0, errors.Wrapf(err, "error updating container %s state", c.ID()) return 0, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.ExitCode, nil return c.state.ExitCode, nil
} }
// Mounted returns a bool as to if the container's storage // Mounted returns a bool as to if the container's storage
// is mounted // is mounted
func (c *Container) Mounted() (bool, error) { func (c *Container) Mounted() (bool, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return false, errors.Wrapf(err, "error updating container %s state", c.ID()) return false, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.Mounted, nil return c.state.Mounted, nil
} }
// Mountpoint returns the path to the container's mounted // Mountpoint returns the path to the container's mounted
// storage as a string // storage as a string
func (c *Container) Mountpoint() (string, error) { func (c *Container) Mountpoint() (string, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return "", errors.Wrapf(err, "error updating container %s state", c.ID()) return "", errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.Mountpoint, nil return c.state.Mountpoint, nil
} }
// StartedTime is the time the container was started // StartedTime is the time the container was started
func (c *Container) StartedTime() (time.Time, error) { func (c *Container) StartedTime() (time.Time, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.StartedTime, nil return c.state.StartedTime, nil
} }
// FinishedTime is the time the container was stopped // FinishedTime is the time the container was stopped
func (c *Container) FinishedTime() (time.Time, error) { func (c *Container) FinishedTime() (time.Time, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.FinishedTime, nil return c.state.FinishedTime, nil
} }
// State returns the current state of the container // State returns the current state of the container
func (c *Container) State() (ContainerState, error) { func (c *Container) State() (ContainerState, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return ContainerStateUnknown, err return ContainerStateUnknown, err
} }
}
return c.state.State, nil return c.state.State, nil
} }
// PID returns the PID of the container // PID returns the PID of the container
// An error is returned if the container is not running // An error is returned if the container is not running
func (c *Container) PID() (int, error) { func (c *Container) PID() (int, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return -1, err return -1, err
} }
}
return c.state.PID, nil return c.state.PID, nil
} }
// MountPoint returns the mount point of the continer // MountPoint returns the mount point of the continer
func (c *Container) MountPoint() (string, error) { func (c *Container) MountPoint() (string, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return "", errors.Wrapf(err, "error updating container %s state", c.ID()) return "", errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.state.Mountpoint, nil return c.state.Mountpoint, nil
} }
@ -612,12 +630,14 @@ func (c *Container) refresh() error {
// Init creates a container in the OCI runtime // Init creates a container in the OCI runtime
func (c *Container) Init() (err error) { func (c *Container) Init() (err error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State != ContainerStateConfigured { if c.state.State != ContainerStateConfigured {
return errors.Wrapf(ErrCtrExists, "container %s has already been created in runtime", c.ID()) return errors.Wrapf(ErrCtrExists, "container %s has already been created in runtime", c.ID())
@ -761,12 +781,14 @@ func (c *Container) Init() (err error) {
// Start starts a container // Start starts a container
func (c *Container) Start() error { func (c *Container) Start() error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
// Container must be created or stopped to be started // Container must be created or stopped to be started
if !(c.state.State == ContainerStateCreated || c.state.State == ContainerStateStopped) { if !(c.state.State == ContainerStateCreated || c.state.State == ContainerStateStopped) {
@ -797,13 +819,16 @@ func (c *Container) Start() error {
// seconds), uses SIGKILL to attempt to forcibly stop the container. // seconds), uses SIGKILL to attempt to forcibly stop the container.
// If timeout is 0, SIGKILL will be used immediately // If timeout is 0, SIGKILL will be used immediately
func (c *Container) Stop(timeout uint) error { func (c *Container) Stop(timeout uint) error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
logrus.Debugf("Stopping ctr %s with timeout %d", c.ID(), timeout)
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
logrus.Debugf("Stopping ctr %s with timeout %d", c.ID(), timeout)
if c.state.State == ContainerStateConfigured || if c.state.State == ContainerStateConfigured ||
c.state.State == ContainerStateUnknown || c.state.State == ContainerStateUnknown ||
@ -825,12 +850,14 @@ func (c *Container) Stop(timeout uint) error {
// Kill sends a signal to a container // Kill sends a signal to a container
func (c *Container) Kill(signal uint) error { func (c *Container) Kill(signal uint) error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State != ContainerStateRunning { if c.state.State != ContainerStateRunning {
return errors.Wrapf(ErrCtrStateInvalid, "can only kill running containers") return errors.Wrapf(ErrCtrStateInvalid, "can only kill running containers")
@ -842,12 +869,15 @@ func (c *Container) Kill(signal uint) error {
// Exec starts a new process inside the container // Exec starts a new process inside the container
func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error { func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error {
var capList []string var capList []string
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
conState := c.state.State conState := c.state.State
@ -875,9 +905,14 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
// Attach attaches to a container // Attach attaches to a container
// Returns fully qualified URL of streaming server for the container // Returns fully qualified URL of streaming server for the container
func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error { func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error {
if !c.locked {
c.lock.Lock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
c.lock.Unlock()
return err return err
} }
c.lock.Unlock()
}
if c.state.State != ContainerStateCreated && if c.state.State != ContainerStateCreated &&
c.state.State != ContainerStateRunning { c.state.State != ContainerStateRunning {
@ -904,12 +939,14 @@ func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) erro
// Mount mounts a container's filesystem on the host // Mount mounts a container's filesystem on the host
// The path where the container has been mounted is returned // The path where the container has been mounted is returned
func (c *Container) Mount(label string) (string, error) { func (c *Container) Mount(label string) (string, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return "", err return "", err
} }
}
// return mountpoint if container already mounted // return mountpoint if container already mounted
if c.state.Mounted { if c.state.Mounted {
@ -937,12 +974,14 @@ func (c *Container) Mount(label string) (string, error) {
// Unmount unmounts a container's filesystem on the host // Unmount unmounts a container's filesystem on the host
func (c *Container) Unmount() error { func (c *Container) Unmount() error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused { if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused {
return errors.Wrapf(ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID()) return errors.Wrapf(ErrCtrStateInvalid, "cannot remove storage for container %s as it is running or paused", c.ID())
@ -953,12 +992,14 @@ func (c *Container) Unmount() error {
// Pause pauses a container // Pause pauses a container
func (c *Container) Pause() error { func (c *Container) Pause() error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State == ContainerStatePaused { if c.state.State == ContainerStatePaused {
return errors.Wrapf(ErrCtrStateInvalid, "%q is already paused", c.ID()) return errors.Wrapf(ErrCtrStateInvalid, "%q is already paused", c.ID())
@ -982,12 +1023,14 @@ func (c *Container) Pause() error {
// Unpause unpauses a container // Unpause unpauses a container
func (c *Container) Unpause() error { func (c *Container) Unpause() error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State != ContainerStatePaused { if c.state.State != ContainerStatePaused {
return errors.Wrapf(ErrCtrStateInvalid, "%q is not paused, can't unpause", c.ID()) return errors.Wrapf(ErrCtrStateInvalid, "%q is not paused, can't unpause", c.ID())
@ -1009,12 +1052,14 @@ func (c *Container) Unpause() error {
// Export exports a container's root filesystem as a tar archive // Export exports a container's root filesystem as a tar archive
// The archive will be saved as a file at the given path // The archive will be saved as a file at the given path
func (c *Container) Export(path string) error { func (c *Container) Export(path string) error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
return c.export(path) return c.export(path)
} }
@ -1051,16 +1096,28 @@ func (c *Container) export(path string) error {
// AddArtifact creates and writes to an artifact file for the container // AddArtifact creates and writes to an artifact file for the container
func (c *Container) AddArtifact(name string, data []byte) error { func (c *Container) AddArtifact(name string, data []byte) error {
if !c.valid {
return ErrCtrRemoved
}
return ioutil.WriteFile(c.getArtifactPath(name), data, 0740) return ioutil.WriteFile(c.getArtifactPath(name), data, 0740)
} }
// GetArtifact reads the specified artifact file from the container // GetArtifact reads the specified artifact file from the container
func (c *Container) GetArtifact(name string) ([]byte, error) { func (c *Container) GetArtifact(name string) ([]byte, error) {
if !c.valid {
return nil, ErrCtrRemoved
}
return ioutil.ReadFile(c.getArtifactPath(name)) return ioutil.ReadFile(c.getArtifactPath(name))
} }
// RemoveArtifact deletes the specified artifacts file // RemoveArtifact deletes the specified artifacts file
func (c *Container) RemoveArtifact(name string) error { func (c *Container) RemoveArtifact(name string) error {
if !c.valid {
return ErrCtrRemoved
}
return os.Remove(c.getArtifactPath(name)) return os.Remove(c.getArtifactPath(name))
} }
@ -1070,12 +1127,14 @@ func (c *Container) getArtifactPath(name string) string {
// Inspect a container for low-level information // Inspect a container for low-level information
func (c *Container) Inspect(size bool) (*ContainerInspectData, error) { func (c *Container) Inspect(size bool) (*ContainerInspectData, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return nil, err return nil, err
} }
}
storeCtr, err := c.runtime.store.Container(c.ID()) storeCtr, err := c.runtime.store.Container(c.ID())
if err != nil { if err != nil {
@ -1096,12 +1155,14 @@ func (c *Container) Inspect(size bool) (*ContainerInspectData, error) {
// Commit commits the changes between a container and its image, creating a new // Commit commits the changes between a container and its image, creating a new
// image // image
func (c *Container) Commit(pause bool, options CopyOptions) error { func (c *Container) Commit(pause bool, options CopyOptions) error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
if c.state.State == ContainerStateRunning && pause { if c.state.State == ContainerStateRunning && pause {
if err := c.runtime.ociRuntime.pauseContainer(c); err != nil { if err := c.runtime.ociRuntime.pauseContainer(c); err != nil {
@ -1129,6 +1190,10 @@ func (c *Container) Commit(pause bool, options CopyOptions) error {
// Wait blocks on a container to exit and returns its exit code // Wait blocks on a container to exit and returns its exit code
func (c *Container) Wait() (int32, error) { func (c *Container) Wait() (int32, error) {
if !c.valid {
return -1, ErrCtrRemoved
}
err := wait.PollImmediateInfinite(1, err := wait.PollImmediateInfinite(1,
func() (bool, error) { func() (bool, error) {
stopped, err := c.isStopped() stopped, err := c.isStopped()
@ -1150,8 +1215,10 @@ func (c *Container) Wait() (int32, error) {
} }
func (c *Container) isStopped() (bool, error) { func (c *Container) isStopped() (bool, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
}
err := c.syncContainer() err := c.syncContainer()
if err != nil { if err != nil {
return true, err return true, err
@ -1215,11 +1282,13 @@ func (c *Container) mountStorage() (err error) {
// CleanupStorage unmounts all mount points in container and cleans up container storage // CleanupStorage unmounts all mount points in container and cleans up container storage
func (c *Container) CleanupStorage() error { func (c *Container) CleanupStorage() error {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return err return err
} }
}
return c.cleanupStorage() return c.cleanupStorage()
} }

View File

@ -14,11 +14,13 @@ import (
// GetContainerPids reads sysfs to obtain the pids associated with the container's cgroup // GetContainerPids reads sysfs to obtain the pids associated with the container's cgroup
// and uses locking // and uses locking
func (c *Container) GetContainerPids() ([]string, error) { func (c *Container) GetContainerPids() ([]string, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID()) return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
return c.getContainerPids() return c.getContainerPids()
} }
@ -38,11 +40,13 @@ func (c *Container) getContainerPids() ([]string, error) {
// GetContainerPidInformation calls ps with the appropriate options and returns // GetContainerPidInformation calls ps with the appropriate options and returns
// the results as a string // the results as a string
func (c *Container) GetContainerPidInformation(args []string) ([]string, error) { func (c *Container) GetContainerPidInformation(args []string) ([]string, error) {
if !c.locked {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
if err := c.syncContainer(); err != nil { if err := c.syncContainer(); err != nil {
return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID()) return []string{}, errors.Wrapf(err, "error updating container %s state", c.ID())
} }
}
pids, err := c.getContainerPids() pids, err := c.getContainerPids()
if err != nil { if err != nil {
return []string{}, errors.Wrapf(err, "unable to obtain pids for ", c.ID()) return []string{}, errors.Wrapf(err, "unable to obtain pids for ", c.ID())