mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #9 from fengjingchao/fileSystem
New error-system for Etcd with docs
This commit is contained in:
commit
7ad523270d
58
Documentation/errorcode.md
Normal file
58
Documentation/errorcode.md
Normal 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"
|
@ -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)
|
||||
|
@ -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"
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user