github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/network/p2p/simulations/mocker.go (about) 1 package simulations 2 3 import ( 4 "fmt" 5 "math/rand" 6 "sync" 7 "time" 8 9 "github.com/neatlab/neatio/chain/log" 10 "github.com/neatlab/neatio/network/p2p/discover" 11 ) 12 13 var mockerList = map[string]func(net *Network, quit chan struct{}, nodeCount int){ 14 "startStop": startStop, 15 "probabilistic": probabilistic, 16 "boot": boot, 17 } 18 19 func LookupMocker(mockerType string) func(net *Network, quit chan struct{}, nodeCount int) { 20 return mockerList[mockerType] 21 } 22 23 func GetMockerList() []string { 24 list := make([]string, 0, len(mockerList)) 25 for k := range mockerList { 26 list = append(list, k) 27 } 28 return list 29 } 30 31 func boot(net *Network, quit chan struct{}, nodeCount int) { 32 _, err := connectNodesInRing(net, nodeCount) 33 if err != nil { 34 panic("Could not startup node network for mocker") 35 } 36 } 37 38 func startStop(net *Network, quit chan struct{}, nodeCount int) { 39 nodes, err := connectNodesInRing(net, nodeCount) 40 if err != nil { 41 panic("Could not startup node network for mocker") 42 } 43 tick := time.NewTicker(10 * time.Second) 44 defer tick.Stop() 45 for { 46 select { 47 case <-quit: 48 log.Info("Terminating simulation loop") 49 return 50 case <-tick.C: 51 id := nodes[rand.Intn(len(nodes))] 52 log.Info("stopping node", "id", id) 53 if err := net.Stop(id); err != nil { 54 log.Error("error stopping node", "id", id, "err", err) 55 return 56 } 57 58 select { 59 case <-quit: 60 log.Info("Terminating simulation loop") 61 return 62 case <-time.After(3 * time.Second): 63 } 64 65 log.Debug("starting node", "id", id) 66 if err := net.Start(id); err != nil { 67 log.Error("error starting node", "id", id, "err", err) 68 return 69 } 70 } 71 } 72 } 73 74 func probabilistic(net *Network, quit chan struct{}, nodeCount int) { 75 nodes, err := connectNodesInRing(net, nodeCount) 76 if err != nil { 77 panic("Could not startup node network for mocker") 78 } 79 for { 80 select { 81 case <-quit: 82 log.Info("Terminating simulation loop") 83 return 84 default: 85 } 86 var lowid, highid int 87 var wg sync.WaitGroup 88 randWait := time.Duration(rand.Intn(5000)+1000) * time.Millisecond 89 rand1 := rand.Intn(nodeCount - 1) 90 rand2 := rand.Intn(nodeCount - 1) 91 if rand1 < rand2 { 92 lowid = rand1 93 highid = rand2 94 } else if rand1 > rand2 { 95 highid = rand1 96 lowid = rand2 97 } else { 98 if rand1 == 0 { 99 rand2 = 9 100 } else if rand1 == 9 { 101 rand1 = 0 102 } 103 lowid = rand1 104 highid = rand2 105 } 106 var steps = highid - lowid 107 wg.Add(steps) 108 for i := lowid; i < highid; i++ { 109 select { 110 case <-quit: 111 log.Info("Terminating simulation loop") 112 return 113 case <-time.After(randWait): 114 } 115 log.Debug(fmt.Sprintf("node %v shutting down", nodes[i])) 116 err := net.Stop(nodes[i]) 117 if err != nil { 118 log.Error(fmt.Sprintf("Error stopping node %s", nodes[i])) 119 wg.Done() 120 continue 121 } 122 go func(id discover.NodeID) { 123 time.Sleep(randWait) 124 err := net.Start(id) 125 if err != nil { 126 log.Error(fmt.Sprintf("Error starting node %s", id)) 127 } 128 wg.Done() 129 }(nodes[i]) 130 } 131 wg.Wait() 132 } 133 134 } 135 136 func connectNodesInRing(net *Network, nodeCount int) ([]discover.NodeID, error) { 137 ids := make([]discover.NodeID, nodeCount) 138 for i := 0; i < nodeCount; i++ { 139 node, err := net.NewNode() 140 if err != nil { 141 log.Error("Error creating a node! %s", err) 142 return nil, err 143 } 144 ids[i] = node.ID() 145 } 146 147 for _, id := range ids { 148 if err := net.Start(id); err != nil { 149 log.Error("Error starting a node! %s", err) 150 return nil, err 151 } 152 log.Debug(fmt.Sprintf("node %v starting up", id)) 153 } 154 for i, id := range ids { 155 peerID := ids[(i+1)%len(ids)] 156 if err := net.Connect(id, peerID); err != nil { 157 log.Error("Error connecting a node to a peer! %s", err) 158 return nil, err 159 } 160 } 161 162 return ids, nil 163 }