github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/catalog/tablebase.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 catalog 16 17 import ( 18 "encoding/binary" 19 "fmt" 20 "io" 21 "sync" 22 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/container/types" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 28 ) 29 30 type TableBaseEntry struct { 31 *txnbase.MVCCChain 32 ID uint64 33 } 34 35 func NewReplayTableBaseEntry() *TableBaseEntry { 36 be := &TableBaseEntry{ 37 MVCCChain: txnbase.NewMVCCChain(CompareTableBaseNode, NewEmptyTableMVCCNode), 38 } 39 return be 40 } 41 42 func NewTableBaseEntry(id uint64) *TableBaseEntry { 43 return &TableBaseEntry{ 44 ID: id, 45 MVCCChain: txnbase.NewMVCCChain(CompareTableBaseNode, NewEmptyTableMVCCNode), 46 } 47 } 48 49 func (be *TableBaseEntry) StringLocked() string { 50 return fmt.Sprintf("[%d]%s", be.ID, be.MVCCChain.StringLocked()) 51 } 52 53 func (be *TableBaseEntry) String() string { 54 be.RLock() 55 defer be.RUnlock() 56 return be.StringLocked() 57 } 58 59 func (be *TableBaseEntry) PPString(level common.PPLevel, depth int, prefix string) string { 60 s := fmt.Sprintf("%s%s%s", common.RepeatStr("\t", depth), prefix, be.StringLocked()) 61 return s 62 } 63 64 func (be *TableBaseEntry) TryGetTerminatedTS(waitIfcommitting bool) (terminated bool, TS types.TS) { 65 node := be.GetLatestCommittedNode() 66 if node == nil { 67 return 68 } 69 if node.(*TableMVCCNode).HasDropCommitted() { 70 return true, node.(*TableMVCCNode).DeletedAt 71 } 72 return 73 } 74 func (be *TableBaseEntry) GetID() uint64 { return be.ID } 75 76 func (be *TableBaseEntry) CreateWithTS(ts types.TS) { 77 node := &TableMVCCNode{ 78 EntryMVCCNode: &EntryMVCCNode{ 79 CreatedAt: ts, 80 }, 81 TxnMVCCNode: txnbase.NewTxnMVCCNodeWithTS(ts), 82 } 83 be.Insert(node) 84 } 85 86 func (be *TableBaseEntry) CreateWithTxn(txn txnif.AsyncTxn, schema *Schema) { 87 node := &TableMVCCNode{ 88 EntryMVCCNode: &EntryMVCCNode{ 89 CreatedAt: txnif.UncommitTS, 90 }, 91 TxnMVCCNode: txnbase.NewTxnMVCCNodeWithTxn(txn), 92 SchemaConstraints: string(schema.Constraint), 93 } 94 be.Insert(node) 95 } 96 97 func (be *TableBaseEntry) getOrSetUpdateNode(txn txnif.TxnReader) (newNode bool, node *TableMVCCNode) { 98 entry := be.GetLatestNodeLocked() 99 if entry.IsSameTxn(txn.GetStartTS()) { 100 return false, entry.(*TableMVCCNode) 101 } else { 102 node := entry.CloneData().(*TableMVCCNode) 103 node.TxnMVCCNode = txnbase.NewTxnMVCCNodeWithTxn(txn) 104 be.Insert(node) 105 return true, node 106 } 107 } 108 109 func (be *TableBaseEntry) DeleteLocked(txn txnif.TxnReader) (isNewNode bool, err error) { 110 var entry *TableMVCCNode 111 isNewNode, entry = be.getOrSetUpdateNode(txn) 112 entry.Delete() 113 return 114 } 115 116 func (be *TableBaseEntry) UpdateConstraint(txn txnif.TxnReader, cstr []byte) (isNewNode bool, err error) { 117 be.Lock() 118 defer be.Unlock() 119 needWait, txnToWait := be.NeedWaitCommitting(txn.GetStartTS()) 120 if needWait { 121 be.Unlock() 122 txnToWait.GetTxnState(true) 123 be.Lock() 124 } 125 err = be.CheckConflict(txn) 126 if err != nil { 127 return 128 } 129 var entry *TableMVCCNode 130 isNewNode, entry = be.getOrSetUpdateNode(txn) 131 entry.SchemaConstraints = string(cstr) 132 return 133 } 134 135 func (be *TableBaseEntry) DeleteBefore(ts types.TS) bool { 136 createAt := be.GetDeleteAt() 137 if createAt.IsEmpty() { 138 return false 139 } 140 return createAt.Less(ts) 141 } 142 143 func (be *TableBaseEntry) NeedWaitCommitting(startTS types.TS) (bool, txnif.TxnReader) { 144 un := be.GetLatestNodeLocked() 145 if un == nil { 146 return false, nil 147 } 148 return un.NeedWaitCommitting(startTS) 149 } 150 151 func (be *TableBaseEntry) HasDropCommitted() bool { 152 be.RLock() 153 defer be.RUnlock() 154 return be.HasDropCommittedLocked() 155 } 156 157 func (be *TableBaseEntry) HasDropCommittedLocked() bool { 158 un := be.GetLatestCommittedNode() 159 if un == nil { 160 return false 161 } 162 return un.(*TableMVCCNode).HasDropCommitted() 163 } 164 165 func (be *TableBaseEntry) DoCompre(voe BaseEntry) int { 166 oe := voe.(*TableBaseEntry) 167 be.RLock() 168 defer be.RUnlock() 169 oe.RLock() 170 defer oe.RUnlock() 171 return CompareUint64(be.ID, oe.ID) 172 } 173 174 func (be *TableBaseEntry) ensureVisibleAndNotDropped(ts types.TS) bool { 175 visible, dropped := be.GetVisibilityLocked(ts) 176 if !visible { 177 return false 178 } 179 return !dropped 180 } 181 182 func (be *TableBaseEntry) GetVisibilityLocked(ts types.TS) (visible, dropped bool) { 183 un := be.GetVisibleNode(ts) 184 if un == nil { 185 return 186 } 187 visible = true 188 if un.IsSameTxn(ts) { 189 dropped = un.(*TableMVCCNode).HasDropIntent() 190 } else { 191 dropped = un.(*TableMVCCNode).HasDropCommitted() 192 } 193 return 194 } 195 196 func (be *TableBaseEntry) IsVisible(ts types.TS, mu *sync.RWMutex) (ok bool, err error) { 197 needWait, txnToWait := be.NeedWaitCommitting(ts) 198 if needWait { 199 mu.RUnlock() 200 txnToWait.GetTxnState(true) 201 mu.RLock() 202 } 203 ok = be.ensureVisibleAndNotDropped(ts) 204 return 205 } 206 207 func (be *TableBaseEntry) DropEntryLocked(txnCtx txnif.TxnReader) (isNewNode bool, err error) { 208 err = be.CheckConflict(txnCtx) 209 if err != nil { 210 return 211 } 212 if be.HasDropCommittedLocked() { 213 return false, moerr.GetOkExpectedEOB() 214 } 215 isNewNode, err = be.DeleteLocked(txnCtx) 216 return 217 } 218 219 func (be *TableBaseEntry) PrepareAdd(txn txnif.TxnReader) (err error) { 220 be.RLock() 221 defer be.RUnlock() 222 if txn != nil { 223 needWait, waitTxn := be.NeedWaitCommitting(txn.GetStartTS()) 224 if needWait { 225 be.RUnlock() 226 waitTxn.GetTxnState(true) 227 be.RLock() 228 } 229 err = be.CheckConflict(txn) 230 if err != nil { 231 return 232 } 233 } 234 if txn == nil || be.GetTxn() != txn { 235 if !be.HasDropCommittedLocked() { 236 return moerr.GetOkExpectedDup() 237 } 238 } else { 239 if be.ensureVisibleAndNotDropped(txn.GetStartTS()) { 240 return moerr.GetOkExpectedDup() 241 } 242 } 243 return 244 } 245 246 func (be *TableBaseEntry) DeleteAfter(ts types.TS) bool { 247 un := be.GetLatestNodeLocked() 248 if un == nil { 249 return false 250 } 251 return un.(*TableMVCCNode).DeletedAt.Greater(ts) 252 } 253 254 func (be *TableBaseEntry) CloneCommittedInRange(start, end types.TS) BaseEntry { 255 chain := be.MVCCChain.CloneCommittedInRange(start, end) 256 if chain == nil { 257 return nil 258 } 259 return &TableBaseEntry{ 260 MVCCChain: chain, 261 ID: be.ID, 262 } 263 } 264 265 func (be *TableBaseEntry) GetCreatedAt() types.TS { 266 un := be.GetLatestNodeLocked() 267 if un == nil { 268 return types.TS{} 269 } 270 return un.(*TableMVCCNode).CreatedAt 271 } 272 273 func (be *TableBaseEntry) GetDeleteAt() types.TS { 274 un := be.GetLatestNodeLocked() 275 if un == nil { 276 return types.TS{} 277 } 278 return un.(*TableMVCCNode).DeletedAt 279 } 280 281 func (be *TableBaseEntry) GetVisibility(ts types.TS) (visible, dropped bool) { 282 be.RLock() 283 defer be.RUnlock() 284 needWait, txnToWait := be.NeedWaitCommitting(ts) 285 if needWait { 286 be.RUnlock() 287 txnToWait.GetTxnState(true) 288 be.RLock() 289 } 290 return be.GetVisibilityLocked(ts) 291 } 292 func (be *TableBaseEntry) WriteOneNodeTo(w io.Writer) (n int64, err error) { 293 if err = binary.Write(w, binary.BigEndian, be.ID); err != nil { 294 return 295 } 296 n += 8 297 var sn int64 298 sn, err = be.MVCCChain.WriteOneNodeTo(w) 299 if err != nil { 300 return 301 } 302 n += sn 303 return 304 } 305 func (be *TableBaseEntry) WriteAllTo(w io.Writer) (n int64, err error) { 306 if err = binary.Write(w, binary.BigEndian, be.ID); err != nil { 307 return 308 } 309 n += 8 310 var sn int64 311 sn, err = be.MVCCChain.WriteAllTo(w) 312 if err != nil { 313 return 314 } 315 n += sn 316 return 317 } 318 func (be *TableBaseEntry) ReadOneNodeFrom(r io.Reader) (n int64, err error) { 319 if err = binary.Read(r, binary.BigEndian, &be.ID); err != nil { 320 return 321 } 322 n += 8 323 var sn int64 324 sn, err = be.MVCCChain.ReadOneNodeFrom(r) 325 if err != nil { 326 return 327 } 328 n += sn 329 return 330 } 331 func (be *TableBaseEntry) ReadAllFrom(r io.Reader) (n int64, err error) { 332 if err = binary.Read(r, binary.BigEndian, &be.ID); err != nil { 333 return 334 } 335 n += 8 336 var sn int64 337 sn, err = be.MVCCChain.ReadAllFrom(r) 338 if err != nil { 339 return 340 } 341 n += sn 342 return 343 }