github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/catalog/node.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  	"sync"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/txnif"
    24  )
    25  
    26  type nodeList[T any] struct {
    27  	common.SSLLNode
    28  	getter       func(uint64) *common.GenericDLNode[T]
    29  	visibilityFn func(*common.GenericDLNode[T], txnif.TxnReader) (bool, bool, string)
    30  	rwlocker     *sync.RWMutex
    31  	name         string
    32  }
    33  
    34  func newNodeList[T any](getter func(uint64) *common.GenericDLNode[T],
    35  	visibilityFn func(*common.GenericDLNode[T], txnif.TxnReader) (bool, bool, string),
    36  	rwlocker *sync.RWMutex,
    37  	name string) *nodeList[T] {
    38  	return &nodeList[T]{
    39  		SSLLNode:     *common.NewSSLLNode(),
    40  		getter:       getter,
    41  		visibilityFn: visibilityFn,
    42  		rwlocker:     rwlocker,
    43  		name:         name,
    44  	}
    45  }
    46  
    47  func (n *nodeList[T]) CreateNode(id uint64) *nameNode[T] {
    48  	nn := newNameNode(id, n.getter)
    49  	n.rwlocker.Lock()
    50  	defer n.rwlocker.Unlock()
    51  	n.Insert(nn)
    52  	return nn
    53  }
    54  
    55  func (n *nodeList[T]) DeleteNode(id uint64) (deleted *nameNode[T], empty bool) {
    56  	n.rwlocker.Lock()
    57  	defer n.rwlocker.Unlock()
    58  	var prev common.ISSLLNode
    59  	prev = n
    60  	curr := n.GetNext()
    61  	depth := 0
    62  	for curr != nil {
    63  		nid := curr.(*nameNode[T]).id
    64  		if id == nid {
    65  			prev.ReleaseNextNode()
    66  			deleted = curr.(*nameNode[T])
    67  			next := curr.GetNext()
    68  			if next == nil && depth == 0 {
    69  				empty = true
    70  			}
    71  			break
    72  		}
    73  		prev = curr
    74  		curr = curr.GetNext()
    75  		depth++
    76  	}
    77  	return
    78  }
    79  
    80  func (n *nodeList[T]) ForEachNodes(fn func(*nameNode[T]) bool) {
    81  	n.rwlocker.RLock()
    82  	defer n.rwlocker.RUnlock()
    83  	n.ForEachNodesLocked(fn)
    84  }
    85  
    86  func (n *nodeList[T]) ForEachNodesLocked(fn func(*nameNode[T]) bool) {
    87  	curr := n.GetNext()
    88  	for curr != nil {
    89  		nn := curr.(*nameNode[T])
    90  		if ok := fn(nn); !ok {
    91  			break
    92  		}
    93  		curr = curr.GetNext()
    94  	}
    95  }
    96  
    97  func (n *nodeList[T]) LengthLocked() int {
    98  	length := 0
    99  	fn := func(*nameNode[T]) bool {
   100  		length++
   101  		return true
   102  	}
   103  	n.ForEachNodesLocked(fn)
   104  	return length
   105  }
   106  
   107  func (n *nodeList[T]) Length() int {
   108  	n.rwlocker.RLock()
   109  	defer n.rwlocker.RUnlock()
   110  	return n.LengthLocked()
   111  }
   112  
   113  func (n *nodeList[T]) GetNode() *common.GenericDLNode[T] {
   114  	n.rwlocker.RLock()
   115  	defer n.rwlocker.RUnlock()
   116  	return n.GetNext().(*nameNode[T]).GetNode()
   117  }
   118  
   119  //	Create                  Deleted
   120  //	  |                        |
   121  //
   122  // --+------+-+------------+--+------+-+--+-------+--+----->
   123  //
   124  //	|      | |            |  |      | |  |       |  |
   125  //	|      +-|------Txn2--|--+      | |  +--Txn5-|--+
   126  //	+--Txn1--+            +----Txn3-|-+          |
   127  //	                                +----Txn4----+
   128  //
   129  // 1. Txn1 start and create a table "tb1"
   130  // 2. Txn2 start and cannot find "tb1".
   131  // 3. Txn1 commit
   132  // 4. Txn3 start and drop table "tb1"
   133  // 6. Txn4 start and can find "tb1"
   134  // 7. Txn3 commit
   135  // 8. Txn4 can still find "tb1"
   136  // 9. Txn5 start and cannot find "tb1"
   137  func (n *nodeList[T]) TxnGetNodeLocked(txn txnif.TxnReader, targetName string) (
   138  	tn *common.GenericDLNode[T], err error) {
   139  	fn := func(nn *nameNode[T]) bool {
   140  		dlNode := nn.GetNode()
   141  		visible, dropped, visibleName := n.visibilityFn(dlNode, txn)
   142  		if !visible {
   143  			// the txn is ancient, it is needed to check older history
   144  			return true
   145  		}
   146  		if dropped {
   147  			return true
   148  		}
   149  		if targetName != visibleName {
   150  			return true
   151  		}
   152  		tn = dlNode
   153  		return false
   154  	}
   155  	n.ForEachNodes(fn)
   156  	if tn == nil && err == nil {
   157  		err = moerr.GetOkExpectedEOB()
   158  	}
   159  	return
   160  }
   161  
   162  func (n *nodeList[T]) PString(level common.PPLevel) string {
   163  	curr := n.GetNext()
   164  	if curr == nil {
   165  		return fmt.Sprintf("TableNode[\"%s\"](Len=0)", n.name)
   166  	}
   167  	node := curr.(*nameNode[T])
   168  	s := fmt.Sprintf("TableNode[\"%s\"](Len=%d)->[%d", n.name, n.Length(), node.id)
   169  	if level == common.PPL0 {
   170  		s = fmt.Sprintf("%s]", s)
   171  		return s
   172  	}
   173  
   174  	curr = curr.GetNext()
   175  	for curr != nil {
   176  		node := curr.(*nameNode[T])
   177  		s = fmt.Sprintf("%s->%d", s, node.id)
   178  		curr = curr.GetNext()
   179  	}
   180  	s = fmt.Sprintf("%s]", s)
   181  	return s
   182  }
   183  
   184  type nameNode[T any] struct {
   185  	common.SSLLNode
   186  	getter func(uint64) *common.GenericDLNode[T]
   187  	id     uint64
   188  }
   189  
   190  func newNameNode[T any](id uint64,
   191  	getter func(uint64) *common.GenericDLNode[T]) *nameNode[T] {
   192  	return &nameNode[T]{
   193  		SSLLNode: *common.NewSSLLNode(),
   194  		getter:   getter,
   195  		id:       id,
   196  	}
   197  }
   198  
   199  func (n *nameNode[T]) GetNode() *common.GenericDLNode[T] {
   200  	if n == nil {
   201  		return nil
   202  	}
   203  	return n.getter(n.id)
   204  }