github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/block.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 txnimpl 16 17 import ( 18 "bytes" 19 "sync" 20 21 "github.com/RoaringBitmap/roaring" 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 29 ) 30 31 type txnBlock struct { 32 *txnbase.TxnBlock 33 isUncommitted bool 34 entry *catalog.BlockEntry 35 table *txnTable 36 } 37 38 type blockIt struct { 39 sync.RWMutex 40 linkIt *common.GenericSortedDListIt[*catalog.BlockEntry] 41 curr *catalog.BlockEntry 42 table *txnTable 43 err error 44 } 45 46 type relBlockIt struct { 47 sync.RWMutex 48 rel handle.Relation 49 segmentIt handle.SegmentIt 50 blockIt handle.BlockIt 51 err error 52 } 53 54 func newBlockIt(table *txnTable, meta *catalog.SegmentEntry) *blockIt { 55 it := &blockIt{ 56 table: table, 57 linkIt: meta.MakeBlockIt(true), 58 } 59 var ok bool 60 var err error 61 for it.linkIt.Valid() { 62 curr := it.linkIt.Get().GetPayload() 63 curr.RLock() 64 ok, err = curr.IsVisible(it.table.store.txn.GetStartTS(), curr.RWMutex) 65 if err != nil { 66 curr.RUnlock() 67 it.err = err 68 break 69 } 70 if ok { 71 curr.RUnlock() 72 it.curr = curr 73 break 74 } 75 curr.RUnlock() 76 it.linkIt.Next() 77 } 78 return it 79 } 80 81 func (it *blockIt) Close() error { return nil } 82 83 func (it *blockIt) Valid() bool { 84 if it.err != nil { 85 return false 86 } 87 return it.linkIt.Valid() 88 } 89 90 func (it *blockIt) Next() { 91 var err error 92 var valid bool 93 for { 94 it.linkIt.Next() 95 node := it.linkIt.Get() 96 if node == nil { 97 it.curr = nil 98 break 99 } 100 entry := node.GetPayload() 101 entry.RLock() 102 valid, err = entry.IsVisible(it.table.store.txn.GetStartTS(), entry.RWMutex) 103 entry.RUnlock() 104 if err != nil { 105 it.err = err 106 break 107 } 108 if valid { 109 it.curr = entry 110 break 111 } 112 } 113 } 114 115 func (it *blockIt) GetError() error { 116 return it.err 117 } 118 119 func (it *blockIt) GetBlock() handle.Block { 120 return buildBlock(it.table, it.curr) 121 } 122 123 func buildBlock(table *txnTable, meta *catalog.BlockEntry) handle.Block { 124 if meta.GetSegment().GetTable().GetDB().IsSystemDB() { 125 return newSysBlock(table, meta) 126 } 127 return newBlock(table, meta) 128 } 129 130 func newBlock(table *txnTable, meta *catalog.BlockEntry) *txnBlock { 131 blk := &txnBlock{ 132 TxnBlock: &txnbase.TxnBlock{ 133 Txn: table.store.txn, 134 }, 135 entry: meta, 136 table: table, 137 isUncommitted: isLocalSegmentByID(meta.GetSegment().ID), 138 } 139 return blk 140 } 141 142 func (blk *txnBlock) GetMeta() any { return blk.entry } 143 func (blk *txnBlock) String() string { 144 if blk.isUncommitted { 145 return blk.entry.String() 146 } 147 blkData := blk.entry.GetBlockData() 148 return blkData.PPString(common.PPL1, 0, "") 149 // return blk.entry.String() 150 } 151 152 func (blk *txnBlock) IsUncommitted() bool { 153 return blk.isUncommitted 154 } 155 func (blk *txnBlock) GetTotalChanges() int { 156 return blk.entry.GetBlockData().GetTotalChanges() 157 } 158 func (blk *txnBlock) IsAppendableBlock() bool { return blk.entry.IsAppendable() } 159 func (blk *txnBlock) ID() uint64 { return blk.entry.GetID() } 160 func (blk *txnBlock) Fingerprint() *common.ID { return blk.entry.AsCommonID() } 161 func (blk *txnBlock) BatchDedup(pks containers.Vector, invisibility *roaring.Bitmap) (err error) { 162 blkData := blk.entry.GetBlockData() 163 blk.Txn.GetStore().LogBlockID(blk.getDBID(), blk.entry.GetSegment().GetTable().GetID(), blk.entry.GetID()) 164 return blkData.BatchDedup(blk.Txn, pks, invisibility, false) 165 } 166 167 func (blk *txnBlock) getDBID() uint64 { 168 return blk.entry.GetSegment().GetTable().GetDB().ID 169 } 170 171 func (blk *txnBlock) RangeDelete(start, end uint32, dt handle.DeleteType) (err error) { 172 return blk.Txn.GetStore().RangeDelete(blk.getDBID(), blk.entry.AsCommonID(), start, end, dt) 173 } 174 175 func (blk *txnBlock) GetMetaLoc() (metaloc string) { 176 return blk.entry.GetVisibleMetaLoc(blk.Txn.GetStartTS()) 177 } 178 func (blk *txnBlock) GetDeltaLoc() (deltaloc string) { 179 return blk.entry.GetVisibleDeltaLoc(blk.Txn.GetStartTS()) 180 } 181 func (blk *txnBlock) UpdateMetaLoc(metaloc string) (err error) { 182 blkID := blk.Fingerprint() 183 dbid := blk.GetMeta().(*catalog.BlockEntry).GetSegment().GetTable().GetDB().GetID() 184 err = blk.Txn.GetStore().UpdateMetaLoc(dbid, blkID, metaloc) 185 return 186 } 187 188 func (blk *txnBlock) UpdateDeltaLoc(deltaloc string) (err error) { 189 blkID := blk.Fingerprint() 190 dbid := blk.GetMeta().(*catalog.BlockEntry).GetSegment().GetTable().GetDB().GetID() 191 err = blk.Txn.GetStore().UpdateDeltaLoc(dbid, blkID, deltaloc) 192 return 193 } 194 195 // TODO: temp use coarse rows 196 func (blk *txnBlock) Rows() int { 197 if blk.isUncommitted { 198 return blk.table.localSegment.GetBlockRows(blk.entry) 199 } 200 return blk.entry.GetBlockData().Rows() 201 } 202 203 func (blk *txnBlock) GetColumnDataByIds(colIdxes []int, buffers []*bytes.Buffer) (*model.BlockView, error) { 204 if blk.isUncommitted { 205 return blk.table.localSegment.GetColumnDataByIds(blk.entry, colIdxes, buffers) 206 } 207 return blk.entry.GetBlockData().GetColumnDataByIds(blk.Txn, colIdxes, buffers) 208 } 209 210 func (blk *txnBlock) GetColumnDataByNames(attrs []string, buffers []*bytes.Buffer) (*model.BlockView, error) { 211 if blk.isUncommitted { 212 attrIds := make([]int, len(attrs)) 213 for i, attr := range attrs { 214 attrIds[i] = blk.table.entry.GetSchema().GetColIdx(attr) 215 } 216 return blk.table.localSegment.GetColumnDataByIds(blk.entry, attrIds, buffers) 217 } 218 return blk.entry.GetBlockData().GetColumnDataByNames(blk.Txn, attrs, buffers) 219 } 220 221 func (blk *txnBlock) GetColumnDataById(colIdx int, buffer *bytes.Buffer) (*model.ColumnView, error) { 222 if blk.isUncommitted { 223 return blk.table.localSegment.GetColumnDataById(blk.entry, colIdx, buffer) 224 } 225 return blk.entry.GetBlockData().GetColumnDataById(blk.Txn, colIdx, buffer) 226 } 227 func (blk *txnBlock) GetColumnDataByName(attr string, buffer *bytes.Buffer) (*model.ColumnView, error) { 228 if blk.isUncommitted { 229 attrId := blk.table.entry.GetSchema().GetColIdx(attr) 230 return blk.table.localSegment.GetColumnDataById(blk.entry, attrId, buffer) 231 } 232 return blk.entry.GetBlockData().GetColumnDataByName(blk.Txn, attr, buffer) 233 } 234 235 func (blk *txnBlock) LogTxnEntry(entry txnif.TxnEntry, readed []*common.ID) (err error) { 236 return blk.Txn.GetStore().LogTxnEntry(blk.getDBID(), blk.entry.GetSegment().GetTable().GetID(), entry, readed) 237 } 238 239 func (blk *txnBlock) GetSegment() (seg handle.Segment) { 240 seg = newSegment(blk.table, blk.entry.GetSegment()) 241 return 242 } 243 244 func (blk *txnBlock) GetByFilter(filter *handle.Filter) (offset uint32, err error) { 245 return blk.entry.GetBlockData().GetByFilter(blk.table.store.txn, filter) 246 } 247 248 // TODO: segmentit or tableit 249 func newRelationBlockIt(rel handle.Relation) *relBlockIt { 250 it := new(relBlockIt) 251 segmentIt := rel.MakeSegmentIt() 252 if !segmentIt.Valid() { 253 it.err = segmentIt.GetError() 254 return it 255 } 256 seg := segmentIt.GetSegment() 257 blockIt := seg.MakeBlockIt() 258 for !blockIt.Valid() { 259 segmentIt.Next() 260 if !segmentIt.Valid() { 261 it.err = segmentIt.GetError() 262 return it 263 } 264 seg = segmentIt.GetSegment() 265 blockIt = seg.MakeBlockIt() 266 } 267 it.blockIt = blockIt 268 it.segmentIt = segmentIt 269 it.rel = rel 270 it.err = blockIt.GetError() 271 return it 272 } 273 274 func (it *relBlockIt) Close() error { return nil } 275 func (it *relBlockIt) GetError() error { return it.err } 276 func (it *relBlockIt) Valid() bool { 277 var err error 278 if it.err != nil { 279 return false 280 } 281 if it.segmentIt == nil { 282 return false 283 } 284 if !it.segmentIt.Valid() { 285 if err = it.segmentIt.GetError(); err != nil { 286 it.err = err 287 } 288 return false 289 } 290 if it.blockIt.Valid() { 291 return true 292 } 293 294 if err = it.blockIt.GetError(); err != nil { 295 it.err = err 296 } 297 if it.err != nil { 298 return false 299 } 300 var seg handle.Segment 301 for { 302 it.segmentIt.Next() 303 if !it.segmentIt.Valid() { 304 if err = it.segmentIt.GetError(); err != nil { 305 it.err = err 306 } 307 return false 308 } 309 seg = it.segmentIt.GetSegment() 310 meta := seg.GetMeta().(*catalog.SegmentEntry) 311 meta.RLock() 312 cnt := meta.BlockCnt() 313 meta.RUnlock() 314 if cnt != 0 { 315 break 316 } 317 } 318 it.blockIt = seg.MakeBlockIt() 319 if err = it.blockIt.GetError(); err != nil { 320 it.err = err 321 } 322 return it.blockIt.Valid() 323 } 324 325 func (it *relBlockIt) GetBlock() handle.Block { 326 return it.blockIt.GetBlock() 327 } 328 329 func (it *relBlockIt) Next() { 330 it.blockIt.Next() 331 if it.blockIt.Valid() { 332 return 333 } 334 it.segmentIt.Next() 335 if !it.segmentIt.Valid() { 336 return 337 } 338 seg := it.segmentIt.GetSegment() 339 it.blockIt = seg.MakeBlockIt() 340 for !it.blockIt.Valid() { 341 it.segmentIt.Next() 342 if !it.segmentIt.Valid() { 343 return 344 } 345 seg := it.segmentIt.GetSegment() 346 it.blockIt = seg.MakeBlockIt() 347 } 348 }