diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-11-02 14:19:45 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-11-02 15:54:00 +0900 |
| commit | 898b5aed3d64fb30b63c0c84a60308c1ec0746f8 (patch) | |
| tree | 9d9252e11c7f3ff7be38c557dcb2dcc71adce5e7 /internal/store/store.go | |
| parent | 7c3c3135d8b0eab767e58bd8ef0e7e04abee3ca2 (diff) | |
internal/store: iterator over all entries
This is quite convenient for searching the store or printing active instance information.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/store/store.go')
| -rw-r--r-- | internal/store/store.go | 46 |
1 files changed, 45 insertions, 1 deletions
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 { |
