diff --git a/cmd/hakurei/print.go b/cmd/hakurei/print.go index 15f71a6..27abc26 100644 --- a/cmd/hakurei/print.go +++ b/cmd/hakurei/print.go @@ -168,7 +168,7 @@ func printShowInstance( } // printPs writes a representation of active instances to output. -func printPs(output io.Writer, now time.Time, s store.Store, short, flagJSON bool) { +func printPs(output io.Writer, now time.Time, s store.Compat, short, flagJSON bool) { var entries map[hst.ID]*hst.State if e, err := store.Join(s); err != nil { log.Fatalf("cannot join store: %v", err) diff --git a/internal/outcome/process.go b/internal/outcome/process.go index 2dc7653..4ef49b0 100644 --- a/internal/outcome/process.go +++ b/internal/outcome/process.go @@ -34,7 +34,7 @@ type mainState struct { // Time is nil if no process was ever created. Time *time.Time - store store.Store + store store.Compat cancel context.CancelFunc cmd *exec.Cmd cmdWait chan error diff --git a/internal/store/compat.go b/internal/store/compat.go index c0ef6dd..0db2f5f 100644 --- a/internal/store/compat.go +++ b/internal/store/compat.go @@ -1,6 +1,8 @@ package store import ( + "errors" + "maps" "strconv" "hakurei.app/container/check" @@ -10,7 +12,7 @@ import ( /* this provides an implementation of Store on top of the improved state tracking to ease in the changes */ -type Store interface { +type Compat interface { // Do calls f exactly once and ensures store exclusivity until f returns. // Returns whether f is called and any errors during the locking process. // Cursor provided to f becomes invalid as soon as f returns. @@ -58,7 +60,7 @@ func (s storeAdapter) List() ([]int, error) { } // NewMulti returns an instance of the multi-file store. -func NewMulti(msg message.Msg, prefix *check.Absolute) Store { +func NewMulti(msg message.Msg, prefix *check.Absolute) Compat { return storeAdapter{msg, newStore(prefix.Append("state"))} } @@ -128,3 +130,57 @@ func (h *storeHandle) Len() (int, error) { } return n, err } + +var ( + ErrDuplicate = errors.New("store contains duplicates") +) + +// Joiner is the interface that wraps the Join method. +// +// The Join function uses Joiner if available. +type Joiner interface { + Join() (map[hst.ID]*hst.State, error) +} + +// Join returns joined state entries of all active identities. +func Join(s Compat) (map[hst.ID]*hst.State, error) { + if j, ok := s.(Joiner); ok { + return j.Join() + } + + var ( + aids []int + entries = make(map[hst.ID]*hst.State) + + el int + res map[hst.ID]*hst.State + loadErr error + ) + + if ln, err := s.List(); err != nil { + return nil, err + } else { + aids = ln + } + + for _, aid := range aids { + if _, err := s.Do(aid, func(c Cursor) { + res, loadErr = c.Load() + }); err != nil { + return nil, err + } + + if loadErr != nil { + return nil, loadErr + } + + // save expected length + el = len(entries) + len(res) + maps.Copy(entries, res) + if len(entries) != el { + return nil, ErrDuplicate + } + } + + return entries, nil +} diff --git a/internal/store/join.go b/internal/store/join.go deleted file mode 100644 index 0bb69df..0000000 --- a/internal/store/join.go +++ /dev/null @@ -1,64 +0,0 @@ -package store - -import ( - "errors" - "maps" - - "hakurei.app/hst" -) - -var ( - ErrDuplicate = errors.New("store contains duplicates") -) - -/* -Joiner is the interface that wraps the Join method. - -The Join function uses Joiner if available. -*/ -type Joiner interface { - Join() (map[hst.ID]*hst.State, error) -} - -// Join returns joined state entries of all active identities. -func Join(s Store) (map[hst.ID]*hst.State, error) { - if j, ok := s.(Joiner); ok { - return j.Join() - } - - var ( - aids []int - entries = make(map[hst.ID]*hst.State) - - el int - res map[hst.ID]*hst.State - loadErr error - ) - - if ln, err := s.List(); err != nil { - return nil, err - } else { - aids = ln - } - - for _, aid := range aids { - if _, err := s.Do(aid, func(c Cursor) { - res, loadErr = c.Load() - }); err != nil { - return nil, err - } - - if loadErr != nil { - return nil, loadErr - } - - // save expected length - el = len(entries) + len(res) - maps.Copy(entries, res) - if len(entries) != el { - return nil, ErrDuplicate - } - } - - return entries, nil -}