From 5fb95bf7290889efaca0729360fc918a7f1730a9 Mon Sep 17 00:00:00 2001 From: Patrick Boyd Date: Wed, 11 Jan 2023 14:25:44 -0600 Subject: [PATCH] Add helper methods for multiple start/stop with wait --- dbus/methods.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/dbus/methods.go b/dbus/methods.go index 074148cb..7906bc6e 100644 --- a/dbus/methods.go +++ b/dbus/methods.go @@ -112,6 +112,39 @@ func (c *Conn) StartUnitContext(ctx context.Context, name string, mode string, c return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode) } +// Starts Multiple units and waits for their success or failure before returning +func (c *Conn) StartMultipleUnitsAndWait(ctx context.Context, names []string, mode string) ([]string, []error) { + channels := make([]chan string, len(names)) + res := make([]string, len(names)) + errs := make([]error, len(names)) + for i := range names { + channels[i] = make(chan string, 1) + } + for i, name := range names { + _, errs[i] = c.StartUnitContext(ctx, name, mode, channels[i]) + if errs[i] != nil { + channels[i] = nil + } + } + for i, ch := range channels { + if ch == nil { + continue + } + select { + case status := <-ch: + res[i] = status + case <-ctx.Done(): + errs[i] = fmt.Errorf("operation halted: %w", ctx.Err()) + } + } + for _, err := range errs { + if err != nil { + return res, errs + } + } + return res, nil +} + // Deprecated: use StopUnitContext instead. func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) { return c.StopUnitContext(context.Background(), name, mode, ch) @@ -123,6 +156,39 @@ func (c *Conn) StopUnitContext(ctx context.Context, name string, mode string, ch return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode) } +// Stops Multiple units and waits for their success or failure before returning +func (c *Conn) StopMultipleUnitsAndWait(ctx context.Context, names []string, mode string) ([]string, []error) { + channels := make([]chan string, len(names)) + res := make([]string, len(names)) + errs := make([]error, len(names)) + for i := range names { + channels[i] = make(chan string, 1) + } + for i, name := range names { + _, errs[i] = c.StopUnitContext(ctx, name, mode, channels[i]) + if errs[i] != nil { + channels[i] = nil + } + } + for i, ch := range channels { + if ch == nil { + continue + } + select { + case status := <-ch: + res[i] = status + case <-ctx.Done(): + errs[i] = fmt.Errorf("operation halted: %w", ctx.Err()) + } + } + for _, err := range errs { + if err != nil { + return res, errs + } + } + return res, nil +} + // Deprecated: use ReloadUnitContext instead. func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) { return c.ReloadUnitContext(context.Background(), name, mode, ch)