github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/catalog/base.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 catalog
    16  
    17  import (
    18  	"fmt"
    19  	// "io"
    20  	"sync"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/logutil"
    25  	"github.com/matrixorigin/matrixone/pkg/util/stack"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/txn/txnbase"
    29  )
    30  
    31  type BaseEntry interface {
    32  	//for global checkpoint
    33  	RLock()
    34  	RUnlock()
    35  	DeleteBeforeLocked(ts types.TS) bool
    36  	DeleteBefore(ts types.TS) bool
    37  }
    38  
    39  func CompareUint64(left, right uint64) int {
    40  	if left > right {
    41  		return 1
    42  	} else if left < right {
    43  		return -1
    44  	}
    45  	return 0
    46  }
    47  
    48  type BaseEntryImpl[T BaseNode[T]] struct {
    49  	//chain of MetadataMVCCNode
    50  	*txnbase.MVCCChain[*MVCCNode[T]]
    51  }
    52  
    53  func NewReplayBaseEntry[T BaseNode[T]](factory func() T) *BaseEntryImpl[T] {
    54  	be := &BaseEntryImpl[T]{
    55  		MVCCChain: txnbase.NewMVCCChain(CompareBaseNode[T], NewEmptyMVCCNodeFactory(factory), nil),
    56  	}
    57  	return be
    58  }
    59  
    60  func NewBaseEntry[T BaseNode[T]](factory func() T) *BaseEntryImpl[T] {
    61  	return &BaseEntryImpl[T]{
    62  		MVCCChain: txnbase.NewMVCCChain(CompareBaseNode[T], NewEmptyMVCCNodeFactory(factory), nil),
    63  	}
    64  }
    65  
    66  func (be *BaseEntryImpl[T]) StringLocked() string {
    67  	return be.MVCCChain.StringLocked()
    68  }
    69  
    70  func (be *BaseEntryImpl[T]) String() string {
    71  	be.RLock()
    72  	defer be.RUnlock()
    73  	return be.StringLocked()
    74  }
    75  
    76  func (be *BaseEntryImpl[T]) PPString(level common.PPLevel, depth int, prefix string) string {
    77  	s := fmt.Sprintf("%s%s%s", common.RepeatStr("\t", depth), prefix, be.StringLocked())
    78  	return s
    79  }
    80  
    81  func (be *BaseEntryImpl[T]) CreateWithTS(ts types.TS, baseNode T) {
    82  	node := &MVCCNode[T]{
    83  		EntryMVCCNode: &EntryMVCCNode{
    84  			CreatedAt: ts,
    85  		},
    86  		TxnMVCCNode: txnbase.NewTxnMVCCNodeWithTS(ts),
    87  		BaseNode:    baseNode,
    88  	}
    89  	be.Insert(node)
    90  }
    91  
    92  func (be *BaseEntryImpl[T]) CreateWithTxn(txn txnif.AsyncTxn, baseNode T) {
    93  	if txn == nil {
    94  		logutil.Warnf("unexpected txn is nil: %+v", stack.Callers(0))
    95  	}
    96  	node := &MVCCNode[T]{
    97  		EntryMVCCNode: &EntryMVCCNode{
    98  			CreatedAt: txnif.UncommitTS,
    99  		},
   100  		TxnMVCCNode: txnbase.NewTxnMVCCNodeWithTxn(txn),
   101  		BaseNode:    baseNode,
   102  	}
   103  	be.Insert(node)
   104  }
   105  
   106  // used when replay
   107  func (be *BaseEntryImpl[T]) CreateWithStartAndEnd(start, end types.TS, baseNode T) {
   108  	node := &MVCCNode[T]{
   109  		EntryMVCCNode: &EntryMVCCNode{
   110  			CreatedAt: end,
   111  		},
   112  		TxnMVCCNode: txnbase.NewTxnMVCCNodeWithStartEnd(start, end),
   113  		BaseNode:    baseNode,
   114  	}
   115  	be.Insert(node)
   116  }
   117  
   118  func (be *BaseEntryImpl[T]) TryGetTerminatedTS(waitIfcommitting bool) (terminated bool, TS types.TS) {
   119  	be.RLock()
   120  	defer be.RUnlock()
   121  	return be.TryGetTerminatedTSLocked(waitIfcommitting)
   122  }
   123  
   124  func (be *BaseEntryImpl[T]) TryGetTerminatedTSLocked(waitIfcommitting bool) (terminated bool, TS types.TS) {
   125  	node := be.GetLatestCommittedNodeLocked()
   126  	if node == nil {
   127  		return
   128  	}
   129  	if node.HasDropCommitted() {
   130  		return true, node.DeletedAt
   131  	}
   132  	return
   133  }
   134  func (be *BaseEntryImpl[T]) PrepareAdd(txn txnif.TxnReader) (err error) {
   135  	if err = be.ConflictCheck(txn); err != nil {
   136  		return
   137  	}
   138  	// check duplication then
   139  	be.RLock()
   140  	defer be.RUnlock()
   141  	if txn == nil || be.GetTxn() != txn {
   142  		if !be.HasDropCommittedLocked() {
   143  			return moerr.GetOkExpectedDup()
   144  		}
   145  	} else {
   146  		if be.ensureVisibleAndNotDropped(txn) {
   147  			return moerr.GetOkExpectedDup()
   148  		}
   149  	}
   150  	return
   151  }
   152  
   153  func (be *BaseEntryImpl[T]) ConflictCheck(txn txnif.TxnReader) (err error) {
   154  	be.RLock()
   155  	defer be.RUnlock()
   156  	if txn != nil {
   157  		needWait, waitTxn := be.NeedWaitCommittingLocked(txn.GetStartTS())
   158  		if needWait {
   159  			be.RUnlock()
   160  			waitTxn.GetTxnState(true)
   161  			be.RLock()
   162  		}
   163  		err = be.CheckConflictLocked(txn)
   164  		if err != nil {
   165  			return
   166  		}
   167  	}
   168  	return
   169  }
   170  func (be *BaseEntryImpl[T]) getOrSetUpdateNodeLocked(txn txnif.TxnReader) (newNode bool, node *MVCCNode[T]) {
   171  	entry := be.GetLatestNodeLocked()
   172  	if entry.IsSameTxn(txn) {
   173  		return false, entry
   174  	} else {
   175  		node := entry.CloneData()
   176  		node.TxnMVCCNode = txnbase.NewTxnMVCCNodeWithTxn(txn)
   177  		be.Insert(node)
   178  		return true, node
   179  	}
   180  }
   181  
   182  func (be *BaseEntryImpl[T]) DeleteLocked(txn txnif.TxnReader) (isNewNode bool, err error) {
   183  	var entry *MVCCNode[T]
   184  	isNewNode, entry = be.getOrSetUpdateNodeLocked(txn)
   185  	entry.Delete()
   186  	return
   187  }
   188  
   189  func (be *BaseEntryImpl[T]) DeleteBefore(ts types.TS) bool {
   190  	be.RLock()
   191  	defer be.RUnlock()
   192  	return be.DeleteBeforeLocked(ts)
   193  }
   194  
   195  func (be *BaseEntryImpl[T]) DeleteBeforeLocked(ts types.TS) bool {
   196  	createAt := be.GetDeleteAtLocked()
   197  	if createAt.IsEmpty() {
   198  		return false
   199  	}
   200  	return createAt.Less(&ts)
   201  }
   202  
   203  func (be *BaseEntryImpl[T]) NeedWaitCommittingLocked(startTS types.TS) (bool, txnif.TxnReader) {
   204  	un := be.GetLatestNodeLocked()
   205  	if un == nil {
   206  		return false, nil
   207  	}
   208  	return un.NeedWaitCommitting(startTS)
   209  }
   210  
   211  func (be *BaseEntryImpl[T]) HasDropCommitted() bool {
   212  	be.RLock()
   213  	defer be.RUnlock()
   214  	return be.HasDropCommittedLocked()
   215  }
   216  
   217  func (be *BaseEntryImpl[T]) HasDropCommittedLocked() bool {
   218  	un := be.GetLatestCommittedNodeLocked()
   219  	if un == nil {
   220  		return false
   221  	}
   222  	return un.HasDropCommitted()
   223  }
   224  
   225  func (be *BaseEntryImpl[T]) ensureVisibleAndNotDropped(txn txnif.TxnReader) bool {
   226  	visible, dropped := be.GetVisibilityLocked(txn)
   227  	if !visible {
   228  		return false
   229  	}
   230  	return !dropped
   231  }
   232  
   233  func (be *BaseEntryImpl[T]) GetVisibilityLocked(txn txnif.TxnReader) (visible, dropped bool) {
   234  	un := be.GetVisibleNodeLocked(txn)
   235  	if un == nil {
   236  		return
   237  	}
   238  	visible = true
   239  	if un.IsSameTxn(txn) {
   240  		dropped = un.HasDropIntent()
   241  	} else {
   242  		dropped = un.HasDropCommitted()
   243  	}
   244  	return
   245  }
   246  
   247  func (be *BaseEntryImpl[T]) IsVisibleWithLock(txn txnif.TxnReader, mu *sync.RWMutex) (ok bool, err error) {
   248  	needWait, txnToWait := be.NeedWaitCommittingLocked(txn.GetStartTS())
   249  	if needWait {
   250  		mu.RUnlock()
   251  		txnToWait.GetTxnState(true)
   252  		mu.RLock()
   253  	}
   254  	ok = be.ensureVisibleAndNotDropped(txn)
   255  	return
   256  }
   257  
   258  func (be *BaseEntryImpl[T]) DropEntryLocked(txn txnif.TxnReader) (isNewNode bool, err error) {
   259  	err = be.CheckConflictLocked(txn)
   260  	if err != nil {
   261  		return
   262  	}
   263  	if be.HasDropCommittedLocked() {
   264  		return false, moerr.GetOkExpectedEOB()
   265  	}
   266  	isNewNode, err = be.DeleteLocked(txn)
   267  	return
   268  }
   269  
   270  func (be *BaseEntryImpl[T]) DeleteAfter(ts types.TS) bool {
   271  	un := be.GetLatestNodeLocked()
   272  	if un == nil {
   273  		return false
   274  	}
   275  	return un.DeletedAt.Greater(&ts)
   276  }
   277  
   278  func (be *BaseEntryImpl[T]) GetCreatedAtLocked() types.TS {
   279  	un := be.GetLatestNodeLocked()
   280  	if un == nil {
   281  		return types.TS{}
   282  	}
   283  	return un.CreatedAt
   284  }
   285  
   286  func (be *BaseEntryImpl[T]) GetDeleteAtLocked() types.TS {
   287  	un := be.GetLatestNodeLocked()
   288  	if un == nil {
   289  		return types.TS{}
   290  	}
   291  	return un.DeletedAt
   292  }
   293  
   294  func (be *BaseEntryImpl[T]) GetVisibility(txn txnif.TxnReader) (visible, dropped bool) {
   295  	be.RLock()
   296  	defer be.RUnlock()
   297  	needWait, txnToWait := be.NeedWaitCommittingLocked(txn.GetStartTS())
   298  	if needWait {
   299  		be.RUnlock()
   300  		txnToWait.GetTxnState(true)
   301  		be.RLock()
   302  	}
   303  	return be.GetVisibilityLocked(txn)
   304  }