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  }