github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/localseg.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 "bytes" 19 "fmt" 20 "github.com/matrixorigin/matrixone/pkg/common/moerr" 21 "github.com/matrixorigin/matrixone/pkg/logutil" 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 28 ) 29 30 const ( 31 // Note: Do not edit this id!!! 32 LocalSegmentStartID uint64 = 1 << 47 33 ) 34 35 var localSegmentIdAlloc *common.IdAlloctor 36 37 func init() { 38 localSegmentIdAlloc = common.NewIdAlloctor(LocalSegmentStartID) 39 } 40 41 func isLocalSegment(id *common.ID) bool { 42 return id.SegmentID >= LocalSegmentStartID 43 } 44 45 func isLocalSegmentByID(id uint64) bool { 46 return id >= LocalSegmentStartID 47 } 48 49 type localSegment struct { 50 entry *catalog.SegmentEntry 51 appendable InsertNode 52 //index for primary key 53 index TableIndex 54 //nodes contains anode and node. 55 nodes []InsertNode 56 table *txnTable 57 rows uint32 58 appends []*appendCtx 59 tableHandle data.TableHandle 60 nseg handle.Segment 61 //sched tasks.TaskScheduler 62 } 63 64 func newLocalSegment(table *txnTable) *localSegment { 65 entry := catalog.NewStandaloneSegment( 66 table.entry, 67 localSegmentIdAlloc.Alloc(), 68 table.store.txn.GetStartTS()) 69 return &localSegment{ 70 entry: entry, 71 nodes: make([]InsertNode, 0), 72 index: NewSimpleTableIndex(), 73 appends: make([]*appendCtx, 0), 74 table: table, 75 } 76 } 77 78 func (seg *localSegment) GetLocalPhysicalAxis(row uint32) (int, uint32) { 79 var sum uint32 80 for i, node := range seg.nodes { 81 sum += node.Rows() 82 if row <= sum-1 { 83 return i, node.Rows() - (sum - (row + 1)) - 1 84 } 85 } 86 panic("Invalid row ") 87 } 88 89 // register a non-appendable insertNode. 90 func (seg *localSegment) registerNode(metaLoc string, deltaLoc string) { 91 meta := catalog.NewStandaloneBlockWithLoc( 92 seg.entry, 93 uint64(len(seg.nodes)), 94 seg.table.store.txn.GetStartTS(), 95 metaLoc, 96 deltaLoc) 97 seg.entry.AddEntryLocked(meta) 98 n := NewNode( 99 seg.table, 100 seg.table.store.dataFactory.Fs, 101 seg.table.store.nodesMgr, 102 seg.table.store.dataFactory.Scheduler, 103 meta, 104 ) 105 seg.nodes = append(seg.nodes, n) 106 107 } 108 109 // register an appendable insertNode. 110 func (seg *localSegment) registerANode() { 111 meta := catalog.NewStandaloneBlock( 112 seg.entry, 113 uint64(len(seg.nodes)), 114 seg.table.store.txn.GetStartTS()) 115 seg.entry.AddEntryLocked(meta) 116 n := NewANode( 117 seg.table, 118 seg.table.store.dataFactory.Fs, 119 seg.table.store.nodesMgr, 120 seg.table.store.dataFactory.Scheduler, 121 meta, 122 ) 123 seg.appendable = n 124 seg.nodes = append(seg.nodes, n) 125 //TODO::if appendable insertNode >= 2, start to flush it into S3/FS. 126 //seg.sched.Scheduler() 127 } 128 129 // ApplyAppend applies all the anodes into appendable blocks 130 // and un-reference the appendable blocks which had been referenced when PrepareApply. 131 func (seg *localSegment) ApplyAppend() (err error) { 132 var destOff int 133 defer func() { 134 // Close All unclosed Appends:un-reference the appendable block. 135 seg.CloseAppends() 136 }() 137 for _, ctx := range seg.appends { 138 bat, _ := ctx.node.Window(ctx.start, ctx.start+ctx.count) 139 defer bat.Close() 140 if destOff, err = ctx.driver.ApplyAppend( 141 bat, 142 seg.table.store.txn); err != nil { 143 return 144 } 145 id := ctx.driver.GetID() 146 ctx.node.AddApplyInfo( 147 ctx.start, 148 ctx.count, 149 uint32(destOff), 150 ctx.count, 151 seg.table.entry.GetDB().ID, id) 152 } 153 if seg.tableHandle != nil { 154 seg.table.entry.GetTableData().ApplyHandle(seg.tableHandle) 155 } 156 return 157 } 158 159 func (seg *localSegment) PrepareApply() (err error) { 160 defer func() { 161 if err != nil { 162 // Close All unclosed Appends: un-reference all the appendable blocks. 163 seg.CloseAppends() 164 } 165 }() 166 for _, node := range seg.nodes { 167 if err = seg.prepareApplyNode(node); err != nil { 168 return 169 } 170 } 171 return 172 } 173 174 func (seg *localSegment) prepareApplyNode(node InsertNode) (err error) { 175 if !node.IsPersisted() { 176 tableData := seg.table.entry.GetTableData() 177 if seg.tableHandle == nil { 178 seg.tableHandle = tableData.GetHandle() 179 } 180 appended := uint32(0) 181 for appended < node.RowsWithoutDeletes() { 182 appender, err := seg.tableHandle.GetAppender() 183 if moerr.IsMoErrCode(err, moerr.ErrAppendableSegmentNotFound) { 184 segH, err := seg.table.CreateSegment(true) 185 if err != nil { 186 return err 187 } 188 blk, err := segH.CreateBlock(true) 189 if err != nil { 190 return err 191 } 192 appender = seg.tableHandle.SetAppender(blk.Fingerprint()) 193 } else if moerr.IsMoErrCode(err, moerr.ErrAppendableBlockNotFound) { 194 id := appender.GetID() 195 blk, err := seg.table.CreateBlock(id.SegmentID, true) 196 if err != nil { 197 return err 198 } 199 appender = seg.tableHandle.SetAppender(blk.Fingerprint()) 200 } 201 //PrepareAppend: It is very important that appending a AppendNode into 202 // block's MVCCHandle before applying data into block. 203 anode, created, toAppend, err := appender.PrepareAppend( 204 node.RowsWithoutDeletes()-appended, 205 seg.table.store.txn) 206 if err != nil { 207 return err 208 } 209 toAppendWithDeletes := node.LengthWithDeletes(appended, toAppend) 210 ctx := &appendCtx{ 211 driver: appender, 212 node: node, 213 anode: anode, 214 start: node.OffsetWithDeletes(appended), 215 count: toAppendWithDeletes, 216 } 217 if created { 218 seg.table.store.IncreateWriteCnt() 219 seg.table.txnEntries.Append(anode) 220 } 221 id := appender.GetID() 222 seg.table.store.warChecker.Insert(appender.GetMeta().(*catalog.BlockEntry)) 223 seg.table.store.txn.GetMemo().AddBlock(seg.table.entry.GetDB().ID, 224 id.TableID, id.SegmentID, id.BlockID) 225 seg.appends = append(seg.appends, ctx) 226 logutil.Debugf("%s: toAppend %d, appended %d, blks=%d", 227 id.String(), toAppend, appended, len(seg.appends)) 228 appended += toAppend 229 if appended == node.Rows() { 230 break 231 } 232 } 233 return 234 } 235 //handle persisted insertNode. 236 if seg.nseg == nil || 237 seg.nseg.GetMeta().(*catalog.SegmentEntry).BlockCnt() == 238 int(seg.nseg.GetMeta().(*catalog.SegmentEntry).GetTable(). 239 GetSchema().SegmentMaxBlocks) { 240 seg.nseg, err = seg.table.CreateNonAppendableSegment(true) 241 if err != nil { 242 return 243 } 244 } 245 _, err = seg.nseg.CreateNonAppendableBlockWithMeta(node.GetPersistedLoc()) 246 if err != nil { 247 return 248 } 249 return 250 } 251 252 // CloseAppends un-reference the appendable blocks 253 func (seg *localSegment) CloseAppends() { 254 for _, ctx := range seg.appends { 255 ctx.driver.Close() 256 } 257 } 258 259 // Append appends batch of data into anode. 260 func (seg *localSegment) Append(data *containers.Batch) (err error) { 261 if seg.appendable == nil { 262 seg.registerANode() 263 } 264 appended := uint32(0) 265 offset := uint32(0) 266 length := uint32(data.Length()) 267 for { 268 h := seg.appendable 269 space := h.GetSpace() 270 if space == 0 { 271 seg.registerANode() 272 h = seg.appendable 273 } 274 appended, err = h.Append(data, offset) 275 if err != nil { 276 return 277 } 278 if seg.table.schema.HasPK() { 279 if err = seg.index.BatchInsert( 280 data.Attrs[seg.table.schema.GetSingleSortKeyIdx()], 281 data.Vecs[seg.table.schema.GetSingleSortKeyIdx()], 282 int(offset), 283 int(appended), 284 seg.rows, 285 false); err != nil { 286 break 287 } 288 } 289 offset += appended 290 seg.rows += appended 291 if offset >= length { 292 break 293 } 294 } 295 return 296 } 297 298 // AddBlksWithMetaLoc transfers blocks with meta location into non-appendable nodes 299 func (seg *localSegment) AddBlksWithMetaLoc( 300 pkVecs []containers.Vector, 301 file string, 302 metaLocs []string, 303 ) (err error) { 304 for i, metaLoc := range metaLocs { 305 seg.registerNode(metaLoc, "") 306 //insert primary keys into seg.index 307 if pkVecs != nil { 308 if err = seg.index.BatchInsert( 309 seg.table.schema.GetSingleSortKey().Name, 310 pkVecs[i], 311 0, 312 pkVecs[i].Length(), 313 seg.rows, 314 false, 315 ); err != nil { 316 return 317 } 318 seg.rows += uint32(pkVecs[i].Length()) 319 } 320 } 321 return nil 322 } 323 324 func (seg *localSegment) DeleteFromIndex(from, to uint32, node InsertNode) (err error) { 325 for i := from; i <= to; i++ { 326 v, err := node.GetValue(seg.table.schema.GetSingleSortKeyIdx(), i) 327 if err != nil { 328 return err 329 } 330 if err = seg.index.Delete(v); err != nil { 331 return err 332 } 333 } 334 return 335 } 336 337 // RangeDelete delete rows : [start, end] 338 func (seg *localSegment) RangeDelete(start, end uint32) error { 339 first, firstOffset := seg.GetLocalPhysicalAxis(start) 340 last, lastOffset := seg.GetLocalPhysicalAxis(end) 341 var err error 342 if last == first { 343 node := seg.nodes[first] 344 err = node.RangeDelete(firstOffset, lastOffset) 345 if err != nil { 346 return err 347 } 348 if !seg.table.schema.HasPK() { 349 // If no pk defined 350 return err 351 } 352 err = seg.DeleteFromIndex(firstOffset, lastOffset, node) 353 return err 354 } 355 356 node := seg.nodes[first] 357 if err = node.RangeDelete(firstOffset, node.Rows()-1); err != nil { 358 359 return err 360 } 361 if err = seg.DeleteFromIndex(firstOffset, node.Rows()-1, node); err != nil { 362 return err 363 } 364 node = seg.nodes[last] 365 if err = node.RangeDelete(0, lastOffset); err != nil { 366 return err 367 } 368 if err = seg.DeleteFromIndex(0, lastOffset, node); err != nil { 369 return err 370 } 371 if last > first+1 { 372 for i := first + 1; i < last; i++ { 373 node = seg.nodes[i] 374 if err = node.RangeDelete(0, node.Rows()-1); err != nil { 375 break 376 } 377 if err = seg.DeleteFromIndex(0, node.Rows()-1, node); err != nil { 378 break 379 } 380 } 381 } 382 return err 383 } 384 385 // CollectCmd collect txnCmd for anode whose data resides in memory. 386 func (seg *localSegment) CollectCmd(cmdMgr *commandManager) (err error) { 387 for _, node := range seg.nodes { 388 csn := uint32(0xffff) // Special cmd 389 cmd, err := node.MakeCommand(csn) 390 if err != nil { 391 panic(err) 392 } 393 if cmd != nil { 394 cmdMgr.AddInternalCmd(cmd) 395 } 396 } 397 return 398 } 399 400 func (seg *localSegment) DeletesToString() string { 401 var s string 402 for i, n := range seg.nodes { 403 s = fmt.Sprintf("%s\t<INode-%d>: %s\n", s, i, n.PrintDeletes()) 404 } 405 return s 406 } 407 408 func (seg *localSegment) IsDeleted(row uint32) bool { 409 npos, noffset := seg.GetLocalPhysicalAxis(row) 410 n := seg.nodes[npos] 411 return n.IsRowDeleted(noffset) 412 } 413 414 func (seg *localSegment) Rows() (n uint32) { 415 for _, node := range seg.nodes { 416 n += node.Rows() 417 } 418 return 419 } 420 421 func (seg *localSegment) GetByFilter(filter *handle.Filter) (id *common.ID, offset uint32, err error) { 422 id = seg.entry.AsCommonID() 423 if !seg.table.schema.HasPK() { 424 _, _, offset = model.DecodePhyAddrKeyFromValue(filter.Val) 425 return 426 } 427 if v, ok := filter.Val.([]byte); ok { 428 offset, err = seg.index.Search(string(v)) 429 } else { 430 offset, err = seg.index.Search(filter.Val) 431 } 432 return 433 } 434 435 func (seg *localSegment) GetPKColumn() containers.Vector { 436 schema := seg.table.entry.GetSchema() 437 return seg.index.KeyToVector(schema.GetSingleSortKeyType()) 438 } 439 440 func (seg *localSegment) GetPKVecs() []containers.Vector { 441 schema := seg.table.entry.GetSchema() 442 return seg.index.KeyToVectors(schema.GetSingleSortKeyType()) 443 } 444 445 func (seg *localSegment) BatchDedup(key containers.Vector) error { 446 return seg.index.BatchDedup(seg.table.GetSchema().GetSingleSortKey().Name, key) 447 } 448 449 func (seg *localSegment) GetColumnDataByIds( 450 blk *catalog.BlockEntry, 451 colIdxes []int, 452 buffers []*bytes.Buffer) (view *model.BlockView, err error) { 453 npos := int(blk.ID) 454 n := seg.nodes[npos] 455 return n.GetColumnDataByIds(colIdxes, buffers) 456 } 457 458 func (seg *localSegment) GetColumnDataById( 459 blk *catalog.BlockEntry, 460 colIdx int, 461 buffer *bytes.Buffer) (view *model.ColumnView, err error) { 462 npos := int(blk.ID) 463 n := seg.nodes[npos] 464 return n.GetColumnDataById(colIdx, buffer) 465 } 466 467 func (seg *localSegment) GetBlockRows(blk *catalog.BlockEntry) int { 468 npos := int(blk.ID) 469 n := seg.nodes[npos] 470 return int(n.Rows()) 471 } 472 473 func (seg *localSegment) GetValue(row uint32, col uint16) (any, error) { 474 npos, noffset := seg.GetLocalPhysicalAxis(row) 475 n := seg.nodes[npos] 476 return n.GetValue(int(col), noffset) 477 } 478 479 // Close free the resource when transaction commits. 480 func (seg *localSegment) Close() (err error) { 481 for _, node := range seg.nodes { 482 if err = node.Close(); err != nil { 483 return 484 } 485 } 486 seg.index.Close() 487 seg.index = nil 488 seg.nodes = nil 489 seg.appendable = nil 490 return 491 }