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