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  }