github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/tables/evictable/coldata.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 evictable
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/objectio"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer/base"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/dataio/blockio"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
    32  )
    33  
    34  type ColDataNode struct {
    35  	*buffer.Node
    36  
    37  	Data containers.Vector
    38  
    39  	colDataKey string
    40  	def        *catalog.ColDef
    41  
    42  	// used for rowid
    43  	rows     uint32
    44  	sid, bid uint64
    45  
    46  	// used for other columns
    47  	metaKey        string
    48  	mgr            base.INodeManager
    49  	colMetaFactory EvictableNodeFactory
    50  }
    51  
    52  type BackendKind = uint8
    53  
    54  const (
    55  	Disk = iota
    56  	S3
    57  )
    58  
    59  var StorageBackend BackendKind = Disk
    60  
    61  func NewColDataNode(
    62  	id *common.ID,
    63  	def *catalog.ColDef,
    64  	colDataKey string,
    65  	metaKey string,
    66  	metaloc string,
    67  	mgr base.INodeManager,
    68  	fs *objectio.ObjectFS) (node *ColDataNode, err error) {
    69  	node = &ColDataNode{
    70  		colDataKey: colDataKey,
    71  		metaKey:    metaKey,
    72  		sid:        id.SegmentID,
    73  		bid:        id.BlockID,
    74  		mgr:        mgr,
    75  		def:        def,
    76  		colMetaFactory: func() (base.INode, error) {
    77  			return NewColumnMetaNode(
    78  				id.Idx,
    79  				def.Type,
    80  				metaloc,
    81  				metaKey,
    82  				mgr,
    83  				fs), nil
    84  		},
    85  	}
    86  	// For disk, size is zero, do not cache, read directly when GetData
    87  	var size uint32 = 0
    88  	if node.def.IsPhyAddr() {
    89  		_, _, node.rows = blockio.DecodeMetaLoc(metaloc)
    90  		size = types.RowidSize * node.rows
    91  	} else if StorageBackend == S3 {
    92  		// on s3, fetch coldata to get data size
    93  		h, pinerr := PinEvictableNode(mgr, metaKey, node.colMetaFactory)
    94  		if pinerr != nil {
    95  			return nil, pinerr
    96  		}
    97  		defer h.Close()
    98  		meta := h.GetNode().(*ColumnMetaNode)
    99  		size = meta.GetMeta().GetLocation().OriginSize()
   100  	}
   101  
   102  	node.Node = buffer.NewNode(node, mgr, colDataKey, uint64(size))
   103  	node.LoadFunc = node.onLoad
   104  	node.UnloadFunc = node.onUnload
   105  	node.HardEvictableFunc = func() bool { return true }
   106  	return
   107  }
   108  
   109  func (n *ColDataNode) onLoad() {
   110  	if n.def.IsPhyAddr() {
   111  		n.constructRowId()
   112  		return
   113  	}
   114  	switch StorageBackend {
   115  	case S3:
   116  		// fetch data via s3 and cache it
   117  		// TODOa: error handling
   118  		data, _ := n.fetchData()
   119  		n.Data = data
   120  	case Disk:
   121  		// for disk, do nothing when load
   122  	}
   123  }
   124  
   125  func (n *ColDataNode) constructRowId() {
   126  	prefix := model.EncodeBlockKeyPrefix(n.sid, n.bid)
   127  	n.Data, _ = model.PreparePhyAddrData(
   128  		types.T_Rowid.ToType(),
   129  		prefix,
   130  		0,
   131  		n.rows,
   132  	)
   133  }
   134  
   135  func (n *ColDataNode) fetchData() (containers.Vector, error) {
   136  	var h base.INodeHandle
   137  	var err error
   138  	h, err = PinEvictableNode(n.mgr, n.metaKey, n.colMetaFactory)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  	metaNode := h.GetNode().(*ColumnMetaNode)
   143  	defer h.Close()
   144  
   145  	// Do IO, fetch data buf
   146  	fsVector, err := metaNode.GetData(context.Background(), nil)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	//srcBuf := fsVector.Entries[0].Object.([]byte)
   152  	srcBuf := make([]byte, len(fsVector.Entries[0].Object.([]byte)))
   153  	copy(srcBuf, fsVector.Entries[0].Object.([]byte))
   154  	v := vector.New(n.def.Type)
   155  	v.Read(srcBuf)
   156  	return containers.NewVectorWithSharedMemory(v, n.def.NullAbility), nil
   157  }
   158  
   159  func (n *ColDataNode) GetData(buf *bytes.Buffer) (containers.Vector, error) {
   160  	// after load, for s3 and phy addr, its data is n.Data
   161  	if n.def.IsPhyAddr() {
   162  		return copyVector(n.Data, buf), nil
   163  	}
   164  	switch StorageBackend {
   165  	case Disk:
   166  		// for disk, read directly
   167  		return n.fetchData()
   168  	case S3:
   169  		return copyVector(n.Data, buf), nil
   170  	}
   171  	return nil, nil
   172  }
   173  
   174  func (n *ColDataNode) onUnload() {
   175  	if n.Data != nil {
   176  		n.Data.Close()
   177  		n.Data = nil
   178  	}
   179  }
   180  
   181  func FetchColumnData(
   182  	id *common.ID,
   183  	def *catalog.ColDef,
   184  	metaloc string,
   185  	buf *bytes.Buffer,
   186  	mgr base.INodeManager,
   187  	fs *objectio.ObjectFS) (res containers.Vector, err error) {
   188  	id.Idx = uint16(def.Idx)
   189  	colDataKey := EncodeColDataKey(id.Idx, metaloc)
   190  	factory := func() (base.INode, error) {
   191  		return NewColDataNode(
   192  			id,
   193  			def,
   194  			colDataKey,
   195  			EncodeColMetaKey(id.Idx, metaloc),
   196  			metaloc,
   197  			mgr,
   198  			fs)
   199  	}
   200  	h, err := PinEvictableNode(mgr, colDataKey, factory)
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  	defer h.Close()
   205  	node := h.GetNode().(*ColDataNode)
   206  	return node.GetData(buf)
   207  }