github.com/matrixorigin/matrixone@v1.2.0/pkg/container/types/txnts.go (about)

     1  // Copyright 2021 Matrix Origin
     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  package types
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"math"
    21  	"strconv"
    22  	"strings"
    23  	"sync/atomic"
    24  	"time"
    25  	"unsafe"
    26  
    27  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    28  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    29  )
    30  
    31  // Transaction ts contains a physical ts in higher 8 bytes
    32  // and a logical in lower 4 bytes.  higher lower in little
    33  // ending sense.
    34  func (ts TS) Physical() int64 {
    35  	return DecodeInt64(ts[4:12])
    36  }
    37  func (ts TS) Logical() uint32 {
    38  	return DecodeUint32(ts[:4])
    39  }
    40  
    41  func (ts *TS) IsEmpty() bool {
    42  	p := DecodeInt64(ts[4:12])
    43  	if p != 0 {
    44  		return false
    45  	}
    46  	return DecodeInt64(ts[:4]) == 0
    47  }
    48  func (ts *TS) Equal(rhs *TS) bool {
    49  	return *ts == *rhs
    50  }
    51  
    52  // Compare physical first then logical.
    53  func (ts *TS) Compare(rhs *TS) int {
    54  	p1 := *(*int64)(unsafe.Pointer(&ts[4]))
    55  	p2 := *(*int64)(unsafe.Pointer(&rhs[4]))
    56  	if p1 < p2 {
    57  		return -1
    58  	}
    59  	if p1 > p2 {
    60  		return 1
    61  	}
    62  	l1 := *(*uint32)(unsafe.Pointer(ts))
    63  	l2 := *(*uint32)(unsafe.Pointer(rhs))
    64  	if l1 < l2 {
    65  		return -1
    66  	}
    67  	if l1 == l2 {
    68  		return 0
    69  	}
    70  	return 1
    71  }
    72  
    73  func (ts *TS) Less(rhs *TS) bool {
    74  	return ts.Compare(rhs) < 0
    75  }
    76  func (ts *TS) LessEq(rhs *TS) bool {
    77  	return ts.Compare(rhs) <= 0
    78  }
    79  func (ts *TS) Greater(rhs *TS) bool {
    80  	return ts.Compare(rhs) > 0
    81  }
    82  func (ts *TS) GreaterEq(rhs *TS) bool {
    83  	return ts.Compare(rhs) >= 0
    84  }
    85  
    86  // TODO::need to take "NodeID" account into
    87  func TimestampToTS(ts timestamp.Timestamp) TS {
    88  	return BuildTS(ts.PhysicalTime, ts.LogicalTime)
    89  }
    90  
    91  func (ts TS) ToTimestamp() timestamp.Timestamp {
    92  	return timestamp.Timestamp{
    93  		PhysicalTime: DecodeInt64(ts[4:12]),
    94  		LogicalTime:  DecodeUint32(ts[:4])}
    95  }
    96  
    97  func BuildTS(p int64, l uint32) (ret TS) {
    98  	copy(ret[4:12], EncodeInt64(&p))
    99  	copy(ret[:4], EncodeUint32(&l))
   100  	return
   101  }
   102  
   103  func BuildTSForTest(p int64, l uint32) *TS {
   104  	ts := BuildTS(p, l)
   105  	return &ts
   106  }
   107  
   108  func MaxTs() TS {
   109  	return BuildTS(math.MaxInt64, math.MaxUint32)
   110  }
   111  
   112  // Who use this function?
   113  func (ts TS) Prev() TS {
   114  	p, l := ts.Physical(), ts.Logical()
   115  	if l == 0 {
   116  		return BuildTS(p-1, math.MaxUint32)
   117  	}
   118  	return BuildTS(p, l-1)
   119  }
   120  
   121  func (ts *TS) Next() TS {
   122  	p, l := DecodeInt64(ts[4:12]), DecodeUint32(ts[:4])
   123  	if l == math.MaxUint32 {
   124  		p += 1
   125  	} else {
   126  		l += 1
   127  	}
   128  	return BuildTS(p, l)
   129  }
   130  
   131  func (ts TS) ToString() string {
   132  	return fmt.Sprintf("%d-%d", ts.Physical(), ts.Logical())
   133  }
   134  
   135  func StringToTS(s string) (ts TS) {
   136  	tmp := strings.Split(s, "-")
   137  	if len(tmp) != 2 {
   138  		panic("format of ts must be physical-logical")
   139  	}
   140  
   141  	pTime, err := strconv.ParseInt(tmp[0], 10, 64)
   142  	if err != nil {
   143  		panic("format of ts must be physical-logical, physical is not an integer")
   144  	}
   145  
   146  	lTime, err := strconv.ParseUint(tmp[1], 10, 32)
   147  	if err != nil {
   148  		panic("format of ts must be physical-logical, logical is not an uint32")
   149  	}
   150  	return BuildTS(pTime, uint32(lTime))
   151  }
   152  
   153  // XXX
   154  // XXX The following code does not belong to types. TAE folks please fix.
   155  
   156  // CompoundKeyType -- this is simply deadly wrong thing.
   157  var CompoundKeyType Type
   158  
   159  // Why this was in package types?
   160  var SystemDBTS TS
   161  
   162  func init() {
   163  	CompoundKeyType = T_varchar.ToType()
   164  	CompoundKeyType.Width = 100
   165  
   166  	SystemDBTS = BuildTS(1, 0)
   167  }
   168  
   169  // var v T
   170  func DefaultVal[T any]() T {
   171  	var v T
   172  	return v
   173  }
   174  
   175  // TAE test infra, should move out
   176  var (
   177  	//just for test
   178  	GlobalTsAlloctor *TsAlloctor
   179  )
   180  
   181  func init() {
   182  	GlobalTsAlloctor = NewTsAlloctor(NewMockHLCClock(1))
   183  }
   184  
   185  type TsAlloctor struct {
   186  	clock clock.Clock
   187  }
   188  
   189  func NewTsAlloctor(clock clock.Clock) *TsAlloctor {
   190  	return &TsAlloctor{clock: clock}
   191  }
   192  
   193  func (alloc *TsAlloctor) Alloc() TS {
   194  	now, _ := alloc.clock.Now()
   195  	var ts TS
   196  	copy(ts[4:12], EncodeInt64(&now.PhysicalTime))
   197  	copy(ts[:4], EncodeUint32(&now.LogicalTime))
   198  	return ts
   199  }
   200  
   201  // TODO::will be removed
   202  func (alloc *TsAlloctor) Get() TS {
   203  	if mockClock, ok := alloc.clock.(*MockHLCClock); ok {
   204  		var ts TS
   205  		i64 := mockClock.Get().PhysicalTime
   206  		copy(ts[4:12], EncodeInt64(&i64))
   207  		//copy(ts[:4], EncodeUint32(mockClock.Get().LogicalTime))
   208  		return ts
   209  	}
   210  	panic("HLCClock does not support Get()")
   211  }
   212  
   213  func (alloc *TsAlloctor) SetStart(start TS) {
   214  	//if start.Greater(alloc.Get()) {
   215  	alloc.clock.Update(timestamp.Timestamp{PhysicalTime: DecodeInt64(start[4:12]),
   216  		LogicalTime: DecodeUint32(start[:4])})
   217  	//}
   218  }
   219  
   220  func NextGlobalTsForTest() TS {
   221  	return GlobalTsAlloctor.Alloc()
   222  }
   223  
   224  type MockHLCClock struct {
   225  	pTime int64
   226  	//always be 0
   227  	//lTime     uint32
   228  	maxOffset time.Duration
   229  }
   230  
   231  // Just for test , start >= 1
   232  func NewMockHLCClock(start int64) *MockHLCClock {
   233  	return &MockHLCClock{pTime: start}
   234  }
   235  
   236  func (c *MockHLCClock) Now() (timestamp.Timestamp, timestamp.Timestamp) {
   237  	now := timestamp.Timestamp{
   238  		PhysicalTime: atomic.AddInt64(&c.pTime, 1),
   239  		//LogicalTime:  c.lTime,
   240  	}
   241  	return now, timestamp.Timestamp{PhysicalTime: now.PhysicalTime + int64(c.maxOffset)}
   242  }
   243  
   244  // TODO::will be removed
   245  func (c *MockHLCClock) Get() timestamp.Timestamp {
   246  	return timestamp.Timestamp{
   247  		PhysicalTime: atomic.LoadInt64(&c.pTime),
   248  		//LogicalTime:  c.lTime,
   249  	}
   250  }
   251  
   252  func (c *MockHLCClock) Update(m timestamp.Timestamp) {
   253  	atomic.StoreInt64(&c.pTime, m.PhysicalTime)
   254  	//atomic.StoreUint32(&c.lTime, m.LogicalTime)
   255  }
   256  
   257  func (c *MockHLCClock) HasNetworkLatency() bool {
   258  	return false
   259  }
   260  
   261  func (c *MockHLCClock) MaxOffset() time.Duration {
   262  	return c.maxOffset
   263  }
   264  
   265  func (c *MockHLCClock) SetNodeID(id uint16) {
   266  	// nothing to do.
   267  }
   268  
   269  var columnTypes = []Type{
   270  	T_int8.ToType(),
   271  	T_int16.ToType(),
   272  	T_int32.ToType(),
   273  	T_int64.ToType(),
   274  	T_uint8.ToType(),
   275  	T_uint16.ToType(),
   276  	T_uint32.ToType(),
   277  	T_uint64.ToType(),
   278  	T_float32.ToType(),
   279  	T_float64.ToType(),
   280  	T_date.ToType(),
   281  	T_datetime.ToType(),
   282  	T_varchar.ToType(),
   283  	T_char.ToType(),
   284  	T_bool.ToType(),
   285  	T_timestamp.ToType(),
   286  	T_decimal64.ToType(),
   287  	T_decimal128.ToType(),
   288  	T_binary.ToType(),
   289  	T_varbinary.ToType(),
   290  	T_enum.ToType(),
   291  	T_array_float32.ToType(),
   292  	T_array_float64.ToType(),
   293  	T_bit.ToType(),
   294  }
   295  
   296  func MockColTypes() (ct []Type) {
   297  	// set type bool's width to 8
   298  	columnTypes[14].Width = 8
   299  	return columnTypes
   300  }
   301  
   302  func CompareTSTSAligned(a, b TS) int {
   303  	return bytes.Compare(a[:], b[:])
   304  }