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  }