1package txn
2
3import (
4	mrand "math/rand"
5	"time"
6)
7
8var chaosEnabled = false
9var chaosSetting Chaos
10
11// Chaos holds parameters for the failure injection mechanism.
12type Chaos struct {
13	// KillChance is the 0.0 to 1.0 chance that a given checkpoint
14	// within the algorithm will raise an interruption that will
15	// stop the procedure.
16	KillChance float64
17
18	// SlowdownChance is the 0.0 to 1.0 chance that a given checkpoint
19	// within the algorithm will be delayed by Slowdown before
20	// continuing.
21	SlowdownChance float64
22	Slowdown       time.Duration
23
24	// If Breakpoint is set, the above settings will only affect the
25	// named breakpoint.
26	Breakpoint string
27}
28
29// SetChaos sets the failure injection parameters to c.
30func SetChaos(c Chaos) {
31	chaosSetting = c
32	chaosEnabled = c.KillChance > 0 || c.SlowdownChance > 0
33}
34
35func chaos(bpname string) {
36	if !chaosEnabled {
37		return
38	}
39	switch chaosSetting.Breakpoint {
40	case "", bpname:
41		kc := chaosSetting.KillChance
42		if kc > 0 && mrand.Intn(1000) < int(kc*1000) {
43			panic(chaosError{})
44		}
45		if bpname == "insert" {
46			return
47		}
48		sc := chaosSetting.SlowdownChance
49		if sc > 0 && mrand.Intn(1000) < int(sc*1000) {
50			time.Sleep(chaosSetting.Slowdown)
51		}
52	}
53}
54
55type chaosError struct{}
56
57func (f *flusher) handleChaos(err *error) {
58	v := recover()
59	if v == nil {
60		return
61	}
62	if _, ok := v.(chaosError); ok {
63		f.debugf("Killed by chaos!")
64		*err = ErrChaos
65		return
66	}
67	panic(v)
68}
69