Merge pull request #9 from fengjingchao/fileSystem

New error-system for Etcd with docs
This commit is contained in:
Xiang Li 2013-09-08 16:25:47 -07:00
commit 7ad523270d
7 changed files with 122 additions and 35 deletions

View File

@ -0,0 +1,58 @@
Error Code
======
This document describes the error code in **Etcd** project.
It's categorized into four groups:
- Command Related Error
- Post Form Related Error
- Raft Related Error
- Etcd Related Error
Error code corresponding strerror
------
const (
EcodeKeyNotFound = 100
EcodeTestFailed = 101
EcodeNotFile = 102
EcodeNoMoreMachine = 103
EcodeNotDir = 104
EcodeNodeExist = 105
EcodeKeyIsPreserved = 106
EcodeValueRequired = 200
EcodePrevValueRequired = 201
EcodeTTLNaN = 202
EcodeIndexNaN = 203
EcodeRaftInternal = 300
EcodeLeaderElect = 301
EcodeWatcherCleared = 400
EcodeEventIndexCleared = 401
)
// command related errors
errors[100] = "Key Not Found"
errors[101] = "Test Failed" //test and set
errors[102] = "Not A File"
errors[103] = "Reached the max number of machines in the cluster"
errors[104] = "Not A Directory"
errors[105] = "Already exists" // create
errors[106] = "The prefix of given key is a keyword in etcd"
// Post form related errors
errors[200] = "Value is Required in POST form"
errors[201] = "PrevValue is Required in POST form"
errors[202] = "The given TTL in POST form is not a number"
errors[203] = "The given index in POST form is not a number"
// raft related errors
errors[300] = "Raft Internal Error"
errors[301] = "During Leader Election"
// etcd related errors
errors[400] = "watcher is cleared due to etcd recovery"
errors[401] = "The event in requested index is outdated and cleared"

View File

@ -156,7 +156,7 @@ func (c *JoinCommand) Apply(raftServer *raft.Server) (interface{}, error) {
num := machineNum()
if num == maxClusterSize {
debug("Reject join request from ", c.Name)
return []byte{0}, etcdErr.NewError(103, "")
return []byte{0}, etcdErr.NewError(etcdErr.EcodeNoMoreMachine, "")
}
addNameToURL(c.Name, c.RaftVersion, c.RaftURL, c.EtcdURL)

View File

@ -7,18 +7,38 @@ import (
var errors map[int]string
const ()
const (
EcodeKeyNotFound = 100
EcodeTestFailed = 101
EcodeNotFile = 102
EcodeNoMoreMachine = 103
EcodeNotDir = 104
EcodeNodeExist = 105
EcodeKeyIsPreserved = 106
EcodeValueRequired = 200
EcodePrevValueRequired = 201
EcodeTTLNaN = 202
EcodeIndexNaN = 203
EcodeRaftInternal = 300
EcodeLeaderElect = 301
EcodeWatcherCleared = 400
EcodeEventIndexCleared = 401
)
func init() {
errors = make(map[int]string)
// command related errors
errors[100] = "Key Not Found"
errors[101] = "Test Failed"
errors[101] = "Test Failed" //test and set
errors[102] = "Not A File"
errors[103] = "Reached the max number of machines in the cluster"
errors[104] = "Not A Directory"
errors[105] = "Already exists"
errors[105] = "Already exists" // create
errors[106] = "The prefix of given key is a keyword in etcd"
// Post form related errors
errors[200] = "Value is Required in POST form"
@ -30,11 +50,9 @@ func init() {
errors[300] = "Raft Internal Error"
errors[301] = "During Leader Election"
// keyword
errors[400] = "The prefix of the given key is a keyword in etcd"
// etcd related errors
errors[500] = "watcher is cleared due to etcd recovery"
errors[400] = "watcher is cleared due to etcd recovery"
errors[401] = "The event in requested index is outdated and cleared"
}

View File

@ -68,7 +68,7 @@ func SetHttpHandler(w http.ResponseWriter, req *http.Request) error {
key := req.URL.Path[len("/v1/keys/"):]
if store.CheckKeyword(key) {
return etcdErr.NewError(400, "Set")
return etcdErr.NewError(etcdErr.EcodeKeyIsPreserved, "Set")
}
debugf("[recv] POST %v/v1/keys/%s [%s]", e.url, key, req.RemoteAddr)
@ -76,7 +76,7 @@ func SetHttpHandler(w http.ResponseWriter, req *http.Request) error {
value := req.FormValue("value")
if len(value) == 0 {
return etcdErr.NewError(200, "Set")
return etcdErr.NewError(etcdErr.EcodeValueRequired, "Set")
}
prevValue := req.FormValue("prevValue")
@ -86,7 +86,7 @@ func SetHttpHandler(w http.ResponseWriter, req *http.Request) error {
expireTime, err := durationToExpireTime(strDuration)
if err != nil {
return etcdErr.NewError(202, "Set")
return etcdErr.NewError(etcdErr.EcodeTTLNaN, "Set")
}
if len(prevValue) != 0 {
@ -131,7 +131,7 @@ func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) er
return err
} else {
if body == nil {
return etcdErr.NewError(300, "Empty result from raft")
return etcdErr.NewError(etcdErr.EcodeRaftInternal, "Empty result from raft")
} else {
body, _ := body.([]byte)
w.WriteHeader(http.StatusOK)
@ -144,7 +144,7 @@ func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) er
leader := r.Leader()
// current no leader
if leader == "" {
return etcdErr.NewError(300, "")
return etcdErr.NewError(etcdErr.EcodeRaftInternal, "")
}
// tell the client where is the leader
@ -165,7 +165,7 @@ func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) er
http.Redirect(w, req, url, http.StatusTemporaryRedirect)
return nil
}
return etcdErr.NewError(300, "")
return etcdErr.NewError(etcdErr.EcodeRaftInternal, "")
}
//--------------------------------------
@ -185,7 +185,7 @@ func dispatch(c Command, w http.ResponseWriter, req *http.Request, etcd bool) er
// w.Write([]byte(raftURL))
// return nil
// } else {
// return etcdErr.NewError(301, "")
// return etcdErr.NewError(etcdErr.EcodeLeaderElect, "")
// }
// }
@ -254,7 +254,7 @@ func WatchHttpHandler(w http.ResponseWriter, req *http.Request) error {
sinceIndex, err := strconv.ParseUint(string(content), 10, 64)
if err != nil {
return etcdErr.NewError(203, "Watch From Index")
return etcdErr.NewError(etcdErr.EcodeIndexNaN, "Watch From Index")
}
command.SinceIndex = sinceIndex
@ -264,7 +264,7 @@ func WatchHttpHandler(w http.ResponseWriter, req *http.Request) error {
}
if body, err := command.Apply(r.Server); err != nil {
return etcdErr.NewError(500, key)
return etcdErr.NewError(etcdErr.EcodeWatcherCleared, key)
} else {
w.WriteHeader(http.StatusOK)

View File

@ -1,6 +1,8 @@
package fileSystem
import (
"fmt"
etcdErr "github.com/coreos/etcd/error"
"strings"
"sync"
"time"
@ -108,7 +110,10 @@ func (eh *EventHistory) scan(prefix string, index uint64) (*Event, error) {
if start < 0 {
// TODO: Add error type
return nil, nil
return nil,
etcdErr.NewError(etcdErr.EcodeEventIndexCleared,
fmt.Sprintf("prefix:%v index:%v", prefix, index),
)
}
if start >= uint64(eh.Queue.size) {

View File

@ -74,7 +74,7 @@ func (fs *FileSystem) Create(nodePath string, value string, expireTime time.Time
_, err := fs.InternalGet(nodePath, index, term)
if err == nil { // key already exists
return nil, etcdErr.NewError(105, nodePath)
return nil, etcdErr.NewError(etcdErr.EcodeNodeExist, nodePath)
}
etcdError, _ := err.(etcdErr.Error)
@ -140,7 +140,7 @@ func (fs *FileSystem) Update(nodePath string, value string, expireTime time.Time
if n.IsDir() { // if the node is a directory, we can only update ttl
if len(value) != 0 {
return nil, etcdErr.NewError(102, nodePath)
return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath)
}
} else { // if the node is a file, we can update value and ttl
@ -180,7 +180,7 @@ func (fs *FileSystem) TestAndSet(nodePath string, prevValue string, prevIndex ui
}
if f.IsDir() { // can only test and set file
return nil, etcdErr.NewError(102, nodePath)
return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath)
}
if f.Value == prevValue || f.ModifiedIndex == prevIndex {
@ -196,7 +196,7 @@ func (fs *FileSystem) TestAndSet(nodePath string, prevValue string, prevIndex ui
}
cause := fmt.Sprintf("[%v/%v] [%v/%v]", prevValue, f.Value, prevIndex, f.ModifiedIndex)
return nil, etcdErr.NewError(101, cause)
return nil, etcdErr.NewError(etcdErr.EcodeTestFailed, cause)
}
// Delete function deletes the node at the given path.
@ -263,7 +263,7 @@ func (fs *FileSystem) InternalGet(nodePath string, index uint64, term uint64) (*
walkFunc := func(parent *Node, name string) (*Node, error) {
if !parent.IsDir() {
return nil, etcdErr.NewError(104, parent.Path)
return nil, etcdErr.NewError(etcdErr.EcodeNotDir, parent.Path)
}
child, ok := parent.Children[name]
@ -271,7 +271,7 @@ func (fs *FileSystem) InternalGet(nodePath string, index uint64, term uint64) (*
return child, nil
}
return nil, etcdErr.NewError(100, path.Join(parent.Path, name))
return nil, etcdErr.NewError(etcdErr.EcodeKeyNotFound, path.Join(parent.Path, name))
}
f, err := fs.walk(nodePath, walkFunc)

View File

@ -93,7 +93,7 @@ func (n *Node) Remove(recursive bool, callback func(path string)) error {
}
if !recursive {
return etcdErr.NewError(102, "")
return etcdErr.NewError(etcdErr.EcodeNotFile, "")
}
for _, child := range n.Children { // delete all children
@ -116,21 +116,21 @@ func (n *Node) Remove(recursive bool, callback func(path string)) error {
return nil
}
// Get function gets the value of the node.
// Read function gets the value of the node.
// If the receiver node is not a key-value pair, a "Not A File" error will be returned.
func (n *Node) Read() (string, error) {
if n.IsDir() {
return "", etcdErr.NewError(102, "")
return "", etcdErr.NewError(etcdErr.EcodeNotFile, "")
}
return n.Value, nil
}
// Set function set the value of the node to the given value.
// Write function set the value of the node to the given value.
// If the receiver node is a directory, a "Not A File" error will be returned.
func (n *Node) Write(value string, index uint64, term uint64) error {
if n.IsDir() {
return etcdErr.NewError(102, "")
return etcdErr.NewError(etcdErr.EcodeNotFile, "")
}
n.Value = value
@ -146,7 +146,7 @@ func (n *Node) List() ([]*Node, error) {
n.mu.Lock()
defer n.mu.Unlock()
if !n.IsDir() {
return nil, etcdErr.NewError(104, "")
return nil, etcdErr.NewError(etcdErr.EcodeNotDir, "")
}
nodes := make([]*Node, len(n.Children))
@ -160,12 +160,18 @@ func (n *Node) List() ([]*Node, error) {
return nodes, nil
}
// GetFile function returns the file node under the directory node.
// On success, it returns the file node
// If the node that calls this function is not a directory, it returns
// Not Directory Error
// If the node corresponding to the name string is not file, it returns
// Not File Error
func (n *Node) GetFile(name string) (*Node, error) {
n.mu.Lock()
defer n.mu.Unlock()
if !n.IsDir() {
return nil, etcdErr.NewError(104, n.Path)
return nil, etcdErr.NewError(etcdErr.EcodeNotDir, n.Path)
}
f, ok := n.Children[name]
@ -174,7 +180,7 @@ func (n *Node) GetFile(name string) (*Node, error) {
if !f.IsDir() {
return f, nil
} else {
return nil, etcdErr.NewError(102, f.Path)
return nil, etcdErr.NewError(etcdErr.EcodeNotFile, f.Path)
}
}
@ -190,11 +196,11 @@ func (n *Node) Add(child *Node) error {
n.mu.Lock()
defer n.mu.Unlock()
if n.status == removed {
return etcdErr.NewError(100, "")
return etcdErr.NewError(etcdErr.EcodeKeyNotFound, "")
}
if !n.IsDir() {
return etcdErr.NewError(104, "")
return etcdErr.NewError(etcdErr.EcodeNotDir, "")
}
_, name := path.Split(child.Path)
@ -202,7 +208,7 @@ func (n *Node) Add(child *Node) error {
_, ok := n.Children[name]
if ok {
return etcdErr.NewError(105, "")
return etcdErr.NewError(etcdErr.EcodeNodeExist, "")
}
n.Children[name] = child