github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bithash/block2.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 bithash
    16  
    17  import (
    18  	"encoding/binary"
    19  	"io"
    20  	"unsafe"
    21  
    22  	"github.com/zuoyebang/bitalosdb/internal/manual"
    23  )
    24  
    25  const recordHeaderSize = 12
    26  
    27  type block2Reader struct {
    28  }
    29  
    30  func (i *block2Reader) readRecordHeader(buf []byte) (ikeySize, valueSize uint32, fileNum FileNum) {
    31  	ikeySize = binary.LittleEndian.Uint32(buf[0:4])
    32  	valueSize = binary.LittleEndian.Uint32(buf[4:8])
    33  	fileNum = FileNum(binary.LittleEndian.Uint32(buf[8:12]))
    34  	return
    35  }
    36  
    37  func (i *block2Reader) readKV(buf []byte, ikeySize, valueSize uint32) (*InternalKey, []byte) {
    38  	ptr := unsafe.Pointer(&buf[0])
    39  
    40  	key := getBytes(ptr, int(ikeySize))
    41  
    42  	ptr = unsafe.Pointer(uintptr(ptr) + uintptr(ikeySize))
    43  	value := getBytes(ptr, int(valueSize))
    44  
    45  	var k InternalKey
    46  	if n := len(key) - 8; n >= 0 {
    47  		k.Trailer = binary.LittleEndian.Uint64(key[n:])
    48  		k.UserKey = key[:n:n]
    49  	} else {
    50  		k.Trailer = uint64(InternalKeyKindInvalid)
    51  	}
    52  
    53  	return &k, value
    54  }
    55  
    56  func (i *block2Reader) readRecord(buf []byte) (*InternalKey, []byte, FileNum) {
    57  	ikeySize, valueSize, fileNum := i.readRecordHeader(buf)
    58  	recordLen := int(recordHeaderSize + ikeySize + valueSize)
    59  	if ikeySize == 0 || valueSize == 0 || len(buf) != recordLen {
    60  		return nil, nil, FileNum(0)
    61  	}
    62  
    63  	k, value := i.readKV(buf[recordHeaderSize:], ikeySize, valueSize)
    64  	return k, value, fileNum
    65  }
    66  
    67  type block2Writer struct {
    68  	buf []byte
    69  	wr  io.Writer
    70  }
    71  
    72  func (w *block2Writer) set(key InternalKey, value []byte, fileNum FileNum) (int, error) {
    73  	keySize := key.Size()
    74  	preSize := keySize + recordHeaderSize
    75  	wrn := 0
    76  
    77  	if cap(w.buf) < preSize {
    78  		w.buf = make([]byte, 0, preSize*2)
    79  	}
    80  
    81  	w.buf = w.buf[:preSize]
    82  	binary.LittleEndian.PutUint32(w.buf[0:4], uint32(keySize))
    83  	binary.LittleEndian.PutUint32(w.buf[4:8], uint32(len(value)))
    84  	binary.LittleEndian.PutUint32(w.buf[8:12], uint32(fileNum))
    85  
    86  	key.Encode(w.buf[recordHeaderSize:])
    87  	n, err := w.wr.Write(w.buf)
    88  	if err != nil {
    89  		return 0, err
    90  	}
    91  	wrn += n
    92  
    93  	n, err = w.wr.Write(value)
    94  	if err != nil {
    95  		return 0, err
    96  	}
    97  	wrn += n
    98  
    99  	w.buf = w.buf[:0]
   100  	return wrn, nil
   101  }
   102  
   103  func (w *block2Writer) setEmptyHeader() (int, error) {
   104  	var buf [recordHeaderSize]byte
   105  	for i := range buf {
   106  		buf[i] = 0
   107  	}
   108  
   109  	n, err := w.wr.Write(buf[:])
   110  	if err != nil {
   111  		return 0, err
   112  	}
   113  	return n, nil
   114  }
   115  
   116  func getBytes(ptr unsafe.Pointer, length int) []byte {
   117  	return (*[manual.MaxArrayLen]byte)(ptr)[:length:length]
   118  }