go.dedis.ch/onet/v3@v3.2.11-0.20210930124529-e36530bca7ef/simul/platform/runsimul.go (about) 1 package platform 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/BurntSushi/toml" 8 "go.dedis.ch/onet/v3" 9 "go.dedis.ch/onet/v3/log" 10 "go.dedis.ch/onet/v3/network" 11 "go.dedis.ch/onet/v3/simul/manage" 12 "go.dedis.ch/onet/v3/simul/monitor" 13 "golang.org/x/xerrors" 14 ) 15 16 type simulInit struct{} 17 type simulInitDone struct{} 18 19 // Simulate starts the server and will setup the protocol. 20 func Simulate(suite, serverAddress, simul, monitorAddress string) error { 21 scs, err := onet.LoadSimulationConfig(suite, ".", serverAddress) 22 if err != nil { 23 // We probably are not needed 24 log.Lvl2(err, serverAddress) 25 return nil 26 } 27 if monitorAddress != "" { 28 if err := monitor.ConnectSink(monitorAddress); err != nil { 29 log.Error("Couldn't connect monitor to sink:", err) 30 return xerrors.New("couldn't connect monitor to sink: " + err.Error()) 31 } 32 } 33 sims := make([]onet.Simulation, len(scs)) 34 simulInitID := network.RegisterMessage(simulInit{}) 35 simulInitDoneID := network.RegisterMessage(simulInitDone{}) 36 var rootSC *onet.SimulationConfig 37 var rootSim onet.Simulation 38 // having a waitgroup so the binary stops when all servers are closed 39 var wgServer, wgSimulInit sync.WaitGroup 40 var ready = make(chan bool) 41 measureNodeBW := true 42 measuresLock := sync.Mutex{} 43 measures := make([]*monitor.CounterIOMeasure, len(scs)) 44 if len(scs) > 0 { 45 cfg := &conf{} 46 _, err := toml.Decode(scs[0].Config, cfg) 47 if err != nil { 48 return xerrors.New("error while decoding config: " + err.Error()) 49 } 50 measureNodeBW = cfg.IndividualStats == "" 51 } 52 for i, sc := range scs { 53 // Starting all servers for that server 54 server := sc.Server 55 56 if measureNodeBW { 57 hostIndex, _ := sc.Roster.Search(sc.Server.ServerIdentity.ID) 58 measures[i] = monitor.NewCounterIOMeasureWithHost("bandwidth", sc.Server, hostIndex) 59 } 60 61 log.Lvl3(serverAddress, "Starting server", server.ServerIdentity.Address) 62 // Launch a server and notifies when it's done 63 wgServer.Add(1) 64 measure := measures[i] 65 go func(c *onet.Server) { 66 ready <- true 67 defer wgServer.Done() 68 c.Start() 69 if measure != nil { 70 measuresLock.Lock() 71 measure.Record() 72 measuresLock.Unlock() 73 } 74 log.Lvl3(serverAddress, "Simulation closed server", c.ServerIdentity) 75 }(server) 76 // wait to be sure the goroutine started 77 <-ready 78 79 sim, err := onet.NewSimulation(simul, sc.Config) 80 if err != nil { 81 return xerrors.New("couldn't create new simulation: " + err.Error()) 82 } 83 sims[i] = sim 84 // Need to store sc in a tmp-variable so it's correctly passed 85 // to the Register-functions. 86 scTmp := sc 87 server.RegisterProcessorFunc(simulInitID, func(env *network.Envelope) error { 88 // The node setup must be done in a goroutine to prevent the connection 89 // from the root to this node to stale forever. 90 go func() { 91 defer func() { 92 if measure != nil { 93 measuresLock.Lock() 94 // Remove the initialization of the simulation from this statistic 95 measure.Reset() 96 measuresLock.Unlock() 97 } 98 }() 99 100 err = sim.Node(scTmp) 101 log.ErrFatal(err) 102 _, err := scTmp.Server.Send(env.ServerIdentity, &simulInitDone{}) 103 log.ErrFatal(err) 104 }() 105 return nil 106 }) 107 server.RegisterProcessorFunc(simulInitDoneID, func(env *network.Envelope) error { 108 wgSimulInit.Done() 109 if measure != nil { 110 measuresLock.Lock() 111 // Reset the root bandwidth after the children sent the ACK. 112 measure.Reset() 113 measuresLock.Unlock() 114 } 115 return nil 116 }) 117 if server.ServerIdentity.ID.Equal(sc.Tree.Root.ServerIdentity.ID) { 118 log.Lvl2(serverAddress, "is root-node, will start protocol") 119 rootSim = sim 120 rootSC = sc 121 } 122 } 123 124 var simError error 125 if rootSim != nil { 126 // If this cothority has the root-server, it will start the simulation 127 log.Lvl2("Starting protocol", simul, "on server", rootSC.Server.ServerIdentity.Address) 128 log.Lvl5("Tree is", rootSC.Tree.Dump()) 129 130 // First count the number of available children 131 childrenWait := monitor.NewTimeMeasure("ChildrenWait") 132 wait := true 133 // The timeout starts with 1 second, which is the time of response between 134 // each level of the tree. 135 timeout := 1 * time.Second 136 for wait { 137 p, err := rootSC.Overlay.CreateProtocol("Count", rootSC.Tree, onet.NilServiceID) 138 if err != nil { 139 return xerrors.New("couldn't create protocol: " + err.Error()) 140 } 141 proto := p.(*manage.ProtocolCount) 142 proto.SetTimeout(timeout) 143 proto.Start() 144 log.Lvl1("Started counting children with timeout of", timeout) 145 select { 146 case count := <-proto.Count: 147 if count == rootSC.Tree.Size() { 148 log.Lvl1("Found all", count, "children") 149 wait = false 150 } else { 151 log.Lvl1("Found only", count, "children, counting again") 152 } 153 } 154 // Double the timeout and try again if not successful. 155 timeout *= 2 156 } 157 childrenWait.Record() 158 log.Lvl2("Broadcasting start") 159 syncWait := monitor.NewTimeMeasure("SimulSyncWait") 160 wgSimulInit.Add(len(rootSC.Tree.Roster.List)) 161 for _, conode := range rootSC.Tree.Roster.List { 162 go func(si *network.ServerIdentity) { 163 _, err := rootSC.Server.Send(si, &simulInit{}) 164 log.ErrFatal(err, "Couldn't send to conode:") 165 }(conode) 166 } 167 wgSimulInit.Wait() 168 syncWait.Record() 169 log.Lvl1("Starting new node", simul) 170 171 measureNet := monitor.NewCounterIOMeasure("bandwidth_root", rootSC.Server) 172 simError = rootSim.Run(rootSC) 173 measureNet.Record() 174 175 // Test if all ServerIdentities are used in the tree, else we'll run into 176 // troubles with CloseAll 177 if !rootSC.Tree.UsesList() { 178 log.Error("The tree doesn't use all ServerIdentities from the list!\n" + 179 "This means that the CloseAll will fail and the experiment never ends!") 180 } 181 182 // Recreate a tree out of the original roster, to be sure all nodes are included and 183 // that the tree is easy to close. 184 closeTree := rootSC.Roster.GenerateBinaryTree() 185 pi, err := rootSC.Overlay.CreateProtocol("CloseAll", closeTree, onet.NilServiceID) 186 if err != nil { 187 return xerrors.New("couldn't create closeAll protocol: " + err.Error()) 188 } 189 pi.Start() 190 } 191 192 log.Lvl3(serverAddress, scs[0].Server.ServerIdentity, "is waiting for all servers to close") 193 wgServer.Wait() 194 log.Lvl2(serverAddress, "has all servers closed") 195 if monitorAddress != "" { 196 monitor.EndAndCleanup() 197 } 198 199 // Give a chance to the simulation to stop the servers and clean up but returns the simulation error anyway. 200 if simError != nil { 201 return xerrors.New("error from simulation run: " + simError.Error()) 202 } 203 return nil 204 } 205 206 type conf struct { 207 IndividualStats string 208 }