github.com/pingcap/chaos@v0.0.0-20190710112158-c86faf4b3719/pkg/model/cas_register.go (about) 1 package model 2 3 import ( 4 "encoding/json" 5 6 "github.com/pingcap/chaos/pkg/core" 7 "github.com/pingcap/chaos/pkg/history" 8 ) 9 10 // CasOp is an operation. 11 type CasOp int 12 13 // cas operation 14 const ( 15 CasRegisterRead CasOp = iota 16 CasRegisterWrite 17 CasRegisterCAS 18 ) 19 20 // CasRegisterRequest is the request that is issued to a cas register. 21 type CasRegisterRequest struct { 22 Op CasOp 23 Arg1 int // used for write, or for CAS from argument 24 Arg2 int // used for CAS to argument 25 } 26 27 // CasRegisterResponse is the response returned by a cas register. 28 type CasRegisterResponse struct { 29 Ok bool // used for CAS 30 Exists bool // used for read 31 Value int // used for read 32 Unknown bool // used when operation times out 33 } 34 35 var _ core.UnknownResponse = (*CasRegisterResponse)(nil) 36 37 // IsUnknown implements UnknownResponse interface 38 func (r CasRegisterResponse) IsUnknown() bool { 39 return r.Unknown 40 } 41 42 type casRegister struct { 43 perparedState *int 44 } 45 46 func (c *casRegister) Prepare(state interface{}) { 47 s := state.(int) 48 c.perparedState = &s 49 } 50 51 func (c *casRegister) Init() interface{} { 52 if c.perparedState != nil { 53 return *c.perparedState 54 } 55 return -1 56 } 57 58 func (*casRegister) Step(state interface{}, input interface{}, output interface{}) (bool, interface{}) { 59 st := state.(int) 60 inp := input.(CasRegisterRequest) 61 out := output.(CasRegisterResponse) 62 if inp.Op == CasRegisterRead { 63 // read 64 ok := (out.Exists == false && st == -1) || (out.Exists == true && st == out.Value) || out.Unknown 65 return ok, state 66 } else if inp.Op == CasRegisterWrite { 67 // write 68 return true, inp.Arg1 69 } 70 71 // cas 72 ok := (inp.Arg1 == st && out.Ok) || (inp.Arg1 != st && !out.Ok) || out.Unknown 73 result := st 74 if inp.Arg1 == st { 75 result = inp.Arg2 76 } 77 return ok, result 78 } 79 80 func (*casRegister) Equal(state1, state2 interface{}) bool { 81 st1 := state1.(int) 82 st2 := state2.(int) 83 return st1 == st2 84 } 85 86 func (*casRegister) Name() string { 87 return "cas_register" 88 } 89 90 // CasRegisterModel returns a cas register model 91 func CasRegisterModel() core.Model { 92 return &casRegister{} 93 } 94 95 type casRegisterParser struct { 96 } 97 98 func (p casRegisterParser) OnRequest(data json.RawMessage) (interface{}, error) { 99 r := CasRegisterRequest{} 100 err := json.Unmarshal(data, &r) 101 return r, err 102 } 103 104 func (p casRegisterParser) OnResponse(data json.RawMessage) (interface{}, error) { 105 r := CasRegisterResponse{} 106 err := json.Unmarshal(data, &r) 107 if r.Unknown { 108 return nil, err 109 } 110 return r, nil 111 } 112 113 func (p casRegisterParser) OnNoopResponse() interface{} { 114 return CasRegisterResponse{Unknown: true} 115 } 116 117 func (p casRegisterParser) OnState(data json.RawMessage) (interface{}, error) { 118 var state int 119 err := json.Unmarshal(data, &state) 120 if err != nil { 121 return nil, err 122 } 123 return state, nil 124 } 125 126 // CasRegisterParser parses CasRegister history. 127 func CasRegisterParser() history.RecordParser { 128 return casRegisterParser{} 129 }