From 898b5aed3d64fb30b63c0c84a60308c1ec0746f8 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 2 Nov 2025 14:19:45 +0900 Subject: internal/store: iterator over all entries This is quite convenient for searching the store or printing active instance information. Signed-off-by: Ophestra --- internal/store/store.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'internal/store/store.go') diff --git a/internal/store/store.go b/internal/store/store.go index 3e8367e8..7475c211 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -126,7 +126,7 @@ func (s *Store) Segments() (iter.Seq[SegmentIdentity], int, error) { } // this should never happen - si.Err = &hst.AppError{Step: step, Err: syscall.EISDIR, + si.Err = &hst.AppError{Step: step, Err: syscall.ENOTDIR, Msg: "skipped non-directory entry " + strconv.Quote(ent.Name())} goto out } @@ -152,6 +152,50 @@ func (s *Store) Segments() (iter.Seq[SegmentIdentity], int, error) { }, l, nil } +// All returns a non-reusable iterator over all [EntryHandle] known to this [Store]. +// Callers must call copyError after completing iteration and handle the error accordingly. +// A non-nil error returned by copyError is of type [hst.AppError]. +func (s *Store) All() (entries iter.Seq[*EntryHandle], copyError func() error) { + var savedErr error + return func(yield func(*EntryHandle) bool) { + var segments iter.Seq[SegmentIdentity] + segments, _, savedErr = s.Segments() + if savedErr != nil { + return + } + + for si := range segments { + if savedErr = si.Err; savedErr != nil { + return + } + + var handle *Handle + if handle, savedErr = s.Handle(si.Identity); savedErr != nil { + return // not reached + } + + var unlock func() + if unlock, savedErr = handle.Lock(); savedErr != nil { + return + } + + var segmentEntries iter.Seq[*EntryHandle] + if segmentEntries, _, savedErr = handle.Entries(); savedErr != nil { + unlock() + return // not reached: lock has succeeded + } + + for eh := range segmentEntries { + if !yield(eh) { + unlock() + return + } + } + unlock() + } + }, func() error { return savedErr } +} + // New returns the address of a new instance of [Store]. // Multiple instances of [Store] rooted in the same directory is possible, but unsupported. func New(base *check.Absolute) *Store { -- cgit v1.3.1