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  }