1
0
mirror of https://github.com/taigrr/bitcask synced 2025-01-18 04:03:17 -08:00
bitcask/internal/keydir.go

130 lines
2.0 KiB
Go

package internal
import (
"bytes"
"encoding/gob"
"io"
"io/ioutil"
"os"
"sync"
)
type Item struct {
FileID int
Offset int64
Size int64
}
type Keydir struct {
sync.RWMutex
keys map[uint64][]byte
items map[uint64]Item
}
func NewKeydir() *Keydir {
return &Keydir{
keys: make(map[uint64][]byte),
items: make(map[uint64]Item),
}
}
func (k *Keydir) Add(key []byte, fileid int, offset, size int64) Item {
item := Item{
FileID: fileid,
Offset: offset,
Size: size,
}
hash := Hash(key)
k.Lock()
k.keys[hash] = key
k.items[hash] = item
k.Unlock()
return item
}
func (k *Keydir) Get(key []byte) (Item, bool) {
k.RLock()
item, ok := k.items[Hash(key)]
k.RUnlock()
return item, ok
}
func (k *Keydir) Delete(key []byte) {
hash := Hash(key)
k.Lock()
delete(k.keys, hash)
delete(k.items, hash)
k.Unlock()
}
func (k *Keydir) Len() int {
return len(k.keys)
}
func (k *Keydir) Keys() chan []byte {
ch := make(chan []byte)
go func() {
k.RLock()
for _, key := range k.keys {
ch <- key
}
close(ch)
k.RUnlock()
}()
return ch
}
func (k *Keydir) Bytes() ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err := enc.Encode(k.keys); err != nil {
return nil, err
}
if err := enc.Encode(k.items); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (k *Keydir) Load(fn string) error {
f, err := os.Open(fn)
if err != nil {
return err
}
defer f.Close()
dec := gob.NewDecoder(f)
if err := dec.Decode(&k.keys); err != nil {
return err
}
if err := dec.Decode(&k.items); err != nil {
return err
}
return nil
}
func (k *Keydir) Save(fn string) error {
data, err := k.Bytes()
if err != nil {
return err
}
return ioutil.WriteFile(fn, data, 0644)
}
func NewKeydirFromBytes(r io.Reader) (*Keydir, error) {
k := NewKeydir()
dec := gob.NewDecoder(r)
if err := dec.Decode(&k.keys); err != nil {
return nil, err
}
if err := dec.Decode(&k.items); err != nil {
return nil, err
}
return k, nil
}