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 }