diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-10-30 18:43:55 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-10-30 18:43:55 +0900 |
| commit | ebdcff1049fb979405677a823a47410df7ee7c4f (patch) | |
| tree | a5a14d409e4bc9f3b4b2e2c15f6c23de5ad0755f /internal/state/segment.go | |
| parent | 46c5ce493638ea2d034bbbdb9449e93b66d0330f (diff) | |
internal/store: rename from state
This reduces collision with local variable names, and generally makes sense for the new store package, since it no longer specifies the state struct.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/state/segment.go')
| -rw-r--r-- | internal/state/segment.go | 161 |
1 files changed, 0 insertions, 161 deletions
diff --git a/internal/state/segment.go b/internal/state/segment.go deleted file mode 100644 index c8ab8c13..00000000 --- a/internal/state/segment.go +++ /dev/null @@ -1,161 +0,0 @@ -package state - -import ( - "errors" - "fmt" - "iter" - "os" - "strconv" - "sync" - - "hakurei.app/container/check" - "hakurei.app/hst" - "hakurei.app/internal/lockedfile" -) - -// stateEntryHandle is a handle on a state entry retrieved from a storeHandle. -// Must only be used while its parent storeHandle.fileMu is held. -type stateEntryHandle struct { - // Error returned while decoding pathname. - // A non-nil value disables stateEntryHandle. - decodeErr error - - // Checked path to entry file. - pathname *check.Absolute - - hst.ID -} - -// open opens the underlying state entry file, returning [hst.AppError] for a non-nil error. -func (eh *stateEntryHandle) open(flag int, perm os.FileMode) (*os.File, error) { - if eh.decodeErr != nil { - return nil, eh.decodeErr - } - - if f, err := os.OpenFile(eh.pathname.String(), flag, perm); err != nil { - return nil, &hst.AppError{Step: "open state entry", Err: err} - } else { - return f, nil - } -} - -// destroy removes the underlying state entry file, returning [hst.AppError] for a non-nil error. -func (eh *stateEntryHandle) destroy() error { - // destroy does not go through open - if eh.decodeErr != nil { - return eh.decodeErr - } - - if err := os.Remove(eh.pathname.String()); err != nil { - return &hst.AppError{Step: "destroy state entry", Err: err} - } - return nil -} - -// save encodes [hst.State] and writes it to the underlying file. -// An error is returned if a file already exists with the same identifier. -// save does not validate the embedded [hst.Config]. -func (eh *stateEntryHandle) save(state *hst.State) error { - f, err := eh.open(os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if err != nil { - return err - } - - err = entryEncode(f, state) - if closeErr := f.Close(); closeErr != nil && err == nil { - err = &hst.AppError{Step: "close state file", Err: closeErr} - } - return err -} - -// load loads and validates the state entry header, and returns the [hst.Enablement] byte. -// for a non-nil v, the full state payload is decoded and stored in the value pointed to by v. -// load validates the embedded hst.Config value. -func (eh *stateEntryHandle) load(v *hst.State) (hst.Enablement, error) { - f, err := eh.open(os.O_RDONLY, 0) - if err != nil { - return 0, err - } - - var et hst.Enablement - 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())} - } - } else { - et, err = entryDecodeHeader(f) - } - - if closeErr := f.Close(); closeErr != nil && err == nil { - err = &hst.AppError{Step: "close state file", Err: closeErr} - } - return et, err -} - -// storeHandle is a handle on a stateStore segment. -// Initialised by stateStore.identityHandle. -type storeHandle struct { - // Identity of instances tracked by this segment. - identity int - // Pathname of directory that the segment referred to by storeHandle is rooted in. - path *check.Absolute - // Inter-process mutex to synchronise operations against resources in this segment. - fileMu *lockedfile.Mutex - - // Must be held alongside fileMu. - mu sync.Mutex -} - -// entries returns an iterator over all stateEntryHandle held in this segment. -// Must be called while holding a lock on mu and fileMu. -// A non-nil error attached to a stateEntryHandle indicates a malformed identifier and is of type [hst.AppError]. -// A non-nil error returned by entries is of type [hst.AppError]. -func (h *storeHandle) entries() (iter.Seq[*stateEntryHandle], int, error) { - // for error reporting - const step = "read store segment entries" - - // read directory contents, should only contain storeMutexName and identifier - var entries []os.DirEntry - if pl, err := os.ReadDir(h.path.String()); err != nil { - return nil, -1, &hst.AppError{Step: step, Err: err} - } else { - entries = pl - } - - // expects lock file - l := len(entries) - if l > 0 { - l-- - } - - return func(yield func(*stateEntryHandle) bool) { - for _, ent := range entries { - var eh = stateEntryHandle{pathname: h.path.Append(ent.Name())} - - // this should never happen - if ent.IsDir() { - eh.decodeErr = &hst.AppError{Step: step, - Err: errors.New("unexpected directory " + strconv.Quote(ent.Name()) + " in store")} - goto out - } - - // silently skip lock file - if ent.Name() == storeMutexName { - continue - } - - // 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} - goto out - } - - out: - if !yield(&eh) { - break - } - } - }, l, nil -} |
