github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/txn/txnimpl/segment.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 "sync" 19 20 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog" 21 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/containers" 23 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/handle" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase" 25 ) 26 27 type txnSegment struct { 28 *txnbase.TxnSegment 29 entry *catalog.SegmentEntry 30 table *txnTable 31 } 32 33 type segmentIt struct { 34 sync.RWMutex 35 linkIt *common.GenericSortedDListIt[*catalog.SegmentEntry] 36 curr *catalog.SegmentEntry 37 table *txnTable 38 err error 39 } 40 41 type composedSegmentIt struct { 42 *segmentIt 43 uncommitted *catalog.SegmentEntry 44 } 45 46 func newSegmentIt(table *txnTable) handle.SegmentIt { 47 it := &segmentIt{ 48 linkIt: table.entry.MakeSegmentIt(true), 49 table: table, 50 } 51 var err error 52 var ok bool 53 for it.linkIt.Valid() { 54 curr := it.linkIt.Get().GetPayload() 55 curr.RLock() 56 ok, err = curr.IsVisible(it.table.store.txn.GetStartTS(), curr.RWMutex) 57 if err != nil { 58 curr.RUnlock() 59 it.err = err 60 return it 61 } 62 if ok { 63 curr.RUnlock() 64 it.curr = curr 65 break 66 } 67 curr.RUnlock() 68 it.linkIt.Next() 69 } 70 if table.localSegment != nil { 71 cit := &composedSegmentIt{ 72 segmentIt: it, 73 uncommitted: table.localSegment.entry, 74 } 75 return cit 76 } 77 return it 78 } 79 80 func (it *segmentIt) Close() error { return nil } 81 82 func (it *segmentIt) GetError() error { return it.err } 83 func (it *segmentIt) Valid() bool { 84 if it.err != nil { 85 return false 86 } 87 return it.linkIt.Valid() 88 } 89 90 func (it *segmentIt) Next() { 91 var err error 92 var valid bool 93 for { 94 it.linkIt.Next() 95 node := it.linkIt.Get() 96 if node == nil { 97 it.curr = nil 98 break 99 } 100 entry := node.GetPayload() 101 entry.RLock() 102 valid, err = entry.IsVisible(it.table.store.txn.GetStartTS(), entry.RWMutex) 103 entry.RUnlock() 104 if err != nil { 105 it.err = err 106 break 107 } 108 if valid { 109 it.curr = entry 110 break 111 } 112 } 113 } 114 115 func (it *segmentIt) GetSegment() handle.Segment { 116 return newSegment(it.table, it.curr) 117 } 118 119 func (cit *composedSegmentIt) GetSegment() handle.Segment { 120 if cit.uncommitted != nil { 121 return newSegment(cit.table, cit.uncommitted) 122 } 123 return cit.segmentIt.GetSegment() 124 } 125 126 func (cit *composedSegmentIt) Valid() bool { 127 if cit.err != nil { 128 return false 129 } 130 if cit.uncommitted != nil { 131 return true 132 } 133 return cit.segmentIt.Valid() 134 } 135 136 func (cit *composedSegmentIt) Next() { 137 if cit.uncommitted != nil { 138 cit.uncommitted = nil 139 return 140 } 141 cit.segmentIt.Next() 142 } 143 144 func newSegment(table *txnTable, meta *catalog.SegmentEntry) *txnSegment { 145 seg := &txnSegment{ 146 TxnSegment: &txnbase.TxnSegment{ 147 Txn: table.store.txn, 148 }, 149 table: table, 150 entry: meta, 151 } 152 return seg 153 } 154 155 func (seg *txnSegment) GetMeta() any { return seg.entry } 156 func (seg *txnSegment) String() string { return seg.entry.String() } 157 func (seg *txnSegment) GetID() uint64 { return seg.entry.GetID() } 158 func (seg *txnSegment) getDBID() uint64 { return seg.entry.GetTable().GetDB().ID } 159 func (seg *txnSegment) MakeBlockIt() (it handle.BlockIt) { 160 return newBlockIt(seg.table, seg.entry) 161 } 162 163 func (seg *txnSegment) CreateNonAppendableBlock() (blk handle.Block, err error) { 164 return seg.Txn.GetStore().CreateNonAppendableBlock(seg.getDBID(), seg.entry.AsCommonID()) 165 } 166 167 func (seg *txnSegment) CreateNonAppendableBlockWithMeta( 168 metaLoc string, 169 deltaLoc string) (blk handle.Block, err error) { 170 return seg.Txn.GetStore().CreateNonAppendableBlockWithMeta( 171 seg.getDBID(), 172 seg.entry.AsCommonID(), 173 metaLoc, 174 deltaLoc) 175 } 176 177 func (seg *txnSegment) IsUncommitted() bool { 178 return isLocalSegmentByID(seg.entry.GetID()) 179 } 180 181 func (seg *txnSegment) IsAppendable() bool { return seg.entry.IsAppendable() } 182 183 func (seg *txnSegment) SoftDeleteBlock(id uint64) (err error) { 184 fp := seg.entry.AsCommonID() 185 fp.BlockID = id 186 return seg.Txn.GetStore().SoftDeleteBlock(seg.getDBID(), fp) 187 } 188 189 func (seg *txnSegment) GetRelation() (rel handle.Relation) { 190 return newRelation(seg.table) 191 } 192 193 func (seg *txnSegment) GetBlock(id uint64) (blk handle.Block, err error) { 194 fp := seg.entry.AsCommonID() 195 fp.BlockID = id 196 return seg.Txn.GetStore().GetBlock(seg.getDBID(), fp) 197 } 198 199 func (seg *txnSegment) CreateBlock(is1PC bool) (blk handle.Block, err error) { 200 return seg.Txn.GetStore().CreateBlock(seg.getDBID(), seg.entry.GetTable().GetID(), seg.entry.GetID(), is1PC) 201 } 202 203 func (seg *txnSegment) BatchDedup(pks containers.Vector) (err error) { 204 if isLocalSegment(seg.entry.AsCommonID()) { 205 return seg.table.localSegment.BatchDedup(pks) 206 } 207 segData := seg.entry.GetSegmentData() 208 seg.Txn.GetStore().LogSegmentID(seg.getDBID(), seg.entry.GetTable().GetID(), seg.entry.GetID()) 209 return segData.BatchDedup(seg.Txn, pks) 210 }