github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/anode.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  	"github.com/matrixorigin/matrixone/pkg/objectio"
    20  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer/base"
    21  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    28  )
    29  
    30  // anode corresponds to an appendable standalone-uncommitted block
    31  // which belongs to txn's workspace and can be appended data into.
    32  type anode struct {
    33  	*baseNode
    34  }
    35  
    36  // NewANode creates a InsertNode with data in memory.
    37  func NewANode(
    38  	tbl *txnTable,
    39  	fs *objectio.ObjectFS,
    40  	mgr base.INodeManager,
    41  	sched tasks.TaskScheduler,
    42  	meta *catalog.BlockEntry,
    43  ) *anode {
    44  	impl := new(anode)
    45  	impl.baseNode = newBaseNode(tbl, fs, mgr, sched, meta)
    46  	impl.storage.mnode = newMemoryNode(impl.baseNode)
    47  	impl.storage.mnode.Ref()
    48  	return impl
    49  }
    50  
    51  func (n *anode) GetAppends() []*appendInfo {
    52  	return n.storage.mnode.appends
    53  }
    54  func (n *anode) AddApplyInfo(srcOff, srcLen, destOff, destLen uint32, dbid uint64, dest *common.ID) *appendInfo {
    55  	seq := len(n.storage.mnode.appends)
    56  	info := &appendInfo{
    57  		dest:    dest,
    58  		destOff: destOff,
    59  		destLen: destLen,
    60  		dbid:    dbid,
    61  		srcOff:  srcOff,
    62  		srcLen:  srcLen,
    63  		seq:     uint32(seq),
    64  	}
    65  	n.storage.mnode.appends = append(n.storage.mnode.appends, info)
    66  	return info
    67  }
    68  
    69  func (n *anode) MakeCommand(id uint32) (cmd txnif.TxnCmd, err error) {
    70  	if n.IsPersisted() {
    71  		return nil, nil
    72  	}
    73  	if n.storage.mnode.data == nil {
    74  		return
    75  	}
    76  	composedCmd := NewAppendCmd(id, n)
    77  	batCmd := txnbase.NewBatchCmd(n.storage.mnode.data)
    78  	composedCmd.AddCmd(batCmd)
    79  	return composedCmd, nil
    80  }
    81  
    82  func (n *anode) Close() (err error) {
    83  	if n.storage.mnode.data != nil {
    84  		n.storage.mnode.data.Close()
    85  	}
    86  	return
    87  }
    88  
    89  func (n *anode) Append(data *containers.Batch, offset uint32) (an uint32, err error) {
    90  	schema := n.table.entry.GetSchema()
    91  	if n.storage.mnode.data == nil {
    92  		opts := containers.Options{}
    93  		opts.Capacity = data.Length() - int(offset)
    94  		if opts.Capacity > int(txnbase.MaxNodeRows) {
    95  			opts.Capacity = int(txnbase.MaxNodeRows)
    96  		}
    97  		n.storage.mnode.data = containers.BuildBatch(
    98  			schema.AllNames(),
    99  			schema.AllTypes(),
   100  			schema.AllNullables(),
   101  			opts)
   102  	}
   103  
   104  	from := uint32(n.storage.mnode.data.Length())
   105  	an = n.storage.mnode.PrepareAppend(data, offset)
   106  	for _, attr := range data.Attrs {
   107  		if attr == catalog.PhyAddrColumnName {
   108  			continue
   109  		}
   110  		def := schema.ColDefs[schema.GetColIdx(attr)]
   111  		destVec := n.storage.mnode.data.Vecs[def.Idx]
   112  		// logutil.Infof("destVec: %s, %d, %d", destVec.String(), cnt, data.Length())
   113  		destVec.ExtendWithOffset(data.Vecs[def.Idx], int(offset), int(an))
   114  	}
   115  	n.storage.mnode.rows = uint32(n.storage.mnode.data.Length())
   116  	err = n.storage.mnode.FillPhyAddrColumn(from, an)
   117  	return
   118  }
   119  
   120  func (n *anode) FillBlockView(view *model.BlockView, buffers []*bytes.Buffer, colIdxes []int) (err error) {
   121  	for i, colIdx := range colIdxes {
   122  		orig := n.storage.mnode.data.Vecs[colIdx]
   123  		if buffers[i] != nil {
   124  			buffers[i].Reset()
   125  			view.SetData(colIdx, containers.CloneWithBuffer(orig, buffers[i]))
   126  		} else {
   127  			view.SetData(colIdx, orig.CloneWindow(0, orig.Length()))
   128  		}
   129  
   130  	}
   131  	view.DeleteMask = n.storage.mnode.data.Deletes
   132  	return
   133  }
   134  func (n *anode) FillColumnView(view *model.ColumnView, buffer *bytes.Buffer) (err error) {
   135  	orig := n.storage.mnode.data.Vecs[view.ColIdx]
   136  	if buffer != nil {
   137  		buffer.Reset()
   138  		view.SetData(containers.CloneWithBuffer(orig, buffer))
   139  	} else {
   140  		view.SetData(orig.CloneWindow(0, orig.Length()))
   141  	}
   142  	view.DeleteMask = n.storage.mnode.data.Deletes
   143  	return
   144  }
   145  
   146  func (n *anode) GetSpace() uint32 {
   147  	return txnbase.MaxNodeRows - n.storage.mnode.rows
   148  }
   149  
   150  func (n *anode) RowsWithoutDeletes() uint32 {
   151  	deletes := uint32(0)
   152  	if n.storage.mnode.data != nil && n.storage.mnode.data.Deletes != nil {
   153  		deletes = uint32(n.storage.mnode.data.DeleteCnt())
   154  	}
   155  	return n.storage.mnode.rows - deletes
   156  }
   157  
   158  func (n *anode) LengthWithDeletes(appended, toAppend uint32) uint32 {
   159  	if !n.storage.mnode.data.HasDelete() {
   160  		return toAppend
   161  	}
   162  	appendedOffset := n.OffsetWithDeletes(appended)
   163  	toAppendOffset := n.OffsetWithDeletes(toAppend + appended)
   164  	// logutil.Infof("appened:%d, toAppend:%d, off1=%d, off2=%d", appended, toAppend, appendedOffset, toAppendOffset)
   165  	return toAppendOffset - appendedOffset
   166  }
   167  
   168  func (n *anode) OffsetWithDeletes(count uint32) uint32 {
   169  	if !n.storage.mnode.data.HasDelete() {
   170  		return count
   171  	}
   172  	offset := count
   173  	for offset < n.storage.mnode.rows {
   174  		deletes := n.storage.mnode.data.Deletes.Rank(offset)
   175  		if offset == count+uint32(deletes) {
   176  			break
   177  		}
   178  		offset = count + uint32(deletes)
   179  	}
   180  	return offset
   181  }
   182  
   183  func (n *anode) GetValue(col int, row uint32) (any, error) {
   184  	if !n.IsPersisted() {
   185  		return n.storage.mnode.data.Vecs[col].Get(int(row)), nil
   186  	}
   187  	//TODO:: get value from S3/FS
   188  	panic("not implemented yet :GetValue from FS/S3 ")
   189  }
   190  
   191  func (n *anode) RangeDelete(start, end uint32) error {
   192  	n.storage.mnode.data.RangeDelete(int(start), int(end+1))
   193  	return nil
   194  }
   195  
   196  func (n *anode) IsRowDeleted(row uint32) bool {
   197  	return n.storage.mnode.data.IsDeleted(int(row))
   198  }
   199  
   200  func (n *anode) PrintDeletes() string {
   201  	if !n.storage.mnode.data.HasDelete() {
   202  		return "NoDeletes"
   203  	}
   204  	return n.storage.mnode.data.Deletes.String()
   205  }
   206  
   207  func (n *anode) Window(start, end uint32) (bat *containers.Batch, err error) {
   208  	bat = n.storage.mnode.data.CloneWindow(int(start), int(end-start))
   209  	bat.Compact()
   210  	return
   211  }
   212  
   213  func (n *anode) GetColumnDataByIds(
   214  	colIdxes []int,
   215  	buffers []*bytes.Buffer,
   216  ) (view *model.BlockView, err error) {
   217  	if !n.IsPersisted() {
   218  		view = model.NewBlockView(n.table.store.txn.GetStartTS())
   219  		err = n.FillBlockView(view, buffers, colIdxes)
   220  		return
   221  	}
   222  	panic("Not Implemented yet : GetColumnDataByIds from S3/FS ")
   223  }
   224  
   225  func (n *anode) GetColumnDataById(colIdx int, buffer *bytes.Buffer) (view *model.ColumnView, err error) {
   226  	if !n.IsPersisted() {
   227  		view = model.NewColumnView(n.table.store.txn.GetStartTS(), colIdx)
   228  		err = n.FillColumnView(view, buffer)
   229  		return
   230  	}
   231  	panic("Not Implemented yet : GetColumnDataByIds from S3/FS ")
   232  }