github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/txn/txnimpl/table_space.go (about)

     1  // Copyright 2022 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  	"fmt"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/container/types"
    22  	"github.com/matrixorigin/matrixone/pkg/objectio"
    23  
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    25  
    26  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    27  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
    32  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle"
    33  )
    34  
    35  type tableSpace struct {
    36  	entry *catalog.ObjectEntry
    37  
    38  	appendable InsertNode
    39  	//index for primary key
    40  	index TableIndex
    41  	//nodes contains anode and node.
    42  	nodes       []InsertNode
    43  	table       *txnTable
    44  	rows        uint32
    45  	appends     []*appendCtx
    46  	tableHandle data.TableHandle
    47  	nobj        handle.Object
    48  
    49  	stats []objectio.ObjectStats
    50  }
    51  
    52  func newTableSpace(table *txnTable) *tableSpace {
    53  	return &tableSpace{
    54  		entry: catalog.NewStandaloneObject(
    55  			table.entry,
    56  			table.store.txn.GetStartTS()),
    57  		nodes:   make([]InsertNode, 0),
    58  		index:   NewSimpleTableIndex(),
    59  		appends: make([]*appendCtx, 0),
    60  		table:   table,
    61  	}
    62  }
    63  
    64  func (space *tableSpace) GetLocalPhysicalAxis(row uint32) (int, uint32) {
    65  	var sum uint32
    66  	for i, node := range space.nodes {
    67  		sum += node.Rows()
    68  		if row <= sum-1 {
    69  			return i, node.Rows() - (sum - (row + 1)) - 1
    70  		}
    71  	}
    72  	panic("Invalid row ")
    73  }
    74  
    75  // register a non-appendable insertNode.
    76  func (space *tableSpace) registerStats(stats objectio.ObjectStats) {
    77  	if space.stats == nil {
    78  		space.stats = make([]objectio.ObjectStats, 0)
    79  	}
    80  	space.stats = append(space.stats, stats)
    81  }
    82  
    83  func (space *tableSpace) isStatsExisted(o objectio.ObjectStats) bool {
    84  	for _, stats := range space.stats {
    85  		if stats.ObjectName().Equal(o.ObjectName()) {
    86  			return true
    87  		}
    88  	}
    89  	return false
    90  }
    91  
    92  // register an appendable insertNode.
    93  func (space *tableSpace) registerANode() {
    94  	n := NewANode(
    95  		space.table,
    96  		space.entry,
    97  	)
    98  	space.appendable = n
    99  	space.nodes = append(space.nodes, n)
   100  }
   101  
   102  // ApplyAppend applies all the anodes into appendable blocks
   103  // and un-reference the appendable blocks which had been referenced when PrepareApply.
   104  func (space *tableSpace) ApplyAppend() (err error) {
   105  	var destOff int
   106  	defer func() {
   107  		// Close All unclosed Appends:un-reference the appendable block.
   108  		space.CloseAppends()
   109  	}()
   110  	for _, ctx := range space.appends {
   111  		bat, _ := ctx.node.Window(ctx.start, ctx.start+ctx.count)
   112  		defer bat.Close()
   113  		if destOff, err = ctx.driver.ApplyAppend(
   114  			bat,
   115  			space.table.store.txn); err != nil {
   116  			return
   117  		}
   118  		id := ctx.driver.GetID()
   119  		ctx.node.AddApplyInfo(
   120  			ctx.start,
   121  			ctx.count,
   122  			uint32(destOff),
   123  			ctx.count, id)
   124  	}
   125  	if space.tableHandle != nil {
   126  		space.table.entry.GetTableData().ApplyHandle(space.tableHandle)
   127  	}
   128  	return
   129  }
   130  
   131  func (space *tableSpace) PrepareApply() (err error) {
   132  	defer func() {
   133  		if err != nil {
   134  			// Close All unclosed Appends: un-reference all the appendable blocks.
   135  			space.CloseAppends()
   136  		}
   137  	}()
   138  	for _, node := range space.nodes {
   139  		if err = space.prepareApplyNode(node); err != nil {
   140  			return
   141  		}
   142  	}
   143  	for _, stats := range space.stats {
   144  		if err = space.prepareApplyObjectStats(stats); err != nil {
   145  			return
   146  		}
   147  	}
   148  	return
   149  }
   150  
   151  func (space *tableSpace) prepareApplyANode(node *anode) error {
   152  	node.Compact()
   153  	tableData := space.table.entry.GetTableData()
   154  	if space.tableHandle == nil {
   155  		space.tableHandle = tableData.GetHandle()
   156  	}
   157  	appended := uint32(0)
   158  	vec := space.table.store.rt.VectorPool.Small.GetVector(&objectio.RowidType)
   159  	for appended < node.Rows() {
   160  		appender, err := space.tableHandle.GetAppender()
   161  		if moerr.IsMoErrCode(err, moerr.ErrAppendableObjectNotFound) {
   162  			objH, err := space.table.CreateObject(true)
   163  			if err != nil {
   164  				return err
   165  			}
   166  			appender = space.tableHandle.SetAppender(objH.Fingerprint())
   167  			objH.Close()
   168  		}
   169  		if !appender.IsSameColumns(space.table.GetLocalSchema()) {
   170  			return moerr.NewInternalErrorNoCtx("schema changed, please rollback and retry")
   171  		}
   172  
   173  		// see more notes in flushtabletail.go
   174  		/// ----------- Choose a ablock ---------
   175  		appender.LockFreeze()
   176  		// no one can touch freeze for now, check it
   177  		if appender.CheckFreeze() {
   178  			// freezed, try to find another ablock
   179  			appender.UnlockFreeze()
   180  			continue
   181  		}
   182  
   183  		// hold freezelock to attach AppendNode
   184  		//PrepareAppend: It is very important that appending a AppendNode into
   185  		// block's MVCCHandle before applying data into block.
   186  		anode, created, toAppend, err := appender.PrepareAppend(
   187  			node.Rows()-appended,
   188  			space.table.store.txn)
   189  		if err != nil {
   190  			appender.UnlockFreeze()
   191  			return err
   192  		}
   193  		appender.UnlockFreeze()
   194  		/// ------- Attach AppendNode Successfully -----
   195  
   196  		objID := appender.GetMeta().(*catalog.ObjectEntry).ID
   197  		col := space.table.store.rt.VectorPool.Small.GetVector(&objectio.RowidType)
   198  		defer col.Close()
   199  		blkID := objectio.NewBlockidWithObjectID(&objID, 0)
   200  		if err = objectio.ConstructRowidColumnTo(
   201  			col.GetDownstreamVector(),
   202  			blkID,
   203  			anode.GetMaxRow()-toAppend,
   204  			toAppend,
   205  			col.GetAllocator(),
   206  		); err != nil {
   207  			return err
   208  		}
   209  		if err = vec.ExtendVec(col.GetDownstreamVector()); err != nil {
   210  			return err
   211  		}
   212  		ctx := &appendCtx{
   213  			driver: appender,
   214  			node:   node,
   215  			anode:  anode,
   216  			start:  appended,
   217  			count:  toAppend,
   218  		}
   219  		if created {
   220  			space.table.store.IncreateWriteCnt()
   221  			space.table.txnEntries.Append(anode)
   222  		}
   223  		id := appender.GetID()
   224  		space.table.store.warChecker.Insert(appender.GetMeta().(*catalog.ObjectEntry))
   225  		space.table.store.txn.GetMemo().AddObject(space.table.entry.GetDB().ID,
   226  			id.TableID, id.ObjectID())
   227  		space.appends = append(space.appends, ctx)
   228  		// logutil.Debugf("%s: toAppend %d, appended %d, blks=%d",
   229  		// 	id.String(), toAppend, appended, len(space.appends))
   230  		appended += toAppend
   231  		if appended == node.Rows() {
   232  			break
   233  		}
   234  	}
   235  	node.data.Vecs[space.table.GetLocalSchema().PhyAddrKey.Idx].Close()
   236  	node.data.Vecs[space.table.GetLocalSchema().PhyAddrKey.Idx] = vec
   237  	return nil
   238  }
   239  
   240  func (space *tableSpace) prepareApplyObjectStats(stats objectio.ObjectStats) (err error) {
   241  	sid := stats.ObjectName().ObjectId()
   242  	shouldCreateNewObj := func() bool {
   243  		if space.nobj == nil {
   244  			return true
   245  		}
   246  		entry := space.nobj.GetMeta().(*catalog.ObjectEntry)
   247  		return !entry.ID.Eq(*sid)
   248  	}
   249  
   250  	if shouldCreateNewObj() {
   251  		space.nobj, err = space.table.CreateNonAppendableObject(true, new(objectio.CreateObjOpt).WithId(sid))
   252  		if err != nil {
   253  			return
   254  		}
   255  		space.nobj.GetMeta().(*catalog.ObjectEntry).SetSorted()
   256  		err = space.nobj.UpdateStats(stats)
   257  		if err != nil {
   258  			return
   259  		}
   260  	}
   261  
   262  	return
   263  }
   264  
   265  func (space *tableSpace) prepareApplyNode(node InsertNode) (err error) {
   266  	if !node.IsPersisted() {
   267  		return space.prepareApplyANode(node.(*anode))
   268  	}
   269  	return nil
   270  }
   271  
   272  // CloseAppends un-reference the appendable blocks
   273  func (space *tableSpace) CloseAppends() {
   274  	for _, ctx := range space.appends {
   275  		if ctx.driver != nil {
   276  			ctx.driver.Close()
   277  			ctx.driver = nil
   278  		}
   279  	}
   280  }
   281  
   282  // Append appends batch of data into anode.
   283  func (space *tableSpace) Append(data *containers.Batch) (err error) {
   284  	if space.appendable == nil {
   285  		space.registerANode()
   286  	}
   287  	appended := uint32(0)
   288  	offset := uint32(0)
   289  	length := uint32(data.Length())
   290  	schema := space.table.GetLocalSchema()
   291  	for {
   292  		h := space.appendable
   293  		appended, err = h.Append(data, offset)
   294  		if err != nil {
   295  			return
   296  		}
   297  		dedupType := space.table.store.txn.GetDedupType()
   298  		if schema.HasPK() && dedupType == txnif.FullDedup {
   299  			if err = space.index.BatchInsert(
   300  				data.Attrs[schema.GetSingleSortKeyIdx()],
   301  				data.Vecs[schema.GetSingleSortKeyIdx()],
   302  				int(offset),
   303  				int(appended),
   304  				space.rows,
   305  				false); err != nil {
   306  				break
   307  			}
   308  		}
   309  		offset += appended
   310  		space.rows += appended
   311  		if offset >= length {
   312  			break
   313  		}
   314  	}
   315  	return
   316  }
   317  
   318  // AddObjsWithMetaLoc transfers blocks with meta location into non-appendable nodes
   319  func (space *tableSpace) AddObjsWithMetaLoc(
   320  	pkVecs []containers.Vector,
   321  	stats objectio.ObjectStats,
   322  ) (err error) {
   323  	space.registerStats(stats)
   324  	for i := range pkVecs {
   325  		dedupType := space.table.store.txn.GetDedupType()
   326  		//insert primary keys into space.index
   327  		if pkVecs != nil && dedupType == txnif.FullDedup {
   328  			if err = space.index.BatchInsert(
   329  				space.table.GetLocalSchema().GetSingleSortKey().Name,
   330  				pkVecs[i],
   331  				0,
   332  				pkVecs[i].Length(),
   333  				space.rows,
   334  				false,
   335  			); err != nil {
   336  				return
   337  			}
   338  			space.rows += uint32(pkVecs[i].Length())
   339  		}
   340  	}
   341  	return nil
   342  }
   343  
   344  func (space *tableSpace) DeleteFromIndex(from, to uint32, node InsertNode) (err error) {
   345  	schema := space.table.GetLocalSchema()
   346  	for i := from; i <= to; i++ {
   347  		v, _, err := node.GetValue(schema.GetSingleSortKeyIdx(), i)
   348  		if err != nil {
   349  			return err
   350  		}
   351  		if err = space.index.Delete(v); err != nil {
   352  			return err
   353  		}
   354  	}
   355  	return
   356  }
   357  
   358  // RangeDelete delete rows : [start, end]
   359  func (space *tableSpace) RangeDelete(start, end uint32) error {
   360  	first, firstOffset := space.GetLocalPhysicalAxis(start)
   361  	last, lastOffset := space.GetLocalPhysicalAxis(end)
   362  	var err error
   363  	if last == first {
   364  		node := space.nodes[first]
   365  		err = node.RangeDelete(firstOffset, lastOffset)
   366  		if err != nil {
   367  			return err
   368  		}
   369  		if !space.table.GetLocalSchema().HasPK() {
   370  			// If no pk defined
   371  			return err
   372  		}
   373  		err = space.DeleteFromIndex(firstOffset, lastOffset, node)
   374  		return err
   375  	}
   376  
   377  	node := space.nodes[first]
   378  	if err = node.RangeDelete(firstOffset, node.Rows()-1); err != nil {
   379  
   380  		return err
   381  	}
   382  	if err = space.DeleteFromIndex(firstOffset, node.Rows()-1, node); err != nil {
   383  		return err
   384  	}
   385  	node = space.nodes[last]
   386  	if err = node.RangeDelete(0, lastOffset); err != nil {
   387  		return err
   388  	}
   389  	if err = space.DeleteFromIndex(0, lastOffset, node); err != nil {
   390  		return err
   391  	}
   392  	if last > first+1 {
   393  		for i := first + 1; i < last; i++ {
   394  			node = space.nodes[i]
   395  			if err = node.RangeDelete(0, node.Rows()-1); err != nil {
   396  				break
   397  			}
   398  			if err = space.DeleteFromIndex(0, node.Rows()-1, node); err != nil {
   399  				break
   400  			}
   401  		}
   402  	}
   403  	return err
   404  }
   405  
   406  // CollectCmd collect txnCmd for anode whose data resides in memory.
   407  func (space *tableSpace) CollectCmd(cmdMgr *commandManager) (err error) {
   408  	for _, node := range space.nodes {
   409  		csn := uint32(0xffff) // Special cmd
   410  		cmd, err := node.MakeCommand(csn)
   411  		if err != nil {
   412  			panic(err)
   413  		}
   414  		if cmd != nil {
   415  			cmdMgr.AddInternalCmd(cmd)
   416  		}
   417  	}
   418  	return
   419  }
   420  
   421  func (space *tableSpace) DeletesToString() string {
   422  	var s string
   423  	for i, n := range space.nodes {
   424  		s = fmt.Sprintf("%s\t<INode-%d>: %s\n", s, i, n.PrintDeletes())
   425  	}
   426  	return s
   427  }
   428  
   429  func (space *tableSpace) IsDeleted(row uint32) bool {
   430  	npos, noffset := space.GetLocalPhysicalAxis(row)
   431  	n := space.nodes[npos]
   432  	return n.IsRowDeleted(noffset)
   433  }
   434  
   435  func (space *tableSpace) Rows() (n uint32) {
   436  	for _, node := range space.nodes {
   437  		n += node.Rows()
   438  	}
   439  	return
   440  }
   441  
   442  func (space *tableSpace) GetByFilter(filter *handle.Filter) (id *common.ID, offset uint32, err error) {
   443  	if !space.table.GetLocalSchema().HasPK() {
   444  		id = space.table.entry.AsCommonID()
   445  		rid := filter.Val.(types.Rowid)
   446  		id.BlockID, offset = rid.Decode()
   447  		return
   448  	}
   449  	id = space.entry.AsCommonID()
   450  	if v, ok := filter.Val.([]byte); ok {
   451  		offset, err = space.index.Search(string(v))
   452  	} else {
   453  		offset, err = space.index.Search(filter.Val)
   454  	}
   455  	if err != nil {
   456  		return
   457  	}
   458  	return
   459  }
   460  
   461  func (space *tableSpace) GetPKColumn() containers.Vector {
   462  	schema := space.table.entry.GetLastestSchemaLocked()
   463  	return space.index.KeyToVector(schema.GetSingleSortKeyType())
   464  }
   465  
   466  func (space *tableSpace) GetPKVecs() []containers.Vector {
   467  	schema := space.table.entry.GetLastestSchemaLocked()
   468  	return space.index.KeyToVectors(schema.GetSingleSortKeyType())
   469  }
   470  
   471  func (space *tableSpace) BatchDedup(key containers.Vector) error {
   472  	return space.index.BatchDedup(space.table.GetLocalSchema().GetSingleSortKey().Name, key)
   473  }
   474  
   475  func (space *tableSpace) GetColumnDataByIds(
   476  	obj *catalog.ObjectEntry,
   477  	colIdxes []int,
   478  	mp *mpool.MPool,
   479  ) (view *containers.BlockView, err error) {
   480  	n := space.nodes[0]
   481  	return n.GetColumnDataByIds(colIdxes, mp)
   482  }
   483  
   484  func (space *tableSpace) GetColumnDataById(
   485  	ctx context.Context,
   486  	obj *catalog.ObjectEntry,
   487  	colIdx int,
   488  	mp *mpool.MPool,
   489  ) (view *containers.ColumnView, err error) {
   490  	n := space.nodes[0]
   491  	return n.GetColumnDataById(ctx, colIdx, mp)
   492  }
   493  
   494  func (space *tableSpace) Prefetch(obj *catalog.ObjectEntry, idxes []uint16) error {
   495  	n := space.nodes[0]
   496  	return n.Prefetch(idxes)
   497  }
   498  
   499  func (space *tableSpace) GetValue(row uint32, col uint16) (any, bool, error) {
   500  	npos, noffset := space.GetLocalPhysicalAxis(row)
   501  	n := space.nodes[npos]
   502  	return n.GetValue(int(col), noffset)
   503  }
   504  
   505  // Close free the resource when transaction commits.
   506  func (space *tableSpace) Close() (err error) {
   507  	for _, node := range space.nodes {
   508  		if err = node.Close(); err != nil {
   509  			return
   510  		}
   511  	}
   512  	space.index.Close()
   513  	space.index = nil
   514  	space.nodes = nil
   515  	space.appendable = nil
   516  	return
   517  }