github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/oracle/oracle.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package oracle 15 16 import ( 17 "context" 18 "time" 19 20 "github.com/whtcorpsinc/failpoint" 21 "github.com/whtcorpsinc/milevadb/soliton/logutil" 22 "go.uber.org/zap" 23 ) 24 25 // Oracle is the interface that provides strictly ascending timestamps. 26 type Oracle interface { 27 GetTimestamp(ctx context.Context) (uint64, error) 28 GetTimestampAsync(ctx context.Context) Future 29 GetLowResolutionTimestamp(ctx context.Context) (uint64, error) 30 GetLowResolutionTimestampAsync(ctx context.Context) Future 31 IsExpired(lockTimestamp uint64, TTL uint64) bool 32 UntilExpired(lockTimeStamp uint64, TTL uint64) int64 33 Close() 34 } 35 36 // Future is a future which promises to return a timestamp. 37 type Future interface { 38 Wait() (uint64, error) 39 } 40 41 const physicalShiftBits = 18 42 43 // ComposeTS creates a ts from physical and logical parts. 44 func ComposeTS(physical, logical int64) uint64 { 45 failpoint.Inject("changeTSFromFIDel", func(val failpoint.Value) { 46 valInt, ok := val.(int) 47 if ok { 48 origPhyTS := physical 49 logical := logical 50 newPhyTs := origPhyTS + int64(valInt) 51 origTS := uint64((physical << physicalShiftBits) + logical) 52 newTS := uint64((newPhyTs << physicalShiftBits) + logical) 53 logutil.BgLogger().Warn("ComposeTS failpoint", zap.Uint64("origTS", origTS), 54 zap.Int("valInt", valInt), zap.Uint64("ts", newTS)) 55 failpoint.Return(newTS) 56 } 57 }) 58 return uint64((physical << physicalShiftBits) + logical) 59 } 60 61 // ExtractPhysical returns a ts's physical part. 62 func ExtractPhysical(ts uint64) int64 { 63 return int64(ts >> physicalShiftBits) 64 } 65 66 // GetPhysical returns physical from an instant time with millisecond precision. 67 func GetPhysical(t time.Time) int64 { 68 return t.UnixNano() / int64(time.Millisecond) 69 } 70 71 // EncodeTSO encodes a millisecond into tso. 72 func EncodeTSO(ts int64) uint64 { 73 return uint64(ts) << physicalShiftBits 74 } 75 76 // GetTimeFromTS extracts time.Time from a timestamp. 77 func GetTimeFromTS(ts uint64) time.Time { 78 ms := ExtractPhysical(ts) 79 return time.Unix(ms/1e3, (ms%1e3)*1e6) 80 }