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 }