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  }