aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/store/store.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-02 14:19:45 +0900
committerOphestra <cat@gensokyo.uk>2025-11-02 15:54:00 +0900
commit898b5aed3d64fb30b63c0c84a60308c1ec0746f8 (patch)
tree9d9252e11c7f3ff7be38c557dcb2dcc71adce5e7 /internal/store/store.go
parent7c3c3135d8b0eab767e58bd8ef0e7e04abee3ca2 (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.go46
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 {