github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/txn/txnimpl/object.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 "context" 19 "sync" 20 21 "github.com/matrixorigin/matrixone/pkg/common/mpool" 22 "github.com/matrixorigin/matrixone/pkg/container/types" 23 "github.com/matrixorigin/matrixone/pkg/objectio" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 28 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 29 ) 30 31 // var newObjectCnt atomic.Int64 32 // var getObjectCnt atomic.Int64 33 // var putObjectCnt atomic.Int64 34 // func GetStatsString() string { 35 // return fmt.Sprintf( 36 // "NewObj: %d, GetObj: %d, PutObj: %d, NewBlk: %d, GetBlk: %d, PutBlk: %d", 37 // newObjectCnt.Load(), 38 // getObjectCnt.Load(), 39 // putObjectCnt.Load(), 40 // newBlockCnt.Load(), 41 // getBlockCnt.Load(), 42 // putBlockCnt.Load()) 43 // } 44 45 var ( 46 _objPool = sync.Pool{ 47 New: func() any { 48 // newObjectCnt.Add(1) 49 return &txnObject{} 50 }, 51 } 52 ) 53 54 type txnObject struct { 55 txnbase.TxnObject 56 entry *catalog.ObjectEntry 57 table *txnTable 58 } 59 60 type ObjectIt struct { 61 sync.RWMutex 62 linkIt *common.GenericSortedDListIt[*catalog.ObjectEntry] 63 curr *catalog.ObjectEntry 64 table *txnTable 65 err error 66 } 67 68 type composedObjectIt struct { 69 *ObjectIt 70 uncommitted *catalog.ObjectEntry 71 } 72 73 func newObjectItOnSnap(table *txnTable) handle.ObjectIt { 74 it := &ObjectIt{ 75 linkIt: table.entry.MakeObjectIt(true), 76 table: table, 77 } 78 var err error 79 var ok bool 80 for it.linkIt.Valid() { 81 curr := it.linkIt.Get().GetPayload() 82 curr.RLock() 83 ok, err = curr.IsVisibleWithLock(it.table.store.txn, curr.RWMutex) 84 if err != nil { 85 curr.RUnlock() 86 it.err = err 87 return it 88 } 89 if ok { 90 curr.RUnlock() 91 it.curr = curr 92 break 93 } 94 curr.RUnlock() 95 it.linkIt.Next() 96 } 97 return it 98 } 99 100 func newObjectIt(table *txnTable) handle.ObjectIt { 101 it := &ObjectIt{ 102 linkIt: table.entry.MakeObjectIt(true), 103 table: table, 104 } 105 var err error 106 var ok bool 107 for it.linkIt.Valid() { 108 curr := it.linkIt.Get().GetPayload() 109 curr.RLock() 110 ok, err = curr.IsVisibleWithLock(it.table.store.txn, curr.RWMutex) 111 if err != nil { 112 curr.RUnlock() 113 it.err = err 114 return it 115 } 116 if ok { 117 curr.RUnlock() 118 it.curr = curr 119 break 120 } 121 curr.RUnlock() 122 it.linkIt.Next() 123 } 124 if table.tableSpace != nil { 125 cit := &composedObjectIt{ 126 ObjectIt: it, 127 uncommitted: table.tableSpace.entry, 128 } 129 return cit 130 } 131 return it 132 } 133 134 func (it *ObjectIt) Close() error { return nil } 135 136 func (it *ObjectIt) GetError() error { return it.err } 137 func (it *ObjectIt) Valid() bool { 138 if it.err != nil { 139 return false 140 } 141 return it.linkIt.Valid() 142 } 143 144 func (it *ObjectIt) Next() { 145 var err error 146 var valid bool 147 for { 148 it.linkIt.Next() 149 node := it.linkIt.Get() 150 if node == nil { 151 it.curr = nil 152 break 153 } 154 entry := node.GetPayload() 155 entry.RLock() 156 valid, err = entry.IsVisibleWithLock(it.table.store.txn, entry.RWMutex) 157 entry.RUnlock() 158 if err != nil { 159 it.err = err 160 break 161 } 162 if valid { 163 it.curr = entry 164 break 165 } 166 } 167 } 168 169 func (it *ObjectIt) GetObject() handle.Object { 170 if isSysTableId(it.table.GetID()) { 171 return newSysObject(it.table, it.curr) 172 } 173 return newObject(it.table, it.curr) 174 } 175 176 func (cit *composedObjectIt) GetObject() handle.Object { 177 if cit.uncommitted != nil { 178 return newObject(cit.table, cit.uncommitted) 179 } 180 return cit.ObjectIt.GetObject() 181 } 182 183 func (cit *composedObjectIt) Valid() bool { 184 if cit.err != nil { 185 return false 186 } 187 if cit.uncommitted != nil { 188 return true 189 } 190 return cit.ObjectIt.Valid() 191 } 192 193 func (cit *composedObjectIt) Next() { 194 if cit.uncommitted != nil { 195 cit.uncommitted = nil 196 return 197 } 198 cit.ObjectIt.Next() 199 } 200 201 func newObject(table *txnTable, meta *catalog.ObjectEntry) *txnObject { 202 obj := _objPool.Get().(*txnObject) 203 // getObjectCnt.Add(1) 204 obj.Txn = table.store.txn 205 obj.table = table 206 obj.entry = meta 207 return obj 208 } 209 210 func (obj *txnObject) reset() { 211 obj.entry = nil 212 obj.table = nil 213 obj.TxnObject.Reset() 214 } 215 func buildObject(table *txnTable, meta *catalog.ObjectEntry) handle.Object { 216 if isSysTableId(meta.GetTable().ID) { 217 return newSysObject(table, meta) 218 } 219 return newObject(table, meta) 220 } 221 func (obj *txnObject) Close() (err error) { 222 obj.reset() 223 _objPool.Put(obj) 224 // putObjectCnt.Add(1) 225 return 226 } 227 func (obj *txnObject) GetTotalChanges() int { 228 return obj.entry.GetObjectData().GetTotalChanges() 229 } 230 func (obj *txnObject) RangeDelete(blkID uint16, start, end uint32, dt handle.DeleteType, mp *mpool.MPool) (err error) { 231 schema := obj.table.GetLocalSchema() 232 pkDef := schema.GetPrimaryKey() 233 pkVec := makeWorkspaceVector(pkDef.Type) 234 defer pkVec.Close() 235 for row := start; row <= end; row++ { 236 pkVal, _, err := obj.entry.GetObjectData().GetValue( 237 obj.table.store.GetContext(), obj.Txn, schema, blkID, int(row), pkDef.Idx, mp, 238 ) 239 if err != nil { 240 return err 241 } 242 pkVec.Append(pkVal, false) 243 } 244 id := obj.entry.AsCommonID() 245 id.SetBlockOffset(blkID) 246 return obj.Txn.GetStore().RangeDelete(id, start, end, pkVec, dt) 247 } 248 func (obj *txnObject) GetMeta() any { return obj.entry } 249 func (obj *txnObject) String() string { return obj.entry.String() } 250 func (obj *txnObject) GetID() *types.Objectid { return &obj.entry.ID } 251 func (obj *txnObject) BlkCnt() int { return obj.entry.BlockCnt() } 252 func (obj *txnObject) IsUncommitted() bool { 253 return obj.entry.IsLocal 254 } 255 256 func (obj *txnObject) IsAppendable() bool { return obj.entry.IsAppendable() } 257 258 func (obj *txnObject) SoftDeleteBlock(id types.Blockid) (err error) { 259 fp := obj.entry.AsCommonID() 260 fp.BlockID = id 261 return obj.Txn.GetStore().SoftDeleteBlock(fp) 262 } 263 264 func (obj *txnObject) GetRelation() (rel handle.Relation) { 265 return newRelation(obj.table) 266 } 267 268 func (obj *txnObject) UpdateStats(stats objectio.ObjectStats) error { 269 id := obj.entry.AsCommonID() 270 return obj.Txn.GetStore().UpdateObjectStats(id, &stats) 271 } 272 273 func (obj *txnObject) Prefetch(idxes []int) error { 274 schema := obj.table.GetLocalSchema() 275 seqnums := make([]uint16, 0, len(idxes)) 276 for _, idx := range idxes { 277 seqnums = append(seqnums, schema.ColDefs[idx].SeqNum) 278 } 279 if obj.IsUncommitted() { 280 return obj.table.tableSpace.Prefetch(obj.entry, seqnums) 281 } 282 for i := 0; i < obj.entry.BlockCnt(); i++ { 283 err := obj.entry.GetObjectData().Prefetch(seqnums, uint16(i)) 284 if err != nil { 285 return err 286 } 287 } 288 return nil 289 } 290 291 func (obj *txnObject) Fingerprint() *common.ID { return obj.entry.AsCommonID() } 292 293 func (obj *txnObject) GetByFilter( 294 ctx context.Context, filter *handle.Filter, mp *mpool.MPool, 295 ) (blkID uint16, offset uint32, err error) { 296 return obj.entry.GetObjectData().GetByFilter(ctx, obj.table.store.txn, filter, mp) 297 } 298 299 func (obj *txnObject) GetColumnDataById( 300 ctx context.Context, blkID uint16, colIdx int, mp *mpool.MPool, 301 ) (*containers.ColumnView, error) { 302 if obj.entry.IsLocal { 303 return obj.table.tableSpace.GetColumnDataById(ctx, obj.entry, colIdx, mp) 304 } 305 return obj.entry.GetObjectData().GetColumnDataById(ctx, obj.Txn, obj.table.GetLocalSchema(), blkID, colIdx, mp) 306 } 307 308 func (obj *txnObject) GetColumnDataByIds( 309 ctx context.Context, blkID uint16, colIdxes []int, mp *mpool.MPool, 310 ) (*containers.BlockView, error) { 311 if obj.entry.IsLocal { 312 return obj.table.tableSpace.GetColumnDataByIds(obj.entry, colIdxes, mp) 313 } 314 return obj.entry.GetObjectData().GetColumnDataByIds(ctx, obj.Txn, obj.table.GetLocalSchema(), blkID, colIdxes, mp) 315 } 316 317 func (obj *txnObject) GetColumnDataByName( 318 ctx context.Context, blkID uint16, attr string, mp *mpool.MPool, 319 ) (*containers.ColumnView, error) { 320 schema := obj.table.GetLocalSchema() 321 colIdx := schema.GetColIdx(attr) 322 if obj.entry.IsLocal { 323 return obj.table.tableSpace.GetColumnDataById(ctx, obj.entry, colIdx, mp) 324 } 325 return obj.entry.GetObjectData().GetColumnDataById(ctx, obj.Txn, schema, blkID, colIdx, mp) 326 } 327 328 func (obj *txnObject) GetColumnDataByNames( 329 ctx context.Context, blkID uint16, attrs []string, mp *mpool.MPool, 330 ) (*containers.BlockView, error) { 331 schema := obj.table.GetLocalSchema() 332 attrIds := make([]int, len(attrs)) 333 for i, attr := range attrs { 334 attrIds[i] = schema.GetColIdx(attr) 335 } 336 if obj.entry.IsLocal { 337 return obj.table.tableSpace.GetColumnDataByIds(obj.entry, attrIds, mp) 338 } 339 return obj.entry.GetObjectData().GetColumnDataByIds(ctx, obj.Txn, schema, blkID, attrIds, mp) 340 } 341 342 func (obj *txnObject) UpdateDeltaLoc(blkID uint16, deltaLoc objectio.Location) error { 343 id := obj.entry.AsCommonID() 344 id.SetBlockOffset(blkID) 345 return obj.table.store.UpdateDeltaLoc(id, deltaLoc) 346 }