github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/buffer/node.go (about)

     1  // Copyright 2022 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 buffer
    16  
    17  import (
    18  	"context"
    19  	"sync"
    20  	"sync/atomic"
    21  	"time"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/buffer/base"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    25  )
    26  
    27  type nodeHandle struct {
    28  	n   base.INode
    29  	mgr base.INodeManager
    30  }
    31  
    32  func newNodeHandle(n base.INode, mgr base.INodeManager) *nodeHandle {
    33  	return &nodeHandle{
    34  		n:   n,
    35  		mgr: mgr,
    36  	}
    37  }
    38  
    39  func (h *nodeHandle) Key() any {
    40  	return h.n.Key()
    41  }
    42  
    43  func (h *nodeHandle) GetNode() base.INode {
    44  	return h.n
    45  }
    46  
    47  func (h *nodeHandle) Close() error {
    48  	h.mgr.Unpin(h.n)
    49  	return nil
    50  }
    51  
    52  type Node struct {
    53  	common.RefHelper
    54  	sync.RWMutex
    55  	mgr               base.INodeManager
    56  	key               any
    57  	state             base.NodeState
    58  	size              uint64
    59  	iter              atomic.Uint64
    60  	closed            bool
    61  	impl              base.INode
    62  	HardEvictableFunc func() bool
    63  	DestroyFunc       func()
    64  	LoadFunc          func()
    65  	UnloadableFunc    func() bool
    66  	UnloadFunc        func()
    67  }
    68  
    69  func NewNode(impl base.INode, mgr base.INodeManager, key any, size uint64) *Node {
    70  	return &Node{
    71  		mgr:  mgr,
    72  		key:  key,
    73  		size: size,
    74  		impl: impl,
    75  	}
    76  }
    77  
    78  func (n *Node) Size() uint64 {
    79  	return n.size
    80  }
    81  
    82  func (n *Node) Key() any {
    83  	return n.key
    84  }
    85  
    86  func (n *Node) MakeHandle() base.INodeHandle {
    87  	if n.impl != nil {
    88  		return newNodeHandle(n.impl, n.mgr)
    89  	}
    90  	return newNodeHandle(n, n.mgr)
    91  }
    92  
    93  func (n *Node) TryClose() (closed bool) {
    94  	n.Lock()
    95  	if n.RefCount() > 0 {
    96  		return false
    97  	}
    98  	if n.closed {
    99  		n.Unlock()
   100  		return true
   101  	}
   102  	n.closed = true
   103  	if n.state == base.NodeLoaded {
   104  		n.Unload()
   105  	}
   106  	n.Unlock()
   107  	n.mgr.UnregisterNode(n)
   108  	return true
   109  }
   110  
   111  func (n *Node) Close() error {
   112  	n.Lock()
   113  	if n.closed {
   114  		n.Unlock()
   115  		return nil
   116  	}
   117  	n.closed = true
   118  	if n.state == base.NodeLoaded {
   119  		n.Unload()
   120  	}
   121  	n.Unlock()
   122  	n.mgr.UnregisterNode(n)
   123  	return nil
   124  }
   125  
   126  func (n *Node) IsClosed() bool {
   127  	return n.closed
   128  }
   129  
   130  func (n *Node) HardEvictable() bool {
   131  	if n.HardEvictableFunc != nil {
   132  		return n.HardEvictableFunc()
   133  	}
   134  	return false
   135  }
   136  
   137  func (n *Node) Destroy() {
   138  	if n.DestroyFunc != nil {
   139  		n.DestroyFunc()
   140  	}
   141  }
   142  
   143  // Load should be guarded by lock
   144  func (n *Node) Load() {
   145  	if n.state == base.NodeLoaded {
   146  		return
   147  	}
   148  	if n.LoadFunc != nil {
   149  		n.LoadFunc()
   150  	}
   151  	n.state = base.NodeLoaded
   152  }
   153  
   154  // Unload should be guarded by lock
   155  func (n *Node) Unload() {
   156  	if n.state == base.NodeUnload {
   157  		return
   158  	}
   159  	n.mgr.RetuernQuota(n.size)
   160  	if n.UnloadFunc != nil {
   161  		n.UnloadFunc()
   162  	}
   163  	n.state = base.NodeUnload
   164  }
   165  
   166  // Unloadable should be guarded by lock
   167  func (n *Node) Unloadable() bool {
   168  	if n.state == base.NodeUnload {
   169  		return false
   170  	}
   171  	if n.RefCount() > 0 {
   172  		return false
   173  	}
   174  	ret := true
   175  	if n.UnloadableFunc != nil {
   176  		ret = n.UnloadableFunc()
   177  	}
   178  	return ret
   179  }
   180  
   181  // GetState should be guarded by lock
   182  func (n *Node) GetState() base.NodeState {
   183  	return n.state
   184  }
   185  
   186  func (n *Node) prepareExpand(delta uint64) bool {
   187  	return n.mgr.MakeRoom(delta)
   188  }
   189  
   190  func (n *Node) Expand(delta uint64, fn func() error) error {
   191  	if !n.prepareExpand(delta) {
   192  		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   193  		defer cancel()
   194  		err := common.DoRetry(func() error {
   195  			if !n.prepareExpand(delta) {
   196  				return base.ErrNoSpace
   197  			}
   198  			return nil
   199  		}, ctx)
   200  		if err != nil {
   201  			return err
   202  		}
   203  	}
   204  	if fn != nil {
   205  		if err := fn(); err != nil {
   206  			n.rollbackExpand(delta)
   207  			return err
   208  		}
   209  	}
   210  	n.commitExpand(delta)
   211  	return nil
   212  }
   213  
   214  func (n *Node) commitExpand(delta uint64) {
   215  	n.size += delta
   216  }
   217  
   218  func (n *Node) rollbackExpand(delta uint64) {
   219  	n.mgr.RetuernQuota(delta)
   220  }
   221  
   222  // IsLoaded should be guarded by lock
   223  func (n *Node) IsLoaded() bool { return n.state == base.NodeLoaded }
   224  
   225  func (n *Node) IncIteration() uint64 {
   226  	return n.iter.Add(1)
   227  }
   228  
   229  func (n *Node) Iteration() uint64 {
   230  	return n.iter.Load()
   231  }