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 }