diff options
author | Matthew Heon <matthew.heon@pm.me> | 2020-08-19 16:15:35 -0400 |
---|---|---|
committer | Matthew Heon <mheon@redhat.com> | 2020-10-07 10:00:11 -0400 |
commit | 2bb2425704cc7181c5eb924400b351b3a2d9a592 (patch) | |
tree | 0a850a365ef085fce496354a241649b7e779877a /pkg/parallel/parallel_linux.go | |
parent | a7500e54a4646c7db477349e2530ac13df77b8fa (diff) | |
download | podman-2bb2425704cc7181c5eb924400b351b3a2d9a592.tar.gz podman-2bb2425704cc7181c5eb924400b351b3a2d9a592.tar.bz2 podman-2bb2425704cc7181c5eb924400b351b3a2d9a592.zip |
Move pod jobs to parallel execution
Make Podman pod operations that do not involve starting
containers (which needs to be done in a specific order) use the
same parallel operation code we use to make `podman stop` on
large numbers of containers fast. We were previously stopping
containers in a pod serially, which could take up to the timeout
(default 15 seconds) for each container - stopping 100 containers
that do not respond to SIGTERM would take 25 minutes.
To do this, refactor the parallel operation code a bit to remove
its dependency on libpod (damn circular import restrictions...)
and use parallel functions that just re-use the standard
container API operations - maximizes code reuse (previously each
pod handler had a separate implementation of the container
function it performed).
This is a bit of a palate cleanser after fighting CI for two
days - nice to be able to return to a land of sanity.
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'pkg/parallel/parallel_linux.go')
-rw-r--r-- | pkg/parallel/parallel_linux.go | 57 |
1 files changed, 0 insertions, 57 deletions
diff --git a/pkg/parallel/parallel_linux.go b/pkg/parallel/parallel_linux.go deleted file mode 100644 index 442db1502..000000000 --- a/pkg/parallel/parallel_linux.go +++ /dev/null @@ -1,57 +0,0 @@ -package parallel - -import ( - "context" - "sync" - - "github.com/containers/podman/v2/libpod" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// ContainerOp performs the given function on the given set of -// containers, using a number of parallel threads. -// If no error is returned, each container specified in ctrs will have an entry -// in the resulting map; containers with no error will be set to nil. -func ContainerOp(ctx context.Context, ctrs []*libpod.Container, applyFunc func(*libpod.Container) error) (map[*libpod.Container]error, error) { - jobControlLock.RLock() - defer jobControlLock.RUnlock() - - // We could use a sync.Map but given Go's lack of generic I'd rather - // just use a lock on a normal map... - // The expectation is that most of the time is spent in applyFunc - // anyways. - var ( - errMap = make(map[*libpod.Container]error) - errLock sync.Mutex - allDone sync.WaitGroup - ) - - for _, ctr := range ctrs { - // Block until a thread is available - if err := jobControl.Acquire(ctx, 1); err != nil { - return nil, errors.Wrapf(err, "error acquiring job control semaphore") - } - - allDone.Add(1) - - c := ctr - go func() { - logrus.Debugf("Launching job on container %s", c.ID()) - - err := applyFunc(c) - errLock.Lock() - errMap[c] = err - errLock.Unlock() - - allDone.Done() - jobControl.Release(1) - }() - } - - allDone.Wait() - - return errMap, nil -} - -// TODO: Add an Enqueue() function that returns a promise |