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  }