aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-08-30 12:59:20 +0900
committerOphestra <cat@gensokyo.uk>2026-08-30 12:59:20 +0900
commitd4fab811d3857c36f1d8271a940ffca113e012b7 (patch)
tree6a3acb3f64d6b74669a3049754313394bc0e7599
parentc2d900ec74e03e9c782cfe7b7ce06ff62cda6601 (diff)
internal/store: improve doc comments
This improves readability on narrow 3:2 display. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--internal/store/data.go10
-rw-r--r--internal/store/header.go3
-rw-r--r--internal/store/segment.go27
-rw-r--r--internal/store/store.go79
4 files changed, 86 insertions, 33 deletions
diff --git a/internal/store/data.go b/internal/store/data.go
index 34a0f261..380481a0 100644
--- a/internal/store/data.go
+++ b/internal/store/data.go
@@ -23,7 +23,8 @@ func entryEncode(w io.Writer, s *hst.State) error {
}
}
-// entryDecodeHeader calls entryReadHeader, returning [hst.AppError] for a non-nil error.
+// entryDecodeHeader calls entryReadHeader, returning [hst.AppError] for a
+// non-nil error.
func entryDecodeHeader(r io.Reader) (hst.Enablements, error) {
if et, err := entryReadHeader(r); err != nil {
return 0, &hst.AppError{Step: "decode state header", Err: err}
@@ -44,11 +45,14 @@ func entryDecode(r io.Reader, p *hst.State) (hst.Enablements, error) {
} else if err = p.Config.Validate(hst.VAllowInsecure); err != nil {
return et, err
} else if p.Enablements.Unwrap() != et {
- return et, &hst.AppError{Step: "validate state enablement", Err: os.ErrInvalid,
+ return et, &hst.AppError{
+ Step: "validate state enablement",
+ Err: os.ErrInvalid,
Msg: fmt.Sprintf(
"state entry %s has unexpected enablement byte %#x, %#x",
p.ID.String(), byte(p.Enablements.Unwrap()), byte(et),
- )}
+ ),
+ }
} else {
return et, nil
}
diff --git a/internal/store/header.go b/internal/store/header.go
index 5b5d73be..0e5a92a2 100644
--- a/internal/store/header.go
+++ b/internal/store/header.go
@@ -60,7 +60,8 @@ func (e *EntrySizeError) Error() string {
return "state entry file " + strconv.Quote(e.Name) + " is too short"
}
-// entryCheckFile checks whether [os.FileInfo] refers to a file that might hold [hst.State].
+// entryCheckFile checks whether [os.FileInfo] refers to a file that might hold
+// [hst.State].
func entryCheckFile(fi os.FileInfo) error {
if fi.IsDir() {
return syscall.EISDIR
diff --git a/internal/store/segment.go b/internal/store/segment.go
index 06849749..32c8a141 100644
--- a/internal/store/segment.go
+++ b/internal/store/segment.go
@@ -92,8 +92,14 @@ func (eh *EntryHandle) Load(v *hst.State) (hst.Enablements, error) {
if v != nil {
et, err = entryDecode(f, v)
if err == nil && v.ID != eh.ID {
- err = &hst.AppError{Step: "validate state identifier", Err: os.ErrInvalid,
- Msg: fmt.Sprintf("state entry %s has unexpected id %s", eh.ID.String(), v.ID.String())}
+ err = &hst.AppError{
+ Step: "validate state identifier",
+ Err: os.ErrInvalid,
+ Msg: fmt.Sprintf(
+ "state entry %s has unexpected id %s",
+ eh.ID.String(), v.ID.String(),
+ ),
+ }
}
} else {
et, err = entryDecodeHeader(f)
@@ -127,7 +133,10 @@ type Handle struct {
// A non-nil error returned by Lock is of type [hst.AppError].
func (h *Handle) Lock() (unlock func(), err error) {
if unlock, err = h.fileMu.Lock(); err != nil {
- return nil, &hst.AppError{Step: "acquire lock on store segment " + strconv.Itoa(h.Identity), Err: err}
+ return nil, &hst.AppError{
+ Step: "acquire lock on store segment " + strconv.Itoa(h.Identity),
+ Err: err,
+ }
}
return
}
@@ -174,8 +183,11 @@ func (h *Handle) Entries() (iter.Seq[*EntryHandle], int, error) {
// this should never happen
if ent.IsDir() {
- eh.DecodeErr = &hst.AppError{Step: step,
- Err: errors.New("unexpected directory " + strconv.Quote(ent.Name()) + " in store")}
+ eh.DecodeErr = &hst.AppError{
+ Step: step,
+ Err: errors.New("unexpected directory " +
+ strconv.Quote(ent.Name()) + " in store"),
+ }
goto out
}
@@ -186,7 +198,10 @@ func (h *Handle) Entries() (iter.Seq[*EntryHandle], int, error) {
// this either indicates a serious bug or external interference
if err := eh.ID.UnmarshalText([]byte(ent.Name())); err != nil {
- eh.DecodeErr = &hst.AppError{Step: "decode store segment entry", Err: err}
+ eh.DecodeErr = &hst.AppError{
+ Step: "decode store segment entry",
+ Err: err,
+ }
goto out
}
diff --git a/internal/store/store.go b/internal/store/store.go
index 3604521c..4383d55f 100644
--- a/internal/store/store.go
+++ b/internal/store/store.go
@@ -1,4 +1,5 @@
-// Package store implements cross-process state tracking for hakurei container instances.
+// Package store provides storage for hakurei instance states, safe for
+// concurrent and cross-process use.
package store
import (
@@ -15,11 +16,15 @@ import (
"hakurei.app/internal/lockedfile"
)
-// MutexName is the pathname of the file backing [lockedfile.Mutex] of a [Store] and [Handle].
+// MutexName is the pathname of the file backing [lockedfile.Mutex] of a [Store]
+// and [Handle].
const MutexName = "lock"
-// A Store keeps track of [hst.State] via a well-known filesystem accessible to all hakurei priv-side processes.
-// Access to store data and related resources are synchronised on a per-segment basis via [Handle].
+// A Store keeps track of [hst.State] via a well-known filesystem accessible to
+// all hakurei priv-side processes.
+//
+// Access to store data and related resources are synchronised on a per-segment
+// basis via [Handle].
type Store struct {
// Pathname of directory that the store is rooted in.
base *check.Absolute
@@ -28,8 +33,10 @@ type Store struct {
handles sync.Map
// Inter-process mutex to synchronise operations against the entire store.
- // Held during List and when initialising previously unknown identities during Do.
- // Must not be accessed directly. Callers should use the bigLock method instead.
+ //
+ // Held during List and when initialising previously unknown identities
+ // during Do. Must not be accessed directly. Callers should use the bigLock
+ // method instead.
fileMu *lockedfile.Mutex
// For creating the base directory.
@@ -43,11 +50,17 @@ type Store struct {
func (s *Store) bigLock() (unlock func(), err error) {
s.mkdirOnce.Do(func() { s.mkdirErr = os.MkdirAll(s.base.String(), 0700) })
if s.mkdirErr != nil {
- return nil, &hst.AppError{Step: "create state store directory", Err: s.mkdirErr}
+ return nil, &hst.AppError{
+ Step: "create state store directory",
+ Err: s.mkdirErr,
+ }
}
if unlock, err = s.fileMu.Lock(); err != nil {
- return nil, &hst.AppError{Step: "acquire lock on the state store", Err: err}
+ return nil, &hst.AppError{
+ Step: "acquire lock on the state store",
+ Err: err,
+ }
}
return
}
@@ -73,7 +86,10 @@ func (s *Store) Handle(identity int) (*Handle, error) {
if err != nil && !errors.Is(err, fs.ErrExist) {
// handle methods will likely return ENOENT
s.handles.CompareAndDelete(identity, h)
- return nil, &hst.AppError{Step: "create store segment directory", Err: err}
+ return nil, &hst.AppError{
+ Step: "create store segment directory",
+ Err: err,
+ }
}
}
return h, nil
@@ -88,8 +104,9 @@ type SegmentIdentity struct {
}
// Segments returns an iterator over all [SegmentIdentity] known to the [Store].
-// To obtain a [Handle] on a segment, caller must then call [Store.Handle].
-// A non-nil error returned by segments is of type [hst.AppError].
+//
+// To obtain a [Handle] on a segment, caller must then call [Store.Handle]. A
+// non-nil error returned by segments is of type [hst.AppError].
func (s *Store) Segments() (iter.Seq[SegmentIdentity], int, error) {
// read directory contents, should only contain storeMutexName and identity
var entries []os.DirEntry
@@ -102,7 +119,10 @@ func (s *Store) Segments() (iter.Seq[SegmentIdentity], int, error) {
unlock()
if err != nil && !errors.Is(err, os.ErrNotExist) {
- return nil, -1, &hst.AppError{Step: "read store segments", Err: err}
+ return nil, -1, &hst.AppError{
+ Step: "read store segments",
+ Err: err,
+ }
}
}
@@ -126,19 +146,25 @@ func (s *Store) Segments() (iter.Seq[SegmentIdentity], int, error) {
}
// this should never happen
- si.Err = &hst.AppError{Step: step, Err: syscall.ENOTDIR,
- Msg: "skipped non-directory entry " + strconv.Quote(ent.Name())}
+ si.Err = &hst.AppError{
+ Step: step, Err: syscall.ENOTDIR,
+ Msg: "skipped non-directory entry " + strconv.Quote(ent.Name()),
+ }
goto out
}
// failure paths either indicates a serious bug or external interference
if v, err := strconv.Atoi(ent.Name()); err != nil {
- si.Err = &hst.AppError{Step: step, Err: err,
- Msg: "skipped non-identity entry " + strconv.Quote(ent.Name())}
+ si.Err = &hst.AppError{
+ Step: step, Err: err,
+ Msg: "skipped non-identity entry " + strconv.Quote(ent.Name()),
+ }
goto out
} else if v < hst.IdentityStart || v > hst.IdentityEnd {
- si.Err = &hst.AppError{Step: step, Err: syscall.ERANGE,
- Msg: "skipped out of bounds entry " + strconv.Itoa(v)}
+ si.Err = &hst.AppError{
+ Step: step, Err: syscall.ERANGE,
+ Msg: "skipped out of bounds entry " + strconv.Itoa(v),
+ }
goto out
} else {
si.Identity = v
@@ -152,9 +178,11 @@ 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].
+// 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) {
@@ -197,7 +225,12 @@ func (s *Store) All() (entries iter.Seq[*EntryHandle], copyError func() error) {
}
// New returns the address of a new instance of [Store].
-// Multiple instances of [Store] rooted in the same directory is possible, but unsupported.
+//
+// Multiple instances of [Store] rooted in the same directory is possible, but
+// unsupported.
func New(base *check.Absolute) *Store {
- return &Store{base: base, fileMu: lockedfile.MutexAt(base.Append(MutexName).String())}
+ return &Store{
+ base: base,
+ fileMu: lockedfile.MutexAt(base.Append(MutexName).String()),
+ }
}