github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/arenaskl/node.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 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 arenaskl 16 17 import ( 18 "math" 19 "sync/atomic" 20 21 "github.com/zuoyebang/bitalosdb/internal/base" 22 ) 23 24 func MaxNodeSize(keySize, valueSize uint32) uint32 { 25 return uint32(maxNodeSize) + keySize + valueSize + align4 26 } 27 28 type links struct { 29 nextOffset uint32 30 prevOffset uint32 31 } 32 33 func (l *links) init(prevOffset, nextOffset uint32) { 34 l.nextOffset = nextOffset 35 l.prevOffset = prevOffset 36 } 37 38 type node struct { 39 keyOffset uint32 40 keySize uint32 41 valueSize uint32 42 allocSize uint32 43 skipToFirst uint32 44 skipToLast uint32 45 tower [maxHeight]links 46 } 47 48 func newNode( 49 arena *Arena, height uint32, key base.InternalKey, value []byte, 50 ) (nd *node, err error) { 51 if height < 1 || height > maxHeight { 52 panic("height cannot be less than one or greater than the max height") 53 } 54 keySize := key.Size() 55 if int64(keySize) > math.MaxUint32 { 56 panic("key is too large") 57 } 58 valueSize := len(value) 59 if int64(len(value)) > math.MaxUint32 { 60 panic("value is too large") 61 } 62 63 nd, err = newRawNode(arena, height, uint32(keySize), uint32(valueSize)) 64 if err != nil { 65 return 66 } 67 68 key.Encode(nd.getKeyBytes(arena)) 69 copy(nd.getValue(arena), value) 70 return 71 } 72 73 func newRawNode(arena *Arena, height uint32, keySize, valueSize uint32) (nd *node, err error) { 74 unusedSize := uint32((maxHeight - int(height)) * linksSize) 75 nodeSize := uint32(maxNodeSize) - unusedSize 76 77 nodeOffset, allocSize, err := arena.alloc(nodeSize+keySize+valueSize, align4, unusedSize) 78 if err != nil { 79 return 80 } 81 82 nd = (*node)(arena.getPointer(nodeOffset)) 83 nd.keyOffset = nodeOffset + nodeSize 84 nd.keySize = keySize 85 nd.valueSize = valueSize 86 nd.allocSize = allocSize 87 nd.skipToFirst = 0 88 nd.skipToLast = 0 89 return 90 } 91 92 func (n *node) getKeyBytes(arena *Arena) []byte { 93 return arena.getBytes(n.keyOffset, n.keySize) 94 } 95 96 func (n *node) getValue(arena *Arena) []byte { 97 return arena.getBytes(n.keyOffset+n.keySize, n.valueSize) 98 } 99 100 func (n *node) nextOffset(h int) uint32 { 101 return atomic.LoadUint32(&n.tower[h].nextOffset) 102 } 103 104 func (n *node) skipToFirstOffset() uint32 { 105 return atomic.LoadUint32(&n.skipToFirst) 106 } 107 108 func (n *node) setSkipToFirstOffset(val uint32) { 109 atomic.StoreUint32(&n.skipToFirst, val) 110 } 111 112 func (n *node) skipToLastOffset() uint32 { 113 return atomic.LoadUint32(&n.skipToLast) 114 } 115 116 func (n *node) setSkipToLastOffset(val uint32) { 117 atomic.StoreUint32(&n.skipToLast, val) 118 } 119 120 func (n *node) prevOffset(h int) uint32 { 121 return atomic.LoadUint32(&n.tower[h].prevOffset) 122 } 123 124 func (n *node) casNextOffset(h int, old, val uint32) bool { 125 return atomic.CompareAndSwapUint32(&n.tower[h].nextOffset, old, val) 126 } 127 128 func (n *node) casPrevOffset(h int, old, val uint32) bool { 129 return atomic.CompareAndSwapUint32(&n.tower[h].prevOffset, old, val) 130 }