github.com/KinWaiYuen/client-go/v2@v2.5.4/oracle/oracles/mock.go (about) 1 // Copyright 2021 TiKV Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/oracle/oracles/mock.go 19 // 20 21 // Copyright 2018 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package oracles 36 37 import ( 38 "context" 39 "sync" 40 "time" 41 42 "github.com/KinWaiYuen/client-go/v2/oracle" 43 "github.com/pingcap/errors" 44 ) 45 46 var errStopped = errors.New("stopped") 47 48 // MockOracle is a mock oracle for test. 49 type MockOracle struct { 50 sync.RWMutex 51 stop bool 52 offset time.Duration 53 lastTS uint64 54 } 55 56 // Enable enables the Oracle 57 func (o *MockOracle) Enable() { 58 o.Lock() 59 defer o.Unlock() 60 o.stop = false 61 } 62 63 // Disable disables the Oracle 64 func (o *MockOracle) Disable() { 65 o.Lock() 66 defer o.Unlock() 67 o.stop = true 68 } 69 70 // AddOffset adds the offset of the oracle. 71 func (o *MockOracle) AddOffset(d time.Duration) { 72 o.Lock() 73 defer o.Unlock() 74 75 o.offset += d 76 } 77 78 // GetTimestamp implements oracle.Oracle interface. 79 func (o *MockOracle) GetTimestamp(ctx context.Context, _ *oracle.Option) (uint64, error) { 80 o.Lock() 81 defer o.Unlock() 82 83 if o.stop { 84 return 0, errors.Trace(errStopped) 85 } 86 ts := oracle.GoTimeToTS(time.Now().Add(o.offset)) 87 if oracle.ExtractPhysical(o.lastTS) == oracle.ExtractPhysical(ts) { 88 ts = o.lastTS + 1 89 } 90 o.lastTS = ts 91 return ts, nil 92 } 93 94 // GetStaleTimestamp implements oracle.Oracle interface. 95 func (o *MockOracle) GetStaleTimestamp(ctx context.Context, txnScope string, prevSecond uint64) (ts uint64, err error) { 96 return oracle.GoTimeToTS(time.Now().Add(-time.Second * time.Duration(prevSecond))), nil 97 } 98 99 type mockOracleFuture struct { 100 o *MockOracle 101 ctx context.Context 102 } 103 104 func (m *mockOracleFuture) Wait() (uint64, error) { 105 return m.o.GetTimestamp(m.ctx, &oracle.Option{}) 106 } 107 108 // GetTimestampAsync implements oracle.Oracle interface. 109 func (o *MockOracle) GetTimestampAsync(ctx context.Context, _ *oracle.Option) oracle.Future { 110 return &mockOracleFuture{o, ctx} 111 } 112 113 // GetLowResolutionTimestamp implements oracle.Oracle interface. 114 func (o *MockOracle) GetLowResolutionTimestamp(ctx context.Context, opt *oracle.Option) (uint64, error) { 115 return o.GetTimestamp(ctx, opt) 116 } 117 118 // GetLowResolutionTimestampAsync implements oracle.Oracle interface. 119 func (o *MockOracle) GetLowResolutionTimestampAsync(ctx context.Context, opt *oracle.Option) oracle.Future { 120 return o.GetTimestampAsync(ctx, opt) 121 } 122 123 // IsExpired implements oracle.Oracle interface. 124 func (o *MockOracle) IsExpired(lockTimestamp, TTL uint64, _ *oracle.Option) bool { 125 o.RLock() 126 defer o.RUnlock() 127 expire := oracle.GetTimeFromTS(lockTimestamp).Add(time.Duration(TTL) * time.Millisecond) 128 return !time.Now().Add(o.offset).Before(expire) 129 } 130 131 // UntilExpired implement oracle.Oracle interface. 132 func (o *MockOracle) UntilExpired(lockTimeStamp, TTL uint64, _ *oracle.Option) int64 { 133 o.RLock() 134 defer o.RUnlock() 135 expire := oracle.GetTimeFromTS(lockTimeStamp).Add(time.Duration(TTL) * time.Millisecond) 136 return expire.Sub(time.Now().Add(o.offset)).Milliseconds() 137 } 138 139 // Close implements oracle.Oracle interface. 140 func (o *MockOracle) Close() { 141 142 }