func NewList() List { list := make([]*Agent, state.NodeCount()) for i := 0; i < state.NodeCount(); i++ { list[i] = NewAgent(uint(i)) } return list }
func New() *Network { count := uint(state.NodeCount()) net := &Network{ links: make([]*Link, 0), cache: make([][]*Link, count), } var i, j, offset uint for i = 0; i < count; i++ { for j = 0; j < i; j++ { link := &Link{ network: net, kill: make(chan bool), // Do smaller number as agent1 agent1: j, agent2: i, } net.links = append(net.links, link) } } for offset, i = 0, 0; i < count; offset, i = offset+i, i+1 { net.cache[i] = net.links[offset : offset+i] } return net }
// SpofMonkey detects single points of failure by netsplitting one node at a // time away from the rest of the cluster and ensuring that the cluster // continues to make progress. func (d *Director) SpofMonkey(rng *rand.Rand, intensity float64) bool { if spofIndex >= state.NodeCount() { return false } else if len(spofOrder) != state.NodeCount() { // Unfortunately we can't do this in an init() because we defer // the parsing of flag arguments until later. spofOrder = rng.Perm(state.NodeCount()) } i := spofOrder[spofIndex] log.Printf("[monkey] Testing if %v is a single point of failure", d.agents[i]) netsplit := d.net.FindPerimeter([]uint{uint(i)}) spofIndex++ d.agents[i].Freeze() for _, target := range netsplit { target.GoodbyeForever() } // We need to make sure that the cluster is capable of servicing // requests that no member of the cluster has ever seen before in order // to ensure that the cluster is making progress. To do this, we // determine the request ID of the last request that has been created, // and make sure that we see a request that was created *after* that // (any requests generated after targetRequestId were necessarily // generated after the actions above). targetRequestId := state.LastGeneratedRequest() for <-state.GotRequest() <= targetRequestId { } log.Printf("[monkey] %v is (probably) not a single point of failure!", d.agents[i]) for _, target := range netsplit { target.WhyHelloThere() } d.agents[i].Thaw() return true }
// Choose random connections such that each node has a connection in the // returned list. func (d *Director) randomNeighborLinks(rng *rand.Rand) []*network.Link { links := d.net.Links() perm := rng.Perm(len(links)) cover := make(map[uint]bool, state.NodeCount()) for i := 0; i < state.NodeCount(); i++ { cover[uint(i)] = false } out := make([]*network.Link, 0, (state.NodeCount()+1)/2) for _, i := range perm { link := links[i] a1, a2 := link.Agents() if !cover[a1] || !cover[a2] { out = append(out, link) cover[a1] = true cover[a2] = true } } return out }
func (d *Director) randomPartition(rng *rand.Rand) []*network.Link { count := state.NodeCount() // If there are fewer than three nodes, netsplits are pretty // boring if count < 3 { return []*network.Link{d.net.Links()[0]} } perm := rng.Perm(count) splitPoint := rng.Intn(count-2) + 1 split := make([]uint, 0) for i := 0; i < splitPoint; i++ { split = append(split, uint(perm[i])) } log.Debugf("Made a netsplit: %v", split) return d.net.FindPerimeter(split) }
func (h *Harness) startQueryThreads() { threads := 4 * state.NodeCount() for i := 0; i < threads; i++ { go h.queryThread() } }