mirror of
https://github.com/taigrr/bitcask
synced 2025-01-18 04:03:17 -08:00
* Replace keydir with ART trie * Address some review feedback * Address review feedback (consts)
111 lines
2.1 KiB
Go
111 lines
2.1 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
|
|
art "github.com/plar/go-adaptive-radix-tree"
|
|
)
|
|
|
|
const (
|
|
Int32Size = 4
|
|
Int64Size = 8
|
|
FileIDSize = Int32Size
|
|
OffsetSize = Int64Size
|
|
SizeSize = Int64Size
|
|
)
|
|
|
|
func ReadBytes(r io.Reader) ([]byte, error) {
|
|
s := make([]byte, Int32Size)
|
|
_, err := io.ReadFull(r, s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
size := binary.BigEndian.Uint32(s)
|
|
b := make([]byte, size)
|
|
_, err = io.ReadFull(r, b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func WriteBytes(b []byte, w io.Writer) (int, error) {
|
|
s := make([]byte, Int32Size)
|
|
binary.BigEndian.PutUint32(s, uint32(len(b)))
|
|
n, err := w.Write(s)
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
m, err := w.Write(b)
|
|
if err != nil {
|
|
return (n + m), err
|
|
}
|
|
return (n + m), nil
|
|
}
|
|
|
|
func ReadItem(r io.Reader) (Item, error) {
|
|
buf := make([]byte, (FileIDSize + OffsetSize + SizeSize))
|
|
_, err := io.ReadFull(r, buf)
|
|
if err != nil {
|
|
return Item{}, err
|
|
}
|
|
|
|
return Item{
|
|
FileID: int(binary.BigEndian.Uint32(buf[:FileIDSize])),
|
|
Offset: int64(binary.BigEndian.Uint64(buf[FileIDSize:(FileIDSize + OffsetSize)])),
|
|
Size: int64(binary.BigEndian.Uint64(buf[(FileIDSize + OffsetSize):])),
|
|
}, nil
|
|
}
|
|
|
|
func WriteItem(item Item, w io.Writer) (int, error) {
|
|
buf := make([]byte, (FileIDSize + OffsetSize + SizeSize))
|
|
binary.BigEndian.PutUint32(buf[:FileIDSize], uint32(item.FileID))
|
|
binary.BigEndian.PutUint64(buf[FileIDSize:(FileIDSize+OffsetSize)], uint64(item.Offset))
|
|
binary.BigEndian.PutUint64(buf[(FileIDSize+OffsetSize):], uint64(item.Size))
|
|
n, err := w.Write(buf)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
func ReadIndex(r io.Reader, t art.Tree) error {
|
|
for {
|
|
key, err := ReadBytes(r)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return err
|
|
}
|
|
|
|
item, err := ReadItem(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
t.Insert(key, item)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func WriteIndex(t art.Tree, w io.Writer) (err error) {
|
|
t.ForEach(func(node art.Node) bool {
|
|
_, err = WriteBytes(node.Key(), w)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
item := node.Value().(Item)
|
|
_, err := WriteItem(item, w)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
})
|
|
return
|
|
}
|