80 lines
1.3 KiB
Go
80 lines
1.3 KiB
Go
package raft
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"sync"
|
|
|
|
"git.giftfish.de/ston1th/raftbbolt/msgpack"
|
|
"github.com/hashicorp/raft"
|
|
)
|
|
|
|
var (
|
|
ErrNotLeader = errors.New("raft: not leader")
|
|
ErrKeyNotFound = errors.New("raft: key not found")
|
|
ErrPrefixNotFound = errors.New("raft: prefix not found")
|
|
)
|
|
|
|
type kvm map[string][]byte
|
|
|
|
type kv struct {
|
|
mu sync.Mutex
|
|
m kvm
|
|
r *raft.Raft
|
|
}
|
|
|
|
func (kv *kv) Get(k string) ([]byte, error) {
|
|
kv.mu.Lock()
|
|
defer kv.mu.Unlock()
|
|
v, ok := kv.m[k]
|
|
if !ok {
|
|
return nil, ErrKeyNotFound
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func (kv *kv) GetPrefix(pk string) (m map[string][]byte, err error) {
|
|
kv.mu.Lock()
|
|
defer kv.mu.Unlock()
|
|
m = make(map[string][]byte)
|
|
for k, v := range kv.m {
|
|
if strings.HasPrefix(k, pk) {
|
|
m[k] = v
|
|
}
|
|
}
|
|
if len(m) == 0 {
|
|
err = ErrPrefixNotFound
|
|
}
|
|
return
|
|
}
|
|
|
|
func (kv *kv) Set(k string, v []byte) error {
|
|
if kv.r.State() != raft.Leader {
|
|
return ErrNotLeader
|
|
}
|
|
|
|
c := &raftCmd{SET, k, v}
|
|
b, err := msgpack.Marshal(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f := kv.r.Apply(b, raftTimeout)
|
|
return f.Error()
|
|
}
|
|
|
|
// Delete deletes the given key.
|
|
func (kv *kv) Delete(k string) error {
|
|
if kv.r.State() != raft.Leader {
|
|
return ErrNotLeader
|
|
}
|
|
|
|
c := &raftCmd{Op: DELETE, K: k}
|
|
b, err := msgpack.Marshal(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f := kv.r.Apply(b, raftTimeout)
|
|
return f.Error()
|
|
}
|