From 149bc3671a499cce0b5719d7396355fabfa7fc2a Mon Sep 17 00:00:00 2001 From: Ophestra Date: Mon, 3 Nov 2025 01:26:01 +0900 Subject: [PATCH] internal/store: remove compat adapter This is no longer used as everything has been migrated. Signed-off-by: Ophestra --- internal/store/compat.go | 186 ---------------------------------- internal/store/compat_test.go | 120 ---------------------- 2 files changed, 306 deletions(-) delete mode 100644 internal/store/compat.go delete mode 100644 internal/store/compat_test.go diff --git a/internal/store/compat.go b/internal/store/compat.go deleted file mode 100644 index c0d4057..0000000 --- a/internal/store/compat.go +++ /dev/null @@ -1,186 +0,0 @@ -package store - -import ( - "errors" - "maps" - - "hakurei.app/container/check" - "hakurei.app/hst" - "hakurei.app/message" -) - -/* this provides an implementation of Store on top of the improved state tracking to ease in the changes */ - -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. - Do(identity int, f func(c Cursor)) (ok bool, err error) - - // List queries the store and returns a list of identities known to the store. - // Note that some or all returned identities might not have any active apps. - List() (identities []int, err error) -} - -// storeAdapter satisfies [Compat] via [Store]. -type storeAdapter struct { - msg message.Msg - *Store -} - -func (s storeAdapter) Do(identity int, f func(c Cursor)) (bool, error) { - if h, err := s.Handle(identity); err != nil { - return false, err - } else { - return handleAdapter{h}.do(f) - } -} - -func (s storeAdapter) List() ([]int, error) { - segments, n, err := s.Segments() - if err != nil { - return nil, err - } - - identities := make([]int, 0, n) - for si := range segments { - if si.Err != nil { - if m, ok := message.GetMessage(err); ok { - s.msg.Verbose(m) - } else { - // unreachable - return nil, err - } - continue - } - identities = append(identities, si.Identity) - } - return identities, nil -} - -// NewMulti returns an instance of the multi-file store. -func NewMulti(msg message.Msg, prefix *check.Absolute) Compat { - return storeAdapter{msg, New(prefix.Append("state"))} -} - -// Cursor provides access to the store of an identity. -type Cursor interface { - Save(state *hst.State) error - Destroy(id hst.ID) error - Load() (map[hst.ID]*hst.State, error) - Len() (int, error) -} - -// handleAdapter satisfies [Cursor] via [Handle]. -type handleAdapter struct{ *Handle } - -// do implements [Compat.Do] on [Handle]. -func (h handleAdapter) do(f func(c Cursor)) (bool, error) { - if unlock, err := h.Lock(); err != nil { - return false, err - } else { - defer unlock() - } - - f(h) - return true, nil -} - -/* these compatibility methods must only be called while fileMu is held */ - -func (h handleAdapter) Save(state *hst.State) error { _, err := h.Handle.Save(state); return err } - -func (h handleAdapter) Destroy(id hst.ID) error { - return (&EntryHandle{nil, h.Path.Append(id.String()), id}).Destroy() -} - -func (h handleAdapter) Load() (map[hst.ID]*hst.State, error) { - entries, n, err := h.Entries() - if err != nil { - return nil, err - } - - r := make(map[hst.ID]*hst.State, n) - for eh := range entries { - if eh.DecodeErr != nil { - err = eh.DecodeErr - break - } - var s hst.State - if _, err = eh.Load(&s); err != nil { - break - } - r[eh.ID] = &s - } - return r, err -} - -func (h handleAdapter) Len() (int, error) { - entries, _, err := h.Entries() - if err != nil { - return -1, err - } - - var n int - for eh := range entries { - if eh.DecodeErr != nil { - err = eh.DecodeErr - } - n++ - } - 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/compat_test.go b/internal/store/compat_test.go deleted file mode 100644 index c8e7fa4..0000000 --- a/internal/store/compat_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package store_test - -import ( - "log" - "math/rand" - "reflect" - "slices" - "testing" - "time" - - "hakurei.app/container/check" - "hakurei.app/hst" - "hakurei.app/internal/store" - "hakurei.app/message" -) - -func TestMulti(t *testing.T) { - s := store.NewMulti(message.NewMsg(log.New(log.Writer(), "multi: ", 0)), check.MustAbs(t.TempDir())) - - t.Run("list empty store", func(t *testing.T) { - if identities, err := s.List(); err != nil { - t.Fatalf("List: error = %v", err) - } else if len(identities) != 0 { - t.Fatalf("List: identities = %#v", identities) - } - }) - - const ( - insertEntryChecked = iota - insertEntryNoCheck - insertEntryOtherApp - - tl - ) - - var tc [tl]hst.State - for i := 0; i < tl; i++ { - if err := hst.NewInstanceID(&tc[i].ID); err != nil { - t.Fatalf("cannot create dummy state: %v", err) - } - tc[i].PID = rand.Int() - tc[i].Config = hst.Template() - tc[i].Time = time.Now() - } - - do := func(identity int, f func(c store.Cursor)) { - if ok, err := s.Do(identity, f); err != nil { - t.Fatalf("Do: ok = %v, error = %v", ok, err) - } - } - - insert := func(i, identity int) { - do(identity, func(c store.Cursor) { - if err := c.Save(&tc[i]); err != nil { - t.Fatalf("Save: error = %v", err) - } - }) - } - - check := func(i, identity int) { - do(identity, func(c store.Cursor) { - if entries, err := c.Load(); err != nil { - t.Fatalf("Load: error = %v", err) - } else if got, ok := entries[tc[i].ID]; !ok { - t.Fatalf("Load: entry %s missing", &tc[i].ID) - } else { - got.Time = tc[i].Time - if !reflect.DeepEqual(got, &tc[i]) { - t.Fatalf("Load: entry %s got %#v, want %#v", &tc[i].ID, got, &tc[i]) - } - } - }) - } - - // insert entry checked - insert(insertEntryChecked, 0) - check(insertEntryChecked, 0) - - // insert entry unchecked - insert(insertEntryNoCheck, 0) - - // insert entry different identity - insert(insertEntryOtherApp, 1) - check(insertEntryOtherApp, 1) - - // check previous insertion - check(insertEntryNoCheck, 0) - - // list identities - if identities, err := s.List(); err != nil { - t.Fatalf("List: error = %v", err) - } else { - slices.Sort(identities) - want := []int{0, 1} - if !slices.Equal(identities, want) { - t.Fatalf("List() = %#v, want %#v", identities, want) - } - } - - // join store - if entries, err := store.Join(s); err != nil { - t.Fatalf("Join: error = %v", err) - } else if len(entries) != 3 { - t.Fatalf("Join(s) = %#v", entries) - } - - // clear identity 1 - do(1, func(c store.Cursor) { - if err := c.Destroy(tc[insertEntryOtherApp].ID); err != nil { - t.Fatalf("Destroy: error = %v", err) - } - }) - do(1, func(c store.Cursor) { - if l, err := c.Len(); err != nil { - t.Fatalf("Len: error = %v", err) - } else if l != 0 { - t.Fatalf("Len: %d, want 0", l) - } - }) -}