1// SPDX-License-Identifier: ISC 2// Copyright (c) 2014-2020 Bitmark Inc. 3// Use of this source code is governed by an ISC 4// license that can be found in the LICENSE file. 5 6package mode 7 8import ( 9 "sync" 10 11 "github.com/bitmark-inc/bitmarkd/chain" 12 "github.com/bitmark-inc/bitmarkd/fault" 13 "github.com/bitmark-inc/logger" 14) 15 16// Mode - type to hold the mode 17type Mode int 18 19// all possible modes 20const ( 21 Stopped Mode = iota 22 Resynchronise 23 Normal 24 maximum 25) 26 27var globalData struct { 28 sync.RWMutex 29 log *logger.L 30 mode Mode 31 testing bool 32 chain string 33 34 // set once during initialise 35 initialised bool 36} 37 38// Initialise - set up the mode system 39func Initialise(chainName string) error { 40 41 // ensure start up in resynchronise mode 42 globalData.Lock() 43 defer globalData.Unlock() 44 45 // no need to start if already started 46 if globalData.initialised { 47 return fault.AlreadyInitialised 48 } 49 50 globalData.log = logger.New("mode") 51 globalData.log.Info("starting…") 52 53 // default settings 54 globalData.chain = chainName 55 globalData.testing = false 56 globalData.mode = Resynchronise 57 58 // override for specific chain 59 switch chainName { 60 case chain.Bitmark: 61 // no change 62 case chain.Testing, chain.Local: 63 globalData.testing = true 64 default: 65 globalData.log.Criticalf("mode cannot handle chain: '%s'", chainName) 66 return fault.InvalidChain 67 } 68 69 // all data initialised 70 globalData.initialised = true 71 72 return nil 73} 74 75// Finalise - shutdown mode handling 76func Finalise() error { 77 78 if !globalData.initialised { 79 return fault.NotInitialised 80 } 81 82 globalData.log.Info("shutting down…") 83 globalData.log.Flush() 84 85 Set(Stopped) 86 87 // finally... 88 globalData.initialised = false 89 90 globalData.log.Info("finished") 91 globalData.log.Flush() 92 93 return nil 94} 95 96// Set - change mode 97func Set(mode Mode) { 98 99 if mode >= Stopped && mode < maximum { 100 globalData.Lock() 101 globalData.mode = mode 102 globalData.Unlock() 103 104 globalData.log.Infof("set: %s", mode) 105 } else { 106 globalData.log.Errorf("ignore invalid set: %d", mode) 107 } 108} 109 110// Is - detect mode 111func Is(mode Mode) bool { 112 globalData.RLock() 113 defer globalData.RUnlock() 114 return mode == globalData.mode 115} 116 117// IsNot - detect mode 118func IsNot(mode Mode) bool { 119 globalData.RLock() 120 defer globalData.RUnlock() 121 return mode != globalData.mode 122} 123 124// IsTesting - special for testing 125func IsTesting() bool { 126 globalData.RLock() 127 defer globalData.RUnlock() 128 return globalData.testing 129} 130 131// ChainName - name of the current chain 132func ChainName() string { 133 globalData.RLock() 134 defer globalData.RUnlock() 135 return globalData.chain 136} 137 138// String - current mode represented as a string 139func String() string { 140 globalData.RLock() 141 defer globalData.RUnlock() 142 return globalData.mode.String() 143} 144 145// String - current mode represented as a string 146func (m Mode) String() string { 147 switch m { 148 case Stopped: 149 return "Stopped" 150 case Resynchronise: 151 return "Resynchronise" 152 case Normal: 153 return "Normal" 154 default: 155 return "*Unknown*" 156 } 157} 158