package hostfloor import ( "encoding/json" "os" "path/filepath" ) // Begun is root's update-begun marker for a floor transaction. Begin writes // it with the reservation ID before the first box-changing step. RolledBack // is set by the backward paths before the journal is removed, so completion // can tell a finished rollback from a transaction that never changed the box // (Opus re-review M1-4). type Begun struct { ID string `json:"id"` RolledBack bool `json:"rolled_back,omitempty"` } // ReadBegun reads the marker in dir. An absent marker is os.ErrNotExist; one // that does not decode or names no transaction is ErrFloor. func ReadBegun(dir string) (Begun, error) { raw, err := os.ReadFile(filepath.Join(dir, "update-begun.json")) if err != nil { return Begun{}, err } var b Begun if json.Unmarshal(raw, &b) != nil || b.ID == "" { return Begun{}, ErrFloor } return b, nil } // MarkRolledBack records durably that transaction id rolled back. It never // creates a marker: an absent one is os.ErrNotExist, and a marker for any // other transaction is ErrFloor and is left as it is. func MarkRolledBack(dir, id string) error { b, err := ReadBegun(dir) if err != nil { return err } if b.ID != id { return ErrFloor } if b.RolledBack { return nil } b.RolledBack = true raw, err := json.Marshal(b) if err != nil { return err } return Durable(filepath.Join(dir, "update-begun.json"), raw, 0644) }