commit
20ca21a3f7
|
@ -0,0 +1,74 @@
|
||||||
|
package raftd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"errors"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Store struct {
|
||||||
|
Nodes map[string]string `json:"nodes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func createStore() *Store{
|
||||||
|
s := new(Store)
|
||||||
|
s.Nodes = make(map[string]string)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the key to value, return the old value if the key exists
|
||||||
|
func (s *Store) Set(key string, value string) (string, bool) {
|
||||||
|
|
||||||
|
key = path.Clean(key)
|
||||||
|
|
||||||
|
oldValue, ok := s.Nodes[key]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
s.Nodes[key] = value
|
||||||
|
return oldValue, true
|
||||||
|
} else {
|
||||||
|
s.Nodes[key] = value
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the node of the key
|
||||||
|
func (s *Store) Get(key string) (string, error) {
|
||||||
|
key = path.Clean(key)
|
||||||
|
|
||||||
|
value, ok := s.Nodes[key]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return value, nil
|
||||||
|
} else {
|
||||||
|
return "", errors.New("Key does not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the key, return the old value if the key exists
|
||||||
|
func (s *Store) Delete(key string) (string, error) {
|
||||||
|
key = path.Clean(key)
|
||||||
|
|
||||||
|
oldValue, ok := s.Nodes[key]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
delete(s.Nodes, key)
|
||||||
|
return oldValue, nil
|
||||||
|
} else {
|
||||||
|
return "", errors.New("Key does not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Save() ([]byte, error) {
|
||||||
|
b, err := json.Marshal(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Recovery(state []byte) error {
|
||||||
|
err := json.Unmarshal(state, s)
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package raftd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStoreGet(t *testing.T) {
|
||||||
|
store := createStore()
|
||||||
|
|
||||||
|
store.Set("foo", "bar")
|
||||||
|
|
||||||
|
value, err := store.Get("foo")
|
||||||
|
|
||||||
|
if err!= nil || value != "bar" {
|
||||||
|
t.Fatalf("Cannot get stored value")
|
||||||
|
}
|
||||||
|
|
||||||
|
store.Delete("foo")
|
||||||
|
value, err = store.Get("foo")
|
||||||
|
|
||||||
|
if err == nil{
|
||||||
|
t.Fatalf("Got deleted value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaveAndRecovery(t *testing.T) {
|
||||||
|
store := createStore()
|
||||||
|
|
||||||
|
store.Set("foo", "bar")
|
||||||
|
|
||||||
|
state, err := store.Save()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Cannot Save")
|
||||||
|
}
|
||||||
|
|
||||||
|
newStore := createStore()
|
||||||
|
newStore.Recovery(state)
|
||||||
|
|
||||||
|
value, err := newStore.Get("foo")
|
||||||
|
|
||||||
|
if err!= nil || value != "bar" {
|
||||||
|
t.Fatalf("Cannot recovery")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type store struct {
|
||||||
|
nodes map[string]node
|
||||||
|
}
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
value string
|
||||||
|
dir bool // just for clearity
|
||||||
|
nodes map[string]node
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the key to value, return the old value if the key exists
|
||||||
|
func (s *store) set(key string, value string) string, error {
|
||||||
|
|
||||||
|
key = path.Clean(key)
|
||||||
|
|
||||||
|
nodeNames := strings.Split(key, "/")
|
||||||
|
|
||||||
|
levelNodes := s.nodes
|
||||||
|
for i = 0; i < len(nodes) - 1; ++i {
|
||||||
|
node, ok := levelNodes[nodeNames[i]]
|
||||||
|
// add new dir
|
||||||
|
if !ok {
|
||||||
|
node := Node{nodeNames[i], true, make(map[string]node)}
|
||||||
|
levelNodes[nodeNames[i]] := node
|
||||||
|
} else if ok && !node.dir {
|
||||||
|
return nil, errors.New("The key is a directory")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
levelNodes = levelNodes.nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add the last node and value
|
||||||
|
node, ok := levelNodes[nodeNames[i]]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
node := Node{nodeNames[i], false, nil}
|
||||||
|
levelNodes[nodeNames] = node
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
oldValue := node.value
|
||||||
|
node.value = value
|
||||||
|
return oldValue ,nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the node of the key
|
||||||
|
func (s *store) get(key string) node {
|
||||||
|
key = path.Clean(key)
|
||||||
|
|
||||||
|
nodeNames := strings.Split(key, "/")
|
||||||
|
|
||||||
|
levelNodes := s.nodes
|
||||||
|
|
||||||
|
for i = 0; i < len(nodes) - 1; ++i {
|
||||||
|
node, ok := levelNodes[nodeNames[i]]
|
||||||
|
if !ok || !node.dir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
levelNodes = levelNodes.nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
node, ok := levelNodes[nodeNames[i]]
|
||||||
|
if ok {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the key, return the old value if the key exists
|
||||||
|
func (s *store) delete(key string) string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) Value() string{
|
||||||
|
return n.value
|
||||||
|
}
|
Loading…
Reference in New Issue