statemachine: Better naming
This commit is contained in:
parent
2fea9433d8
commit
2ef8c1ae0c
@ -10,7 +10,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/evtsm"
|
||||
"github.com/filecoin-project/lotus/lib/statemachine"
|
||||
"github.com/filecoin-project/lotus/paych"
|
||||
"github.com/filecoin-project/lotus/storage"
|
||||
)
|
||||
@ -133,9 +133,9 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = gen.WriteMapEncodersToFile("./lib/evtsm/cbor_gen.go", "evtsm",
|
||||
evtsm.TestState{},
|
||||
evtsm.TestEvent{},
|
||||
err = gen.WriteMapEncodersToFile("./lib/statemachine/cbor_gen.go", "statemachine",
|
||||
statemachine.TestState{},
|
||||
statemachine.TestEvent{},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("%+v\n", err)
|
||||
|
@ -1,5 +0,0 @@
|
||||
package evtsm
|
||||
|
||||
type Event struct {
|
||||
User interface{}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
import "context"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -15,43 +15,49 @@ type StateHandler interface {
|
||||
Plan(events []Event, user interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
type Sched struct {
|
||||
// StateGroup manages a group of state machines sharing the same logic
|
||||
type StateGroup struct {
|
||||
sts *statestore.StateStore
|
||||
hnd StateHandler
|
||||
stateType reflect.Type
|
||||
|
||||
lk sync.Mutex
|
||||
sms map[datastore.Key]*ESm
|
||||
sms map[datastore.Key]*StateMachine
|
||||
}
|
||||
|
||||
// stateType: T - (reflect.TypeOf(MyStateStruct{}))
|
||||
func New(ds datastore.Datastore, hnd StateHandler, stateType reflect.Type) *Sched {
|
||||
return &Sched{
|
||||
func New(ds datastore.Datastore, hnd StateHandler, stateType reflect.Type) *StateGroup {
|
||||
return &StateGroup{
|
||||
sts: statestore.New(ds),
|
||||
hnd: hnd,
|
||||
stateType: stateType,
|
||||
|
||||
sms: map[datastore.Key]*ESm{},
|
||||
sms: map[datastore.Key]*StateMachine{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Sched) Send(to interface{}, evt interface{}) (err error) {
|
||||
// Send sends an event to machine identified by `id`.
|
||||
// `evt` is going to be passed into StateHandler.Planner, in the events[].User param
|
||||
//
|
||||
// If a state machine with the specified id doesn't exits, it's created, and it's
|
||||
// state is set to zero-value of stateType provided in group constructor
|
||||
func (s *StateGroup) Send(id interface{}, evt interface{}) (err error) {
|
||||
s.lk.Lock()
|
||||
defer s.lk.Unlock()
|
||||
|
||||
sm, exist := s.sms[statestore.ToKey(to)]
|
||||
sm, exist := s.sms[statestore.ToKey(id)]
|
||||
if !exist {
|
||||
sm, err = s.loadOrCreate(to)
|
||||
sm, err = s.loadOrCreate(id)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("loadOrCreate state: %w", err)
|
||||
}
|
||||
s.sms[statestore.ToKey(to)] = sm
|
||||
s.sms[statestore.ToKey(id)] = sm
|
||||
}
|
||||
|
||||
return sm.send(Event{User: evt})
|
||||
}
|
||||
|
||||
func (s *Sched) loadOrCreate(name interface{}) (*ESm, error) {
|
||||
func (s *StateGroup) loadOrCreate(name interface{}) (*StateMachine, error) {
|
||||
exists, err := s.sts.Has(name)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to check if state for %v exists: %w", name, err)
|
||||
@ -66,7 +72,7 @@ func (s *Sched) loadOrCreate(name interface{}) (*ESm, error) {
|
||||
}
|
||||
}
|
||||
|
||||
res := &ESm{
|
||||
res := &StateMachine{
|
||||
planner: s.hnd.Plan,
|
||||
eventsIn: make(chan Event),
|
||||
|
||||
@ -84,7 +90,8 @@ func (s *Sched) loadOrCreate(name interface{}) (*ESm, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Sched) Stop(ctx context.Context) error {
|
||||
// Stop stops all state machines in this group
|
||||
func (s *StateGroup) Stop(ctx context.Context) error {
|
||||
s.lk.Lock()
|
||||
defer s.lk.Unlock()
|
||||
|
||||
@ -97,10 +104,13 @@ func (s *Sched) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Sched) List(out interface{}) error {
|
||||
// List outputs states of all state machines in this group
|
||||
// out: *[]StateT
|
||||
func (s *StateGroup) List(out interface{}) error {
|
||||
return s.sts.List(out)
|
||||
}
|
||||
|
||||
func (s *Sched) Get(i interface{}) *statestore.StoredState {
|
||||
return s.sts.Get(i)
|
||||
// Get gets state for a single state machine
|
||||
func (s *StateGroup) Get(id interface{}) *statestore.StoredState {
|
||||
return s.sts.Get(id)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -12,10 +12,14 @@ import (
|
||||
|
||||
var log = logging.Logger("evtsm")
|
||||
|
||||
type Event struct {
|
||||
User interface{}
|
||||
}
|
||||
|
||||
// returns func(ctx Context, st <T>) (func(*<T>), error), where <T> is the typeOf(User) param
|
||||
type Planner func(events []Event, user interface{}) (interface{}, error)
|
||||
|
||||
type ESm struct {
|
||||
type StateMachine struct {
|
||||
planner Planner
|
||||
eventsIn chan Event
|
||||
|
||||
@ -30,7 +34,7 @@ type ESm struct {
|
||||
busy int32
|
||||
}
|
||||
|
||||
func (fsm *ESm) run() {
|
||||
func (fsm *StateMachine) run() {
|
||||
defer close(fsm.closed)
|
||||
|
||||
var pendingEvents []Event
|
||||
@ -93,7 +97,7 @@ func (fsm *ESm) run() {
|
||||
}
|
||||
}
|
||||
|
||||
func (fsm *ESm) mutateUser(cb func(user interface{}) error) error {
|
||||
func (fsm *StateMachine) mutateUser(cb func(user interface{}) error) error {
|
||||
mutt := reflect.FuncOf([]reflect.Type{reflect.PtrTo(fsm.stateType)}, []reflect.Type{reflect.TypeOf(new(error)).Elem()}, false)
|
||||
|
||||
mutf := reflect.MakeFunc(mutt, func(args []reflect.Value) (results []reflect.Value) {
|
||||
@ -104,12 +108,12 @@ func (fsm *ESm) mutateUser(cb func(user interface{}) error) error {
|
||||
return fsm.st.Mutate(mutf.Interface())
|
||||
}
|
||||
|
||||
func (fsm *ESm) send(evt Event) error {
|
||||
func (fsm *StateMachine) send(evt Event) error {
|
||||
fsm.eventsIn <- evt // TODO: ctx, at least
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fsm *ESm) stop(ctx context.Context) error {
|
||||
func (fsm *StateMachine) stop(ctx context.Context) error {
|
||||
close(fsm.closing)
|
||||
|
||||
select {
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package evtsm
|
||||
package statemachine
|
||||
|
||||
type TestState struct {
|
||||
A uint64
|
@ -22,7 +22,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/evtsm"
|
||||
"github.com/filecoin-project/lotus/lib/statemachine"
|
||||
)
|
||||
|
||||
var log = logging.Logger("storageminer")
|
||||
@ -39,7 +39,7 @@ type Miner struct {
|
||||
|
||||
// Sealing
|
||||
sb SectorBuilder
|
||||
sectors *evtsm.Sched
|
||||
sectors *statemachine.StateGroup
|
||||
tktFn TicketFn
|
||||
|
||||
sectorIncoming chan *SectorInfo
|
||||
@ -104,7 +104,7 @@ func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datasto
|
||||
}
|
||||
|
||||
// TODO: separate sector stuff from miner struct
|
||||
m.sectors = evtsm.New(namespace.Wrap(ds, datastore.NewKey(SectorStorePrefix)), m, reflect.TypeOf(SectorInfo{}))
|
||||
m.sectors = statemachine.New(namespace.Wrap(ds, datastore.NewKey(SectorStorePrefix)), m, reflect.TypeOf(SectorInfo{}))
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/lib/evtsm"
|
||||
"github.com/filecoin-project/lotus/lib/statemachine"
|
||||
)
|
||||
|
||||
type SectorStart struct {
|
||||
@ -53,13 +53,13 @@ type SectorForceState struct {
|
||||
state api.SectorState
|
||||
}
|
||||
|
||||
func (m *Miner) Plan(events []evtsm.Event, user interface{}) (interface{}, error) {
|
||||
func (m *Miner) Plan(events []statemachine.Event, user interface{}) (interface{}, error) {
|
||||
next, err := m.plan(events, user.(*SectorInfo))
|
||||
if err != nil || next == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(ctx evtsm.Context, si SectorInfo) error {
|
||||
return func(ctx statemachine.Context, si SectorInfo) error {
|
||||
err := next(ctx, si)
|
||||
if err != nil {
|
||||
if err := ctx.Send(SectorFatalError{error: err}); err != nil {
|
||||
@ -71,7 +71,7 @@ func (m *Miner) Plan(events []evtsm.Event, user interface{}) (interface{}, error
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Miner) plan(events []evtsm.Event, state *SectorInfo) (func(evtsm.Context, SectorInfo) error, error) {
|
||||
func (m *Miner) plan(events []statemachine.Event, state *SectorInfo) (func(statemachine.Context, SectorInfo) error, error) {
|
||||
/////
|
||||
// First process all events
|
||||
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/evtsm"
|
||||
"github.com/filecoin-project/lotus/lib/statemachine"
|
||||
)
|
||||
|
||||
func (m *Miner) handlePacking(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handlePacking(ctx statemachine.Context, sector SectorInfo) error {
|
||||
log.Infow("performing filling up rest of the sector...", "sector", sector.SectorID)
|
||||
|
||||
var allocated uint64
|
||||
@ -43,7 +43,7 @@ func (m *Miner) handlePacking(ctx evtsm.Context, sector SectorInfo) error {
|
||||
return ctx.Send(SectorPacked{pieces: pieces})
|
||||
}
|
||||
|
||||
func (m *Miner) handleUnsealed(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handleUnsealed(ctx statemachine.Context, sector SectorInfo) error {
|
||||
log.Infow("performing sector replication...", "sector", sector.SectorID)
|
||||
ticket, err := m.tktFn(ctx.Context())
|
||||
if err != nil {
|
||||
@ -65,7 +65,7 @@ func (m *Miner) handleUnsealed(ctx evtsm.Context, sector SectorInfo) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Miner) handlePreCommitting(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handlePreCommitting(ctx statemachine.Context, sector SectorInfo) error {
|
||||
params := &actors.SectorPreCommitInfo{
|
||||
SectorNumber: sector.SectorID,
|
||||
|
||||
@ -97,7 +97,7 @@ func (m *Miner) handlePreCommitting(ctx evtsm.Context, sector SectorInfo) error
|
||||
return ctx.Send(SectorPreCommitted{message: smsg.Cid()})
|
||||
}
|
||||
|
||||
func (m *Miner) handlePreCommitted(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handlePreCommitted(ctx statemachine.Context, sector SectorInfo) error {
|
||||
// would be ideal to just use the events.Called handler, but it wouldnt be able to handle individual message timeouts
|
||||
log.Info("Sector precommitted: ", sector.SectorID)
|
||||
mw, err := m.api.StateWaitMsg(ctx.Context(), *sector.PreCommitMessage)
|
||||
@ -142,7 +142,7 @@ func (m *Miner) handlePreCommitted(ctx evtsm.Context, sector SectorInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Miner) handleCommitting(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handleCommitting(ctx statemachine.Context, sector SectorInfo) error {
|
||||
log.Info("scheduling seal proof computation...")
|
||||
|
||||
proof, err := m.sb.SealCommit(ctx.Context(), sector.SectorID, sector.Ticket.SB(), sector.Seed.SB(), sector.pieceInfos(), sector.rspco())
|
||||
@ -184,7 +184,7 @@ func (m *Miner) handleCommitting(ctx evtsm.Context, sector SectorInfo) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Miner) handleCommitWait(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handleCommitWait(ctx statemachine.Context, sector SectorInfo) error {
|
||||
if sector.CommitMessage == nil {
|
||||
log.Errorf("sector %d entered commit wait state without a message cid", sector.SectorID)
|
||||
return ctx.Send(SectorCommitFailed{xerrors.Errorf("entered commit wait with no commit cid")})
|
||||
@ -203,7 +203,7 @@ func (m *Miner) handleCommitWait(ctx evtsm.Context, sector SectorInfo) error {
|
||||
return ctx.Send(SectorProving{})
|
||||
}
|
||||
|
||||
func (m *Miner) handleFaulty(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handleFaulty(ctx statemachine.Context, sector SectorInfo) error {
|
||||
// TODO: check if the fault has already been reported, and that this sector is even valid
|
||||
|
||||
// TODO: coalesce faulty sector reporting
|
||||
@ -235,7 +235,7 @@ func (m *Miner) handleFaulty(ctx evtsm.Context, sector SectorInfo) error {
|
||||
return ctx.Send(SectorFaultReported{reportMsg: smsg.Cid()})
|
||||
}
|
||||
|
||||
func (m *Miner) handleFaultReported(ctx evtsm.Context, sector SectorInfo) error {
|
||||
func (m *Miner) handleFaultReported(ctx statemachine.Context, sector SectorInfo) error {
|
||||
if sector.FaultReportMsg == nil {
|
||||
return xerrors.Errorf("entered fault reported state without a FaultReportMsg cid")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user