mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-28 17:09:30 -05:00
52 lines
1.2 KiB
Go
52 lines
1.2 KiB
Go
|
package state
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sync/atomic"
|
||
|
)
|
||
|
|
||
|
//go:generate stringer -type=State
|
||
|
|
||
|
// State is a peer's state.
|
||
|
//
|
||
|
// State's methods are thread safe. Get the State's value using the Get method if
|
||
|
// you're accessing it concurrently. Otherwise, you may access it directly.
|
||
|
type State uint32
|
||
|
|
||
|
const (
|
||
|
Uninitialized State = iota
|
||
|
AcceptingInit
|
||
|
ActivatingNodes
|
||
|
NodeWaitingForClusterJoin
|
||
|
IsNode
|
||
|
Failed
|
||
|
maxState
|
||
|
)
|
||
|
|
||
|
// State's methods should be thread safe. As we only need to protect
|
||
|
// one primitive value, we can use atomic operations.
|
||
|
|
||
|
// Get gets the state in a thread-safe manner.
|
||
|
func (s *State) Get() State {
|
||
|
return State(atomic.LoadUint32((*uint32)(s)))
|
||
|
}
|
||
|
|
||
|
// Require checks if the state is one of the desired ones and returns an error otherwise.
|
||
|
func (s *State) Require(states ...State) error {
|
||
|
this := s.Get()
|
||
|
for _, st := range states {
|
||
|
if st == this {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
return fmt.Errorf("server is not in expected state: require one of %v, but this is %v", states, this)
|
||
|
}
|
||
|
|
||
|
// Advance advances the state.
|
||
|
func (s *State) Advance(newState State) {
|
||
|
curState := State(atomic.SwapUint32((*uint32)(s), uint32(newState)))
|
||
|
if !(curState < newState && newState < maxState) {
|
||
|
panic(fmt.Errorf("cannot advance from %v to %v", curState, newState))
|
||
|
}
|
||
|
}
|