github.com/braveheart12/just@v0.8.7/pulsar/statemachine.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package pulsar 18 19 import ( 20 "context" 21 "sync" 22 23 "github.com/insolar/insolar/instrumentation/inslogger" 24 "github.com/insolar/insolar/instrumentation/instracer" 25 ) 26 27 //go:generate stringer -type=State 28 type State int 29 30 const ( 31 // Failed means that current iteration is broken 32 Failed State = iota 33 34 // WaitingForStart means that state machine is waiting for the start 35 WaitingForStart 36 37 // GenerateEntropy means that state machine is generating entropy for a current slot 38 GenerateEntropy 39 40 // WaitingForEntropySigns means that state machine is waiting for other pulsars' signs of entropy 41 WaitingForEntropySigns 42 43 // SendingEntropy means that state machine is sending entropy to other pulsars 44 SendingEntropy 45 46 // WaitingForEntropy means that state machine is waiting for the entropy for other pulsars 47 WaitingForEntropy 48 49 // SendingVector means that state machine is sending verctor to other pulsars 50 SendingVector 51 52 // WaitingForVectors means that state machine is waiting for other pulsars' vectors 53 WaitingForVectors 54 55 // Verifying means that state machine is verifying bft-table 56 Verifying 57 58 // SendingPulseSign means that state machine is sending sign to chosen pulsar 59 SendingPulseSign 60 61 // WaitingForPulseSigns means that state machine is waiting for signs to chosen pulsar 62 WaitingForPulseSigns 63 64 // SendingPulseSign means that state machine is sending pulse to network 65 SendingPulse 66 ) 67 68 // StateSwitcher is a base for pulsar's state machine 69 type StateSwitcher interface { 70 SwitchToState(ctx context.Context, state State, args interface{}) 71 GetState() State 72 setState(state State) 73 SetPulsar(pulsar *Pulsar) 74 } 75 76 // StateSwitcherImpl is a base implementation of the pulsar's state machine 77 type StateSwitcherImpl struct { 78 pulsar *Pulsar 79 state State 80 lock sync.RWMutex 81 } 82 83 func (switcher *StateSwitcherImpl) GetState() State { 84 switcher.lock.RLock() 85 defer switcher.lock.RUnlock() 86 return switcher.state 87 } 88 89 func (switcher *StateSwitcherImpl) setState(state State) { 90 switcher.lock.Lock() 91 defer switcher.lock.Unlock() 92 switcher.state = state 93 } 94 95 // SetPulsar sets pulsar of the current instance 96 func (switcher *StateSwitcherImpl) SetPulsar(pulsar *Pulsar) { 97 switcher.setState(WaitingForStart) 98 switcher.pulsar = pulsar 99 } 100 101 // SwitchToState switches the state-machine to another step 102 func (switcher *StateSwitcherImpl) SwitchToState(ctx context.Context, state State, args interface{}) { 103 ctx, span := instracer.StartSpan(ctx, "Pulsar.SwitchToState") 104 defer span.End() 105 106 logger := inslogger.FromContext(ctx) 107 logger.Debugf("Switch state from %v to %v, node - %v", switcher.GetState().String(), state.String(), switcher.pulsar.Config.MainListenerAddress) 108 if state < switcher.GetState() && (state != WaitingForStart && state != Failed) { 109 logger.Panic("Attempt to set a backward step. %v", switcher.pulsar.Config.MainListenerAddress) 110 } 111 112 logger.Debug(".setState(state)") 113 switcher.setState(state) 114 115 switch state { 116 case WaitingForStart: 117 logger.Debug("switcher.pulsar.clearState()") 118 switcher.pulsar.clearState() 119 case WaitingForEntropySigns: 120 switcher.pulsar.waitForEntropySigns(ctx) 121 case SendingEntropy: 122 switcher.pulsar.sendEntropy(ctx) 123 case WaitingForEntropy: 124 switcher.pulsar.waitForEntropy(ctx) 125 case SendingVector: 126 switcher.pulsar.sendVector(ctx) 127 case WaitingForVectors: 128 switcher.pulsar.waitForVectors(ctx) 129 case Verifying: 130 switcher.pulsar.verify(ctx) 131 case WaitingForPulseSigns: 132 switcher.pulsar.waitForPulseSigns(ctx) 133 case SendingPulseSign: 134 switcher.pulsar.sendPulseSign(ctx) 135 case SendingPulse: 136 switcher.pulsar.sendPulseToNodesAndPulsars(ctx) 137 case Failed: 138 switcher.pulsar.handleErrorState(ctx, args.(error)) 139 switcher.setState(WaitingForStart) 140 } 141 }