github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logtail/reader.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 logtail 16 17 import ( 18 "github.com/matrixorigin/matrixone/pkg/container/types" 19 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif" 20 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 21 ) 22 23 // Reader is a snapshot of all txn prepared between from and to. 24 // Dirty tables/objects/blocks can be queried based on those txn 25 type Reader struct { 26 from, to types.TS 27 table *TxnTable 28 } 29 30 // Merge all dirty table/object/block into one dirty tree 31 func (r *Reader) GetDirty() (tree *model.Tree, count int) { 32 tree = model.NewTree() 33 op := func(row RowT) (moveOn bool) { 34 if memo := row.GetMemo(); memo.HasAnyTableDataChanges() { 35 tree.Merge(memo.GetDirty()) 36 } 37 count++ 38 return true 39 } 40 r.table.ForeachRowInBetween(r.from, r.to, nil, op) 41 return 42 } 43 44 // HasCatalogChanges returns true if any txn in the reader modified the Catalog 45 func (r *Reader) HasCatalogChanges() bool { 46 changed := false 47 op := func(row RowT) (moveOn bool) { 48 if row.GetMemo().HasCatalogChanges() { 49 changed = true 50 return false 51 } 52 return true 53 } 54 skipFn := func(blk BlockT) bool { 55 summary := blk.summary.Load() 56 return summary != nil && !summary.hasCatalogChanges 57 } 58 r.table.ForeachRowInBetween(r.from, r.to, skipFn, op) 59 return changed 60 } 61 62 func (r *Reader) IsCommitted() bool { 63 committed := true 64 r.table.ForeachRowInBetween(r.from, r.to, nil, func(row RowT) (goNext bool) { 65 state := row.GetTxnState(false) 66 if state != txnif.TxnStateCommitted && state != txnif.TxnStateRollbacked { 67 committed = false 68 return false 69 } 70 return true 71 }) 72 return committed 73 } 74 75 // Merge all dirty table/object/block of **a table** into one tree 76 func (r *Reader) GetDirtyByTable( 77 dbID, id uint64, 78 ) (tree *model.TableTree) { 79 tree = model.NewTableTree(dbID, id) 80 op := func(row RowT) (moveOn bool) { 81 if memo := row.GetMemo(); memo.HasTableDataChanges(id) { 82 tree.Merge(memo.GetDirtyTableByID(id)) 83 } 84 return true 85 } 86 r.table.ForeachRowInBetween(r.from, r.to, nil, op) 87 return 88 } 89 90 // TODO: optimize 91 func (r *Reader) GetMaxLSN() (maxLsn uint64) { 92 r.table.ForeachRowInBetween( 93 r.from, 94 r.to, 95 nil, 96 func(row RowT) (moveOn bool) { 97 lsn := row.GetLSN() 98 if lsn > maxLsn { 99 maxLsn = lsn 100 } 101 return true 102 }) 103 return 104 }