github.com/pingcap/chaos@v0.0.0-20190710112158-c86faf4b3719/pkg/nemesis/generator.go (about)

     1  package nemesis
     2  
     3  import (
     4  	"math/rand"
     5  	"time"
     6  
     7  	"github.com/pingcap/chaos/pkg/core"
     8  )
     9  
    10  type killGenerator struct {
    11  	db   string
    12  	name string
    13  }
    14  
    15  func (g killGenerator) Generate(nodes []string) []*core.NemesisOperation {
    16  	n := 1
    17  	switch g.name {
    18  	case "minor_kill":
    19  		n = len(nodes)/2 - 1
    20  	case "major_kill":
    21  		n = len(nodes)/2 + 1
    22  	case "all_kill":
    23  		n = len(nodes)
    24  	default:
    25  		n = 1
    26  	}
    27  
    28  	return killNodes(g.db, nodes, n)
    29  }
    30  
    31  func (g killGenerator) Name() string {
    32  	return g.name
    33  }
    34  
    35  func killNodes(db string, nodes []string, n int) []*core.NemesisOperation {
    36  	ops := make([]*core.NemesisOperation, len(nodes))
    37  
    38  	// randomly shuffle the indecies and get the first n nodes to be partitioned.
    39  	indices := shuffleIndices(len(nodes))
    40  
    41  	for i := 0; i < n; i++ {
    42  		ops[indices[i]] = &core.NemesisOperation{
    43  			Name:        "kill",
    44  			InvokeArgs:  []string{db},
    45  			RecoverArgs: []string{db},
    46  			RunTime:     time.Second * time.Duration(rand.Intn(10)+1),
    47  		}
    48  	}
    49  
    50  	return ops
    51  }
    52  
    53  // NewKillGenerator creates a generator.
    54  // Name is random_kill, minor_kill, major_kill, and all_kill.
    55  func NewKillGenerator(db string, name string) core.NemesisGenerator {
    56  	return killGenerator{db: db, name: name}
    57  }
    58  
    59  type dropGenerator struct {
    60  	name string
    61  }
    62  
    63  func (g dropGenerator) Generate(nodes []string) []*core.NemesisOperation {
    64  	n := 1
    65  	switch g.name {
    66  	case "minor_drop":
    67  		n = len(nodes)/2 - 1
    68  	case "major_drop":
    69  		n = len(nodes)/2 + 1
    70  	case "all_drop":
    71  		n = len(nodes)
    72  	default:
    73  		n = 1
    74  	}
    75  	return partitionNodes(nodes, n)
    76  }
    77  
    78  func (g dropGenerator) Name() string {
    79  	return g.name
    80  }
    81  
    82  func partitionNodes(nodes []string, n int) []*core.NemesisOperation {
    83  	ops := make([]*core.NemesisOperation, len(nodes))
    84  
    85  	// randomly shuffle the indecies and get the first n nodes to be partitioned.
    86  	indices := shuffleIndices(len(nodes))
    87  
    88  	partNodes := make([]string, n)
    89  	for i := 0; i < n; i++ {
    90  		partNodes[i] = nodes[indices[i]]
    91  	}
    92  
    93  	for i := 0; i < len(nodes); i++ {
    94  		ops[i] = &core.NemesisOperation{
    95  			Name:       "drop",
    96  			InvokeArgs: partNodes,
    97  			RunTime:    time.Second * time.Duration(rand.Intn(10)+1),
    98  		}
    99  	}
   100  
   101  	return ops
   102  }
   103  
   104  func shuffleIndices(n int) []int {
   105  	indices := make([]int, n)
   106  	for i := 0; i < n; i++ {
   107  		indices[i] = i
   108  	}
   109  	for i := len(indices) - 1; i > 0; i-- {
   110  		j := rand.Intn(i + 1)
   111  		indices[i], indices[j] = indices[j], indices[i]
   112  	}
   113  
   114  	return indices
   115  }
   116  
   117  // NewDropGenerator creates a generator.
   118  // Name is random_drop, minor_drop, major_drop, and all_drop.
   119  func NewDropGenerator(name string) core.NemesisGenerator {
   120  	return dropGenerator{name: name}
   121  }