github.com/matrixorigin/matrixone@v0.7.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/container/types"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    24  )
    25  
    26  type nodeList[T any] struct {
    27  	common.SSLLNode
    28  	getter       func(uint64) *common.GenericDLNode[T]
    29  	visibilityFn func(*common.GenericDLNode[T], types.TS) (bool, bool)
    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], types.TS) (bool, bool),
    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(ts types.TS) (
   138  	dn *common.GenericDLNode[T], err error) {
   139  	fn := func(nn *nameNode[T]) bool {
   140  		dlNode := nn.GetNode()
   141  		visible, dropped := n.visibilityFn(dlNode, ts)
   142  		if !visible {
   143  			return true
   144  		}
   145  		if dropped {
   146  			return false
   147  		}
   148  		dn = dlNode
   149  		return true
   150  	}
   151  	n.ForEachNodes(fn)
   152  	if dn == nil && err == nil {
   153  		err = moerr.GetOkExpectedEOB()
   154  	}
   155  	return
   156  }
   157  
   158  func (n *nodeList[T]) PString(level common.PPLevel) string {
   159  	curr := n.GetNext()
   160  	if curr == nil {
   161  		return fmt.Sprintf("TableNode[\"%s\"](Len=0)", n.name)
   162  	}
   163  	node := curr.(*nameNode[T])
   164  	s := fmt.Sprintf("TableNode[\"%s\"](Len=%d)->[%d", n.name, n.Length(), node.id)
   165  	if level == common.PPL0 {
   166  		s = fmt.Sprintf("%s]", s)
   167  		return s
   168  	}
   169  
   170  	curr = curr.GetNext()
   171  	for curr != nil {
   172  		node := curr.(*nameNode[T])
   173  		s = fmt.Sprintf("%s->%d", s, node.id)
   174  		curr = curr.GetNext()
   175  	}
   176  	s = fmt.Sprintf("%s]", s)
   177  	return s
   178  }
   179  
   180  type nameNode[T any] struct {
   181  	common.SSLLNode
   182  	getter func(uint64) *common.GenericDLNode[T]
   183  	id     uint64
   184  }
   185  
   186  func newNameNode[T any](id uint64,
   187  	getter func(uint64) *common.GenericDLNode[T]) *nameNode[T] {
   188  	return &nameNode[T]{
   189  		SSLLNode: *common.NewSSLLNode(),
   190  		getter:   getter,
   191  		id:       id,
   192  	}
   193  }
   194  
   195  func (n *nameNode[T]) GetNode() *common.GenericDLNode[T] {
   196  	if n == nil {
   197  		return nil
   198  	}
   199  	return n.getter(n.id)
   200  }