diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 4ef9ce3ac48982ea8172209ea17e54b6dc59b6ef..46d60b0883cf8a6df44411fc75e56f1339d1f1cb 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -26,17 +26,17 @@ }, { "ImportPath": "github.com/gorilla/websocket", - "Rev": "a3ec486e6a7a41858210b0fc5d7b5df593b3c4a3" + "Rev": "1f87405cd9755fc388e111c4003caca4a2f52fa6" }, { "ImportPath": "github.com/inconshreveable/log15/stack", - "Comment": "v2.3-42-gee210fc", - "Rev": "ee210fc98cc7756aa0cf55d8d554148828e8e658" + "Comment": "v2.3-38-g352fceb", + "Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f" }, { "ImportPath": "github.com/inconshreveable/log15/term", - "Comment": "v2.3-42-gee210fc", - "Rev": "ee210fc98cc7756aa0cf55d8d554148828e8e658" + "Comment": "v2.3-38-g352fceb", + "Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f" }, { "ImportPath": "github.com/manucorporat/sse", @@ -44,7 +44,7 @@ }, { "ImportPath": "github.com/mattn/go-colorable", - "Rev": "d67e0b7d1797975196499f79bcc322c08b9f218b" + "Rev": "043ae16291351db8465272edf465c9f388161627" }, { "ImportPath": "github.com/naoina/go-stringutil", @@ -52,7 +52,7 @@ }, { "ImportPath": "github.com/naoina/toml", - "Rev": "5667c316ee9576e9d5bca793ce4ec813a88ce7d3" + "Rev": "7b2dffbeaee47506726f29e36d19cf4ee90d361b" }, { "ImportPath": "github.com/sfreiberg/gotwilio", @@ -75,7 +75,7 @@ }, { "ImportPath": "github.com/syndtr/goleveldb/leveldb", - "Rev": "a06509502ca32565bdf74afc1e573050023f261c" + "Rev": "63c9e642efad852f49e20a6f90194cae112fd2ac" }, { "ImportPath": "github.com/syndtr/gosnappy/snappy", @@ -87,103 +87,103 @@ }, { "ImportPath": "github.com/tendermint/log15", - "Comment": "v2.3-36-gc65281b", - "Rev": "c65281bb703b7612f60558e75b07c434c06e2636" + "Comment": "v2.3-36-g6e46075", + "Rev": "6e460758f10ef42a4724b8e4a82fee59aaa0e41d" }, { "ImportPath": "github.com/tendermint/tendermint/account", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/alert", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/blockchain", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/common", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/config", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/consensus", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/db", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/events", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/logger", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/mempool", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/merkle", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/node", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/p2p", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/permission/types", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/rpc", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/state", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/types", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/vm", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tendermint/tendermint/wire", - "Comment": "0.1-26-g85d5b16", - "Rev": "85d5b16dbc610a6a27f6c3d4ece0316907babec6" + "Comment": "0.1-56-gd51741d", + "Rev": "d51741df7220f7506334ab43563bfa98f5062058" }, { "ImportPath": "github.com/tommy351/gin-cors", @@ -191,40 +191,40 @@ }, { "ImportPath": "golang.org/x/crypto/curve25519", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/crypto/nacl/box", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/crypto/nacl/secretbox", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/crypto/poly1305", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/crypto/ripemd160", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/crypto/salsa20/salsa", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "4d8f0cfeca8290cfc0091edf678a138ce669b1bb" }, { "ImportPath": "golang.org/x/net/context", - "Rev": "02a186af8b62cb007f392270669b91be5527d39c" + "Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5" }, { "ImportPath": "golang.org/x/net/netutil", - "Rev": "10576091dc82c9c109dddfb5ed77bdbbc87a9af8" + "Rev": "2cba614e8ff920c60240d2677bc019af32ee04e5" }, { "ImportPath": "gopkg.in/bluesuncorp/validator.v5", - "Comment": "v5.8", - "Rev": "c06d47f593d786142436a43334f724d819093c04" + "Comment": "v5.12", + "Rev": "d5acf1dac43705f8bfbb71d878e290e2bed3950b" }, { "ImportPath": "gopkg.in/fatih/set.v0", diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go index 0455c0db4ba18653acb86e97144098bb1c27266c..a5e946ccc5655dc498b5866c0da8cc2fb1b34f49 100644 --- a/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go +++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/context.go @@ -14,8 +14,8 @@ import ( "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/binding" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/render" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/net/context" - "github.com/manucorporat/sse" ) const ( diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go index e31411e84c7e4fce0f800dcd50145c00f73ea40b..9e9f3dda4b8ea983c96fd42c1b3ff4a302d07414 100644 --- a/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go +++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/context_test.go @@ -14,8 +14,8 @@ import ( "testing" "time" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/stretchr/testify/assert" - "github.com/manucorporat/sse" ) // Unit tests TODO diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go index 61535de2101687579494bc04eb0cb0687a802611..8af80d333d5b88142131abf6673c550775adc7f6 100644 --- a/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go +++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/middleware_test.go @@ -9,8 +9,8 @@ import ( "testing" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/manucorporat/sse" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/stretchr/testify/assert" - "github.com/manucorporat/sse" ) func TestMiddlewareGeneralCase(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go b/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go index f563ae8192bd8400f4f031cd668a7f0649d281d1..5dcf4e85a2385fdbf6c4f5f61af2485236b84b5b 100644 --- a/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go +++ b/Godeps/_workspace/src/github.com/gin-gonic/gin/mode.go @@ -9,7 +9,7 @@ import ( "os" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gin-gonic/gin/binding" - "github.com/mattn/go-colorable" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/mattn/go-colorable" ) const ENV_GIN_MODE = "GIN_MODE" diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go index 93db8ddc320df9489edf64271ef2188ab793d93e..c25d24f80421a422f130045a04754d90d261f4f9 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/client.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client.go @@ -5,11 +5,8 @@ package websocket import ( - "bytes" "crypto/tls" "errors" - "io" - "io/ioutil" "net" "net/http" "net/url" @@ -130,11 +127,6 @@ func parseURL(s string) (*url.URL, error) { u.Opaque = s[i:] } - if strings.Contains(u.Host, "@") { - // WebSocket URIs do not contain user information. - return nil, errMalformedURL - } - return &u, nil } @@ -163,8 +155,7 @@ var DefaultDialer *Dialer // // If the WebSocket handshake fails, ErrBadHandshake is returned along with a // non-nil *http.Response so that callers can handle redirects, authentication, -// etcetera. The response body may not contain the entire response and does not -// need to be closed by the application. +// etc. func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) { u, err := parseURL(urlStr) if err != nil { @@ -233,33 +224,8 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re requestHeader = h } - if len(requestHeader["Host"]) > 0 { - // This can be used to supply a Host: header which is different from - // the dial address. - u.Host = requestHeader.Get("Host") - - // Drop "Host" header - h := http.Header{} - for k, v := range requestHeader { - if k == "Host" { - continue - } - h[k] = v - } - requestHeader = h - } - conn, resp, err := NewClient(netConn, u, requestHeader, d.ReadBufferSize, d.WriteBufferSize) - if err != nil { - if err == ErrBadHandshake { - // Before closing the network connection on return from this - // function, slurp up some of the response to aid application - // debugging. - buf := make([]byte, 1024) - n, _ := io.ReadFull(resp.Body, buf) - resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n])) - } return nil, resp, err } diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go index 749ef20509ccb54418fee9f78e1d57067d1e4a08..8c608f68c4b41fbd6c920ffcc5c0f31ab482dcb4 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_server_test.go @@ -8,13 +8,11 @@ import ( "crypto/tls" "crypto/x509" "io" - "io/ioutil" "net" "net/http" "net/http/httptest" "net/url" "reflect" - "strings" "testing" "time" ) @@ -36,22 +34,22 @@ var cstDialer = Dialer{ type cstHandler struct{ *testing.T } -type cstServer struct { +type Server struct { *httptest.Server URL string } -func newServer(t *testing.T) *cstServer { - var s cstServer +func newServer(t *testing.T) *Server { + var s Server s.Server = httptest.NewServer(cstHandler{t}) - s.URL = makeWsProto(s.Server.URL) + s.URL = "ws" + s.Server.URL[len("http"):] return &s } -func newTLSServer(t *testing.T) *cstServer { - var s cstServer +func newTLSServer(t *testing.T) *Server { + var s Server s.Server = httptest.NewTLSServer(cstHandler{t}) - s.URL = makeWsProto(s.Server.URL) + s.URL = "ws" + s.Server.URL[len("http"):] return &s } @@ -99,10 +97,6 @@ func (t cstHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func makeWsProto(s string) string { - return "ws" + strings.TrimPrefix(s, "http") -} - func sendRecv(t *testing.T, ws *Conn) { const message = "Hello World!" if err := ws.SetWriteDeadline(time.Now().Add(time.Second)); err != nil { @@ -163,7 +157,6 @@ func TestDialTLS(t *testing.T) { } func xTestDialTLSBadCert(t *testing.T) { - // This test is deactivated because of noisy logging from the net/http package. s := newTLSServer(t) defer s.Close() @@ -254,70 +247,3 @@ func TestHandshake(t *testing.T) { } sendRecv(t, ws) } - -func TestRespOnBadHandshake(t *testing.T) { - const expectedStatus = http.StatusGone - const expectedBody = "This is the response body." - - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(expectedStatus) - io.WriteString(w, expectedBody) - })) - defer s.Close() - - ws, resp, err := cstDialer.Dial(makeWsProto(s.URL), nil) - if err == nil { - ws.Close() - t.Fatalf("Dial: nil") - } - - if resp == nil { - t.Fatalf("resp=nil, err=%v", err) - } - - if resp.StatusCode != expectedStatus { - t.Errorf("resp.StatusCode=%d, want %d", resp.StatusCode, expectedStatus) - } - - p, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("ReadFull(resp.Body) returned error %v", err) - } - - if string(p) != expectedBody { - t.Errorf("resp.Body=%s, want %s", p, expectedBody) - } -} - -// If the Host header is specified in `Dial()`, the server must receive it as -// the `Host:` header. -func TestHostHeader(t *testing.T) { - s := newServer(t) - defer s.Close() - - specifiedHost := make(chan string, 1) - origHandler := s.Server.Config.Handler - - // Capture the request Host header. - s.Server.Config.Handler = http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { - specifiedHost <- r.Host - origHandler.ServeHTTP(w, r) - }) - - ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Host": {"testhost"}}) - if err != nil { - t.Fatalf("Dial: %v", err) - } - defer ws.Close() - - if resp.StatusCode != http.StatusSwitchingProtocols { - t.Fatalf("resp.StatusCode = %v, want http.StatusSwitchingProtocols", resp.StatusCode) - } - - if gotHost := <-specifiedHost; gotHost != "testhost" { - t.Fatalf("gotHost = %q, want \"testhost\"", gotHost) - } - - sendRecv(t, ws) -} diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go index 07a9cb453ed7353dbbfa098a6a7020b8d82b4615..d2f2ebd798b2f1834fa2d19b6508b82eb2a77b01 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/client_test.go @@ -20,7 +20,6 @@ var parseURLTests = []struct { {"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}}, {"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}}, {"ss://example.com/a/b", nil}, - {"ws://webmaster@example.com/", nil}, } func TestParseURL(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go b/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go index e719f1ce63eee37e332a244960df9b126cd407a3..86c35e5fc06136f5a3d712dcc282640883cd08e7 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/conn.go @@ -801,7 +801,7 @@ func (c *Conn) SetPingHandler(h func(string) error) { c.handlePing = h } -// SetPongHandler sets the handler for pong messages received from the peer. +// SetPongHandler sets then handler for pong messages received from the peer. // The default pong handler does nothing. func (c *Conn) SetPongHandler(h func(string) error) { if h == nil { diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go b/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go index f52925dd11a50a9b5d01fe85c73f0e774f31fc7e..0d2bd912b3e475e4acff7291130d6b76f9a08d93 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/doc.go @@ -24,7 +24,7 @@ // ... Use conn to send and receive messages. // } // -// Call the connection's WriteMessage and ReadMessage methods to send and +// Call the connection WriteMessage and ReadMessages methods to send and // receive messages as a slice of bytes. This snippet of code shows how to echo // messages using these methods: // diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go index d96ac84dbf282d639c2619f233e124cedcb7a0d0..b7eed0da47c4cddf21b7fd9d37fc1f6e6dce0218 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/autobahn/server.go @@ -8,7 +8,7 @@ package main import ( "errors" "flag" - "github.com/gorilla/websocket" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" "io" "log" "net/http" diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go index 7cc0496c3e05d930ce8e47b218b696af3cad33d4..00b4645a47bb9ea0790e2cebf7b3bcd766d720e4 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/chat/conn.go @@ -5,7 +5,7 @@ package main import ( - "github.com/gorilla/websocket" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" "log" "net/http" "time" diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go index a2c7b85fab38b96b19c9c6145b80f95cd5262dea..37d7433ebf93f58856211f2050caf3ade9059ded 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/examples/filewatch/main.go @@ -14,7 +14,7 @@ import ( "text/template" "time" - "github.com/gorilla/websocket" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" ) const ( diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/json.go b/Godeps/_workspace/src/github.com/gorilla/websocket/json.go index 18e62f2256cbff262fe9273884b59e853c03a0bb..e0668f25e15fc65279662c32269ea677127e91d8 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/json.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/json.go @@ -6,7 +6,6 @@ package websocket import ( "encoding/json" - "io" ) // WriteJSON is deprecated, use c.WriteJSON instead. @@ -46,12 +45,5 @@ func (c *Conn) ReadJSON(v interface{}) error { if err != nil { return err } - err = json.NewDecoder(r).Decode(v) - if err == io.EOF { - // Decode returns io.EOF when the message is empty or all whitespace. - // Convert to io.ErrUnexpectedEOF so that application can distinguish - // between an error reading the JSON value and the connection closing. - err = io.ErrUnexpectedEOF - } - return err + return json.NewDecoder(r).Decode(v) } diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go b/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go index 1b7a5ec8bd08f5ec4fd101f53a2b9d51476711f9..2edb28d2f876298f0e7dce0a37db827503eb8c96 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/json_test.go @@ -6,8 +6,6 @@ package websocket import ( "bytes" - "encoding/json" - "io" "reflect" "testing" ) @@ -38,60 +36,6 @@ func TestJSON(t *testing.T) { } } -func TestPartialJsonRead(t *testing.T) { - var buf bytes.Buffer - c := fakeNetConn{&buf, &buf} - wc := newConn(c, true, 1024, 1024) - rc := newConn(c, false, 1024, 1024) - - var v struct { - A int - B string - } - v.A = 1 - v.B = "hello" - - messageCount := 0 - - // Partial JSON values. - - data, err := json.Marshal(v) - if err != nil { - t.Fatal(err) - } - for i := len(data) - 1; i >= 0; i-- { - if err := wc.WriteMessage(TextMessage, data[:i]); err != nil { - t.Fatal(err) - } - messageCount++ - } - - // Whitespace. - - if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil { - t.Fatal(err) - } - messageCount++ - - // Close. - - if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil { - t.Fatal(err) - } - - for i := 0; i < messageCount; i++ { - err := rc.ReadJSON(&v) - if err != io.ErrUnexpectedEOF { - t.Error("read", i, err) - } - } - - err = rc.ReadJSON(&v) - if err != io.EOF { - t.Error("final", err) - } -} - func TestDeprecatedJSON(t *testing.T) { var buf bytes.Buffer c := fakeNetConn{&buf, &buf} diff --git a/Godeps/_workspace/src/github.com/gorilla/websocket/server.go b/Godeps/_workspace/src/github.com/gorilla/websocket/server.go index e56a004933ad31a9846eda5f8942f11e40990ddd..349e5b997ab951174e5dfa6d9b7a27f19e662e1d 100644 --- a/Godeps/_workspace/src/github.com/gorilla/websocket/server.go +++ b/Godeps/_workspace/src/github.com/gorilla/websocket/server.go @@ -98,11 +98,11 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade } if !tokenListContainsValue(r.Header, "Connection", "upgrade") { - return u.returnError(w, r, http.StatusBadRequest, "websocket: could not find connection header with token 'upgrade'") + return u.returnError(w, r, http.StatusBadRequest, "websocket: connection header != upgrade") } if !tokenListContainsValue(r.Header, "Upgrade", "websocket") { - return u.returnError(w, r, http.StatusBadRequest, "websocket: could not find upgrade header with token 'websocket'") + return u.returnError(w, r, http.StatusBadRequest, "websocket: upgrade != websocket") } checkOrigin := u.CheckOrigin diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go index 52371b1e45ab1ac08469a56607133e18cc6716d5..64cd7d08075a7c43b884ce6076545c30a0564990 100644 --- a/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go +++ b/Godeps/_workspace/src/github.com/inconshreveable/log15/stack/stack_test.go @@ -9,7 +9,7 @@ import ( "runtime" "testing" - "github.com/inconshreveable/log15/stack" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack" ) type testType struct{} diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go index 87df7d5b0290d5297cf32cfc482e7282e3886c16..c0b201a5308991fe68a003c3684805fcb34fa556 100644 --- a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go +++ b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_notwindows.go @@ -3,7 +3,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,!appengine darwin freebsd openbsd +// +build linux,!appengine darwin freebsd package term diff --git a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go b/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go deleted file mode 100644 index 571ece3d139223c8fc9687e1ff140697d8cc39ae..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/github.com/inconshreveable/log15/term/terminal_openbsd.go +++ /dev/null @@ -1,7 +0,0 @@ -package term - -import "syscall" - -const ioctlReadTermios = syscall.TIOCGETA - -type Termios syscall.Termios diff --git a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go index 90c280bda102f6cf23c7370fdf43231d4c880eb6..9e9dbc45133be54bae72d4c567d91b5624d9bc46 100644 --- a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go +++ b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_bench_test.go @@ -3,7 +3,7 @@ package stringutil_test import ( "testing" - "github.com/naoina/go-stringutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil" ) var benchcaseForCamelCase = "the_quick_brown_fox_jumps_over_the_lazy_dog" diff --git a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go index 69c831e1238ca7e1068090be1b121b96573b05a2..89384c2c0b3c822d4868f1092507b1cc72c57862 100644 --- a/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go +++ b/Godeps/_workspace/src/github.com/naoina/go-stringutil/strings_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/naoina/go-stringutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil" ) func TestToUpperCamelCase(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode.go b/Godeps/_workspace/src/github.com/naoina/toml/decode.go index c5446fe922d5fbd2e3ca6816f6bcccd268a19e5a..4bc86a4e47eedcc4d4e7db680c5f1a308f3bd1ec 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/decode.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/decode.go @@ -2,13 +2,11 @@ package toml import ( "fmt" - "io" - "io/ioutil" "reflect" "strconv" "strings" - "github.com/naoina/toml/ast" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml/ast" ) const ( @@ -51,29 +49,6 @@ func Unmarshal(data []byte, v interface{}) error { return nil } -// A Decoder reads and decodes TOML from an input stream. -type Decoder struct { - r io.Reader -} - -// NewDecoder returns a new Decoder that reads from r. -// Note that it reads all from r before parsing it. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{ - r: r, - } -} - -// Decode parses the TOML data from its input and stores it in the value pointed to by v. -// See the documentation for Unmarshal for details about the conversion of TOML into a Go value. -func (d *Decoder) Decode(v interface{}) error { - b, err := ioutil.ReadAll(d.r) - if err != nil { - return err - } - return Unmarshal(b, v) -} - // Unmarshaler is the interface implemented by objects that can unmarshal a // TOML description of themselves. // The input can be assumed to be a valid encoding of a TOML value. diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go b/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go index b85c1c680ffc50bd35f9789434ac820140d6fb3d..94ffdfb365ba1f69ecb48a0a9a098956abe5a2b0 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/decode_bench_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/naoina/toml" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml" ) func BenchmarkUnmarshal(b *testing.B) { diff --git a/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go b/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go index 1fcae9b7abcd64a96572e7640fcd449536d415ad..17dd2e79b56155af3609167becb7975ffafe5b66 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/decode_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/naoina/toml" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml" ) const ( diff --git a/Godeps/_workspace/src/github.com/naoina/toml/encode.go b/Godeps/_workspace/src/github.com/naoina/toml/encode.go index 1932538e67b9e4f6c3db7b14e85a49a48517d09a..7465a7a2b996ea2a35f4f16e278dd91c785e5ff9 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/encode.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/encode.go @@ -2,14 +2,13 @@ package toml import ( "fmt" - "io" "reflect" "strconv" "time" "go/ast" - "github.com/naoina/go-stringutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/go-stringutil" ) const ( @@ -44,29 +43,6 @@ func Marshal(v interface{}) ([]byte, error) { return marshal(nil, "", reflect.ValueOf(v), false, false) } -// A Encoder writes TOML to an output stream. -type Encoder struct { - w io.Writer -} - -// NewEncoder returns a new Encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - w: w, - } -} - -// Encode writes the TOML of v to the stream. -// See the documentation for Marshal for details about the conversion of Go values to TOML. -func (e *Encoder) Encode(v interface{}) error { - b, err := Marshal(v) - if err != nil { - return err - } - _, err = e.w.Write(b) - return err -} - // Marshaler is the interface implemented by objects that can marshal themshelves into valid TOML. type Marshaler interface { MarshalTOML() ([]byte, error) diff --git a/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go b/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go index 17e04fd0a9d501d30e905db2f93333040f4c1c5e..3445c879e5756aab000beca1931bdcf125daac35 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/encode_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/naoina/toml" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml" ) func TestMarshal(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/naoina/toml/parse.go b/Godeps/_workspace/src/github.com/naoina/toml/parse.go index e0186662525a4ae11660a97a6c16b6c683132331..f7a3c83cdb47604ca716a0da17fd2e33b4b0ff0d 100644 --- a/Godeps/_workspace/src/github.com/naoina/toml/parse.go +++ b/Godeps/_workspace/src/github.com/naoina/toml/parse.go @@ -3,7 +3,7 @@ package toml import ( "fmt" - "github.com/naoina/toml/ast" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml/ast" ) // Parse returns an AST representation of TOML. diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go index ccf390c9cff4bd120180dd47b5b58e9a0c00b102..354ebe4fee5f2bfd622b5ec8700f5de7cc45af56 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch.go @@ -10,8 +10,8 @@ import ( "encoding/binary" "fmt" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" ) type ErrBatchCorrupted struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go index 7fc842f4fedd6f8dbd9902945d6098d4d556b6f4..e98b683cde11ad97fa83134167be6b7f74eb6b13 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/batch_test.go @@ -10,8 +10,8 @@ import ( "bytes" "testing" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" ) type tbRec struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go deleted file mode 100644 index 0dd60fd829bb83fbe497a9838e6c73e462729c6b..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench2_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// +build !go1.2 - -package leveldb - -import ( - "sync/atomic" - "testing" -) - -func BenchmarkDBReadConcurrent(b *testing.B) { - p := openDBBench(b, false) - p.populate(b.N) - p.fill() - p.gc() - defer p.close() - - b.ResetTimer() - b.SetBytes(116) - - b.RunParallel(func(pb *testing.PB) { - iter := p.newIter() - defer iter.Release() - for pb.Next() && iter.Next() { - } - }) -} - -func BenchmarkDBReadConcurrent2(b *testing.B) { - p := openDBBench(b, false) - p.populate(b.N) - p.fill() - p.gc() - defer p.close() - - b.ResetTimer() - b.SetBytes(116) - - var dir uint32 - b.RunParallel(func(pb *testing.PB) { - iter := p.newIter() - defer iter.Release() - if atomic.AddUint32(&dir, 1)%2 == 0 { - for pb.Next() && iter.Next() { - } - } else { - if pb.Next() && iter.Last() { - for pb.Next() && iter.Prev() { - } - } - } - }) -} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go index 91b426709d59a8fb0860cec31ba601f9daca3605..621e52db283da81202a19a0f464ae3ab0b0a0fb4 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/bench_test.go @@ -15,9 +15,9 @@ import ( "runtime" "testing" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" ) func randomString(r *rand.Rand, n int) []byte { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go deleted file mode 100644 index 175e2220323c8428957d1cad24aa9e8604f8a23e..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/bench2_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// +build !go1.2 - -package cache - -import ( - "math/rand" - "testing" -) - -func BenchmarkLRUCache(b *testing.B) { - c := NewCache(NewLRU(10000)) - - b.SetParallelism(10) - b.RunParallel(func(pb *testing.PB) { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - - for pb.Next() { - key := uint64(r.Intn(1000000)) - c.Get(0, key, func() (int, Value) { - return 1, key - }).Release() - } - }) -} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go index c9670de5de6f70f4ba905df39776f67a42ff32d1..9ae499311026ce392b16b641577337f946754ef0 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache.go @@ -12,7 +12,7 @@ import ( "sync/atomic" "unsafe" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // Cacher provides interface to implements a caching functionality. diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go index c2a50156f0472c99d3b60022781435fc18cf8947..5575583dcef4c151badda08a1d9009888884157e 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache/cache_test.go @@ -552,3 +552,19 @@ func TestLRUCache_Close(t *testing.T) { t.Errorf("delFunc isn't called 1 times: got=%d", delFuncCalled) } } + +func BenchmarkLRUCache(b *testing.B) { + c := NewCache(NewLRU(10000)) + + b.SetParallelism(10) + b.RunParallel(func(pb *testing.PB) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + for pb.Next() { + key := uint64(r.Intn(1000000)) + c.Get(0, key, func() (int, Value) { + return 1, key + }).Release() + } + }) +} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go index d33d5e9c78fcf566114dce757ffe4ea6e0f0ba46..6e57fab707a08b08c1bd088dac3088c7bd6e48a9 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer.go @@ -6,7 +6,7 @@ package leveldb -import "github.com/syndtr/goleveldb/leveldb/comparer" +import "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" type iComparer struct { ucmp comparer.Comparer diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go index a351874ed4351f6d0abf67719bf7698d4228216a..f1ef0743e955f114cea9018d051e45d898787464 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/corrupt_test.go @@ -9,9 +9,9 @@ package leveldb import ( "bytes" "fmt" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" "io" "math/rand" "testing" diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go index def86bc1aa8240e30aba67c204f0e0c311a48b37..03c6a06867327b8ab74a9c91acc6bc0200efb05b 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db.go @@ -17,14 +17,14 @@ import ( "sync/atomic" "time" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/journal" - "github.com/syndtr/goleveldb/leveldb/memdb" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/table" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // DB is a LevelDB database. @@ -63,14 +63,13 @@ type DB struct { journalAckC chan error // Compaction. - tcompCmdC chan cCmd - tcompPauseC chan chan<- struct{} - mcompCmdC chan cCmd - compErrC chan error - compPerErrC chan error - compErrSetC chan error - compWriteLocking bool - compStats []cStats + tcompCmdC chan cCmd + tcompPauseC chan chan<- struct{} + mcompCmdC chan cCmd + compErrC chan error + compPerErrC chan error + compErrSetC chan error + compStats []cStats // Close. closeW sync.WaitGroup @@ -109,44 +108,28 @@ func openDB(s *session) (*DB, error) { closeC: make(chan struct{}), } - // Read-only mode. - readOnly := s.o.GetReadOnly() - - if readOnly { - // Recover journals (read-only mode). - if err := db.recoverJournalRO(); err != nil { - return nil, err - } - } else { - // Recover journals. - if err := db.recoverJournal(); err != nil { - return nil, err - } + if err := db.recoverJournal(); err != nil { + return nil, err + } - // Remove any obsolete files. - if err := db.checkAndCleanFiles(); err != nil { - // Close journal. - if db.journal != nil { - db.journal.Close() - db.journalWriter.Close() - } - return nil, err + // Remove any obsolete files. + if err := db.checkAndCleanFiles(); err != nil { + // Close journal. + if db.journal != nil { + db.journal.Close() + db.journalWriter.Close() } - + return nil, err } // Doesn't need to be included in the wait group. go db.compactionError() go db.mpoolDrain() - if readOnly { - db.SetReadOnly() - } else { - db.closeW.Add(3) - go db.tCompaction() - go db.mCompaction() - go db.jWriter() - } + db.closeW.Add(3) + go db.tCompaction() + go db.mCompaction() + go db.jWriter() s.logf("db@open done T·%v", time.Since(start)) @@ -292,7 +275,7 @@ func recoverTable(s *session, o *opt.Options) error { // We will drop corrupted table. strict = o.GetStrict(opt.StrictRecovery) - rec = &sessionRecord{} + rec = &sessionRecord{numLevel: o.GetNumLevel()} bpool = util.NewBufferPool(o.GetBlockSize() + 5) ) buildTable := func(iter iterator.Iterator) (tmp storage.File, size int64, err error) { @@ -364,14 +347,12 @@ func recoverTable(s *session, o *opt.Options) error { return err } iter := tr.NewIterator(nil, nil) - if itererr, ok := iter.(iterator.ErrorCallbackSetter); ok { - itererr.SetErrorCallback(func(err error) { - if errors.IsCorrupted(err) { - s.logf("table@recovery block corruption @%d %q", file.Num(), err) - tcorruptedBlock++ - } - }) - } + iter.(iterator.ErrorCallbackSetter).SetErrorCallback(func(err error) { + if errors.IsCorrupted(err) { + s.logf("table@recovery block corruption @%d %q", file.Num(), err) + tcorruptedBlock++ + } + }) // Scan the table. for iter.Next() { @@ -467,136 +448,132 @@ func recoverTable(s *session, o *opt.Options) error { } func (db *DB) recoverJournal() error { - // Get all journals and sort it by file number. - allJournalFiles, err := db.s.getFiles(storage.TypeJournal) + // Get all tables and sort it by file number. + journalFiles_, err := db.s.getFiles(storage.TypeJournal) if err != nil { return err } - files(allJournalFiles).sort() + journalFiles := files(journalFiles_) + journalFiles.sort() - // Journals that will be recovered. - var recJournalFiles []storage.File - for _, jf := range allJournalFiles { - if jf.Num() >= db.s.stJournalNum || jf.Num() == db.s.stPrevJournalNum { - recJournalFiles = append(recJournalFiles, jf) + // Discard older journal. + prev := -1 + for i, file := range journalFiles { + if file.Num() >= db.s.stJournalNum { + if prev >= 0 { + i-- + journalFiles[i] = journalFiles[prev] + } + journalFiles = journalFiles[i:] + break + } else if file.Num() == db.s.stPrevJournalNum { + prev = i + } + } + + var jr *journal.Reader + var of storage.File + var mem *memdb.DB + batch := new(Batch) + cm := newCMem(db.s) + buf := new(util.Buffer) + // Options. + strict := db.s.o.GetStrict(opt.StrictJournal) + checksum := db.s.o.GetStrict(opt.StrictJournalChecksum) + writeBuffer := db.s.o.GetWriteBuffer() + recoverJournal := func(file storage.File) error { + db.logf("journal@recovery recovering @%d", file.Num()) + reader, err := file.Open() + if err != nil { + return err } - } + defer reader.Close() - var ( - of storage.File // Obsolete file. - rec = &sessionRecord{} - ) - - // Recover journals. - if len(recJournalFiles) > 0 { - db.logf("journal@recovery F·%d", len(recJournalFiles)) - - // Mark file number as used. - db.s.markFileNum(recJournalFiles[len(recJournalFiles)-1].Num()) - - var ( - // Options. - strict = db.s.o.GetStrict(opt.StrictJournal) - checksum = db.s.o.GetStrict(opt.StrictJournalChecksum) - writeBuffer = db.s.o.GetWriteBuffer() - - jr *journal.Reader - mdb = memdb.New(db.s.icmp, writeBuffer) - buf = &util.Buffer{} - batch = &Batch{} - ) - - for _, jf := range recJournalFiles { - db.logf("journal@recovery recovering @%d", jf.Num()) + // Create/reset journal reader instance. + if jr == nil { + jr = journal.NewReader(reader, dropper{db.s, file}, strict, checksum) + } else { + jr.Reset(reader, dropper{db.s, file}, strict, checksum) + } - fr, err := jf.Open() - if err != nil { + // Flush memdb and remove obsolete journal file. + if of != nil { + if mem.Len() > 0 { + if err := cm.flush(mem, 0); err != nil { + return err + } + } + if err := cm.commit(file.Num(), db.seq); err != nil { return err } + cm.reset() + of.Remove() + of = nil + } - // Create or reset journal reader instance. - if jr == nil { - jr = journal.NewReader(fr, dropper{db.s, jf}, strict, checksum) - } else { - jr.Reset(fr, dropper{db.s, jf}, strict, checksum) + // Replay journal to memdb. + mem.Reset() + for { + r, err := jr.Next() + if err != nil { + if err == io.EOF { + break + } + return errors.SetFile(err, file) } - // Flush memdb and remove obsolete journal file. - if of != nil { - if mdb.Len() > 0 { - if _, err := db.s.flushMemdb(rec, mdb, -1); err != nil { - fr.Close() - return err - } + buf.Reset() + if _, err := buf.ReadFrom(r); err != nil { + if err == io.ErrUnexpectedEOF { + // This is error returned due to corruption, with strict == false. + continue + } else { + return errors.SetFile(err, file) } - - rec.setJournalNum(jf.Num()) - rec.setSeqNum(db.seq) - if err := db.s.commit(rec); err != nil { - fr.Close() - return err + } + if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mem); err != nil { + if strict || !errors.IsCorrupted(err) { + return errors.SetFile(err, file) + } else { + db.s.logf("journal error: %v (skipped)", err) + // We won't apply sequence number as it might be corrupted. + continue } - rec.resetAddedTables() - - of.Remove() - of = nil } - // Replay journal to memdb. - mdb.Reset() - for { - r, err := jr.Next() - if err != nil { - if err == io.EOF { - break - } + // Save sequence number. + db.seq = batch.seq + uint64(batch.Len()) - fr.Close() - return errors.SetFile(err, jf) + // Flush it if large enough. + if mem.Size() >= writeBuffer { + if err := cm.flush(mem, 0); err != nil { + return err } + mem.Reset() + } + } - buf.Reset() - if _, err := buf.ReadFrom(r); err != nil { - if err == io.ErrUnexpectedEOF { - // This is error returned due to corruption, with strict == false. - continue - } - - fr.Close() - return errors.SetFile(err, jf) - } - if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil { - if !strict && errors.IsCorrupted(err) { - db.s.logf("journal error: %v (skipped)", err) - // We won't apply sequence number as it might be corrupted. - continue - } - - fr.Close() - return errors.SetFile(err, jf) - } + of = file + return nil + } - // Save sequence number. - db.seq = batch.seq + uint64(batch.Len()) + // Recover all journals. + if len(journalFiles) > 0 { + db.logf("journal@recovery F·%d", len(journalFiles)) - // Flush it if large enough. - if mdb.Size() >= writeBuffer { - if _, err := db.s.flushMemdb(rec, mdb, 0); err != nil { - fr.Close() - return err - } + // Mark file number as used. + db.s.markFileNum(journalFiles[len(journalFiles)-1].Num()) - mdb.Reset() - } + mem = memdb.New(db.s.icmp, writeBuffer) + for _, file := range journalFiles { + if err := recoverJournal(file); err != nil { + return err } - - fr.Close() - of = jf } - // Flush the last memdb. - if mdb.Len() > 0 { - if _, err := db.s.flushMemdb(rec, mdb, 0); err != nil { + // Flush the last journal. + if mem.Len() > 0 { + if err := cm.flush(mem, 0); err != nil { return err } } @@ -608,10 +585,8 @@ func (db *DB) recoverJournal() error { } // Commit. - rec.setJournalNum(db.journalFile.Num()) - rec.setSeqNum(db.seq) - if err := db.s.commit(rec); err != nil { - // Close journal on error. + if err := cm.commit(db.journalFile.Num(), db.seq); err != nil { + // Close journal. if db.journal != nil { db.journal.Close() db.journalWriter.Close() @@ -627,103 +602,6 @@ func (db *DB) recoverJournal() error { return nil } -func (db *DB) recoverJournalRO() error { - // Get all journals and sort it by file number. - allJournalFiles, err := db.s.getFiles(storage.TypeJournal) - if err != nil { - return err - } - files(allJournalFiles).sort() - - // Journals that will be recovered. - var recJournalFiles []storage.File - for _, jf := range allJournalFiles { - if jf.Num() >= db.s.stJournalNum || jf.Num() == db.s.stPrevJournalNum { - recJournalFiles = append(recJournalFiles, jf) - } - } - - var ( - // Options. - strict = db.s.o.GetStrict(opt.StrictJournal) - checksum = db.s.o.GetStrict(opt.StrictJournalChecksum) - writeBuffer = db.s.o.GetWriteBuffer() - - mdb = memdb.New(db.s.icmp, writeBuffer) - ) - - // Recover journals. - if len(recJournalFiles) > 0 { - db.logf("journal@recovery RO·Mode F·%d", len(recJournalFiles)) - - var ( - jr *journal.Reader - buf = &util.Buffer{} - batch = &Batch{} - ) - - for _, jf := range recJournalFiles { - db.logf("journal@recovery recovering @%d", jf.Num()) - - fr, err := jf.Open() - if err != nil { - return err - } - - // Create or reset journal reader instance. - if jr == nil { - jr = journal.NewReader(fr, dropper{db.s, jf}, strict, checksum) - } else { - jr.Reset(fr, dropper{db.s, jf}, strict, checksum) - } - - // Replay journal to memdb. - for { - r, err := jr.Next() - if err != nil { - if err == io.EOF { - break - } - - fr.Close() - return errors.SetFile(err, jf) - } - - buf.Reset() - if _, err := buf.ReadFrom(r); err != nil { - if err == io.ErrUnexpectedEOF { - // This is error returned due to corruption, with strict == false. - continue - } - - fr.Close() - return errors.SetFile(err, jf) - } - if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil { - if !strict && errors.IsCorrupted(err) { - db.s.logf("journal error: %v (skipped)", err) - // We won't apply sequence number as it might be corrupted. - continue - } - - fr.Close() - return errors.SetFile(err, jf) - } - - // Save sequence number. - db.seq = batch.seq + uint64(batch.Len()) - } - - fr.Close() - } - } - - // Set memDB. - db.mem = &memDB{db: db, DB: mdb, ref: 1} - - return nil -} - func (db *DB) get(key []byte, seq uint64, ro *opt.ReadOptions) (value []byte, err error) { ikey := newIkey(key, seq, ktSeek) @@ -734,7 +612,7 @@ func (db *DB) get(key []byte, seq uint64, ro *opt.ReadOptions) (value []byte, er } defer m.decref() - mk, mv, me := m.Find(ikey) + mk, mv, me := m.mdb.Find(ikey) if me == nil { ukey, _, kt, kerr := parseIkey(mk) if kerr != nil { @@ -772,7 +650,7 @@ func (db *DB) has(key []byte, seq uint64, ro *opt.ReadOptions) (ret bool, err er } defer m.decref() - mk, _, me := m.Find(ikey) + mk, _, me := m.mdb.Find(ikey) if me == nil { ukey, _, kt, kerr := parseIkey(mk) if kerr != nil { @@ -904,7 +782,7 @@ func (db *DB) GetProperty(name string) (value string, err error) { const prefix = "leveldb." if !strings.HasPrefix(name, prefix) { - return "", ErrNotFound + return "", errors.New("leveldb: GetProperty: unknown property: " + name) } p := name[len(prefix):] @@ -918,7 +796,7 @@ func (db *DB) GetProperty(name string) (value string, err error) { var rest string n, _ := fmt.Sscanf(p[len(numFilesPrefix):], "%d%s", &level, &rest) if n != 1 || int(level) >= db.s.o.GetNumLevel() { - err = ErrNotFound + err = errors.New("leveldb: GetProperty: invalid property: " + name) } else { value = fmt.Sprint(v.tLen(int(level))) } @@ -957,7 +835,7 @@ func (db *DB) GetProperty(name string) (value string, err error) { case p == "aliveiters": value = fmt.Sprintf("%d", atomic.LoadInt32(&db.aliveIters)) default: - err = ErrNotFound + err = errors.New("leveldb: GetProperty: unknown property: " + name) } return @@ -1020,9 +898,6 @@ func (db *DB) Close() error { var err error select { case err = <-db.compErrC: - if err == ErrReadOnly { - err = nil - } default: } diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go index 26003106ead5ad7436db63da0f49dbfcd1c2cdf1..2f14a588fec1b697d89073853761c3184047ea88 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_compaction.go @@ -10,8 +10,9 @@ import ( "sync" "time" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" ) var ( @@ -61,8 +62,58 @@ func (p *cStatsStaging) stopTimer() { } } +type cMem struct { + s *session + level int + rec *sessionRecord +} + +func newCMem(s *session) *cMem { + return &cMem{s: s, rec: &sessionRecord{numLevel: s.o.GetNumLevel()}} +} + +func (c *cMem) flush(mem *memdb.DB, level int) error { + s := c.s + + // Write memdb to table. + iter := mem.NewIterator(nil) + defer iter.Release() + t, n, err := s.tops.createFrom(iter) + if err != nil { + return err + } + + // Pick level. + if level < 0 { + v := s.version() + level = v.pickLevel(t.imin.ukey(), t.imax.ukey()) + v.release() + } + c.rec.addTableFile(level, t) + + s.logf("mem@flush created L%d@%d N·%d S·%s %q:%q", level, t.file.Num(), n, shortenb(int(t.size)), t.imin, t.imax) + + c.level = level + return nil +} + +func (c *cMem) reset() { + c.rec = &sessionRecord{numLevel: c.s.o.GetNumLevel()} +} + +func (c *cMem) commit(journal, seq uint64) error { + c.rec.setJournalNum(journal) + c.rec.setSeqNum(seq) + + // Commit changes. + return c.s.commit(c.rec) +} + func (db *DB) compactionError() { - var err error + var ( + err error + wlocked bool + ) noerr: // No error. for { @@ -70,7 +121,7 @@ noerr: case err = <-db.compErrSetC: switch { case err == nil: - case err == ErrReadOnly, errors.IsCorrupted(err): + case errors.IsCorrupted(err): goto hasperr default: goto haserr @@ -88,7 +139,7 @@ haserr: switch { case err == nil: goto noerr - case err == ErrReadOnly, errors.IsCorrupted(err): + case errors.IsCorrupted(err): goto hasperr default: } @@ -104,9 +155,9 @@ hasperr: case db.compPerErrC <- err: case db.writeLockC <- struct{}{}: // Hold write lock, so that write won't pass-through. - db.compWriteLocking = true + wlocked = true case _, _ = <-db.closeC: - if db.compWriteLocking { + if wlocked { // We should release the lock or Close will hang. <-db.writeLockC } @@ -236,18 +287,21 @@ func (db *DB) compactionExitTransact() { } func (db *DB) memCompaction() { - mdb := db.getFrozenMem() - if mdb == nil { + mem := db.getFrozenMem() + if mem == nil { return } - defer mdb.decref() + defer mem.decref() + + c := newCMem(db.s) + stats := new(cStatsStaging) - db.logf("memdb@flush N·%d S·%s", mdb.Len(), shortenb(mdb.Size())) + db.logf("mem@flush N·%d S·%s", mem.mdb.Len(), shortenb(mem.mdb.Size())) // Don't compact empty memdb. - if mdb.Len() == 0 { - db.logf("memdb@flush skipping") - // drop frozen memdb + if mem.mdb.Len() == 0 { + db.logf("mem@flush skipping") + // drop frozen mem db.dropFrozenMem() return } @@ -263,20 +317,13 @@ func (db *DB) memCompaction() { return } - var ( - rec = &sessionRecord{} - stats = &cStatsStaging{} - flushLevel int - ) - - db.compactionTransactFunc("memdb@flush", func(cnt *compactionTransactCounter) (err error) { + db.compactionTransactFunc("mem@flush", func(cnt *compactionTransactCounter) (err error) { stats.startTimer() - flushLevel, err = db.s.flushMemdb(rec, mdb.DB, -1) - stats.stopTimer() - return + defer stats.stopTimer() + return c.flush(mem.mdb, -1) }, func() error { - for _, r := range rec.addedTables { - db.logf("memdb@flush revert @%d", r.num) + for _, r := range c.rec.addedTables { + db.logf("mem@flush revert @%d", r.num) f := db.s.getTableFile(r.num) if err := f.Remove(); err != nil { return err @@ -285,23 +332,20 @@ func (db *DB) memCompaction() { return nil }) - db.compactionTransactFunc("memdb@commit", func(cnt *compactionTransactCounter) (err error) { + db.compactionTransactFunc("mem@commit", func(cnt *compactionTransactCounter) (err error) { stats.startTimer() - rec.setJournalNum(db.journalFile.Num()) - rec.setSeqNum(db.frozenSeq) - err = db.s.commit(rec) - stats.stopTimer() - return + defer stats.stopTimer() + return c.commit(db.journalFile.Num(), db.frozenSeq) }, nil) - db.logf("memdb@flush committed F·%d T·%v", len(rec.addedTables), stats.duration) + db.logf("mem@flush committed F·%d T·%v", len(c.rec.addedTables), stats.duration) - for _, r := range rec.addedTables { + for _, r := range c.rec.addedTables { stats.write += r.size } - db.compStats[flushLevel].add(stats) + db.compStats[c.level].add(stats) - // Drop frozen memdb. + // Drop frozen mem. db.dropFrozenMem() // Resume table compaction. @@ -513,7 +557,7 @@ func (b *tableCompactionBuilder) revert() error { func (db *DB) tableCompaction(c *compaction, noTrivial bool) { defer c.release() - rec := &sessionRecord{} + rec := &sessionRecord{numLevel: db.s.o.GetNumLevel()} rec.addCompPtr(c.level, c.imax) if !noTrivial && c.trivial() { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go index 656ae98567f38ecae293500a2649021ec9fd525f..626369271785310282175947f10a2b473a47c5d4 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_iter.go @@ -8,14 +8,13 @@ package leveldb import ( "errors" - "math/rand" "runtime" "sync" "sync/atomic" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( @@ -40,11 +39,11 @@ func (db *DB) newRawIterator(slice *util.Range, ro *opt.ReadOptions) iterator.It ti := v.getIterators(slice, ro) n := len(ti) + 2 i := make([]iterator.Iterator, 0, n) - emi := em.NewIterator(slice) + emi := em.mdb.NewIterator(slice) emi.SetReleaser(&memdbReleaser{m: em}) i = append(i, emi) if fm != nil { - fmi := fm.NewIterator(slice) + fmi := fm.mdb.NewIterator(slice) fmi.SetReleaser(&memdbReleaser{m: fm}) i = append(i, fmi) } @@ -81,10 +80,6 @@ func (db *DB) newIterator(seq uint64, slice *util.Range, ro *opt.ReadOptions) *d return iter } -func (db *DB) iterSamplingRate() int { - return rand.Intn(2 * db.s.o.GetIteratorSamplingRate()) -} - type dir int const ( @@ -103,21 +98,11 @@ type dbIter struct { seq uint64 strict bool - smaplingGap int - dir dir - key []byte - value []byte - err error - releaser util.Releaser -} - -func (i *dbIter) sampleSeek() { - ikey := i.iter.Key() - i.smaplingGap -= len(ikey) + len(i.iter.Value()) - for i.smaplingGap < 0 { - i.smaplingGap += i.db.iterSamplingRate() - i.db.sampleSeek(ikey) - } + dir dir + key []byte + value []byte + err error + releaser util.Releaser } func (i *dbIter) setErr(err error) { @@ -190,7 +175,6 @@ func (i *dbIter) Seek(key []byte) bool { func (i *dbIter) next() bool { for { if ukey, seq, kt, kerr := parseIkey(i.iter.Key()); kerr == nil { - i.sampleSeek() if seq <= i.seq { switch kt { case ktDel: @@ -241,7 +225,6 @@ func (i *dbIter) prev() bool { if i.iter.Valid() { for { if ukey, seq, kt, kerr := parseIkey(i.iter.Key()); kerr == nil { - i.sampleSeek() if seq <= i.seq { if !del && i.icmp.uCompare(ukey, i.key) < 0 { return true @@ -283,7 +266,6 @@ func (i *dbIter) Prev() bool { case dirForward: for i.iter.Prev() { if ukey, _, _, kerr := parseIkey(i.iter.Key()); kerr == nil { - i.sampleSeek() if i.icmp.uCompare(ukey, i.key) < 0 { goto cont } diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go index 0372848ff1e4f62ececce67d9abe04d8e08121bd..4af7403317888b03177c989614003cff84009589 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_snapshot.go @@ -13,9 +13,9 @@ import ( "sync" "sync/atomic" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type snapshotElement struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go index 24671dd39ede09ec35cc01a5f0e9bdec926a11bc..ddad4d4a9bcb7b4631c37910443719bd8e033ada 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_state.go @@ -10,13 +10,13 @@ import ( "sync/atomic" "time" - "github.com/syndtr/goleveldb/leveldb/journal" - "github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" ) type memDB struct { - db *DB - *memdb.DB + db *DB + mdb *memdb.DB ref int32 } @@ -27,12 +27,12 @@ func (m *memDB) incref() { func (m *memDB) decref() { if ref := atomic.AddInt32(&m.ref, -1); ref == 0 { // Only put back memdb with std capacity. - if m.Capacity() == m.db.s.o.GetWriteBuffer() { - m.Reset() - m.db.mpoolPut(m.DB) + if m.mdb.Capacity() == m.db.s.o.GetWriteBuffer() { + m.mdb.Reset() + m.db.mpoolPut(m.mdb) } m.db = nil - m.DB = nil + m.mdb = nil } else if ref < 0 { panic("negative memdb ref") } @@ -48,15 +48,6 @@ func (db *DB) addSeq(delta uint64) { atomic.AddUint64(&db.seq, delta) } -func (db *DB) sampleSeek(ikey iKey) { - v := db.s.version() - if v.sampleSeek(ikey) { - // Trigger table compaction. - db.compSendTrigger(db.tcompCmdC) - } - v.release() -} - func (db *DB) mpoolPut(mem *memdb.DB) { defer func() { recover() @@ -126,7 +117,7 @@ func (db *DB) newMem(n int) (mem *memDB, err error) { } mem = &memDB{ db: db, - DB: mdb, + mdb: mdb, ref: 2, } db.mem = mem diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go index 9d91ebf1a80e78e399b745edeb8e61bbaa3bf0c8..b2e0fb36f2eca1271313ef1a5c3df75f0c2f9ca3 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_test.go @@ -23,13 +23,13 @@ import ( "time" "unsafe" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func tkey(i int) []byte { @@ -405,21 +405,19 @@ func (h *dbHarness) compactRange(min, max string) { t.Log("DB range compaction done") } -func (h *dbHarness) sizeOf(start, limit string) uint64 { - sz, err := h.db.SizeOf([]util.Range{ +func (h *dbHarness) sizeAssert(start, limit string, low, hi uint64) { + t := h.t + db := h.db + + s, err := db.SizeOf([]util.Range{ {[]byte(start), []byte(limit)}, }) if err != nil { - h.t.Error("SizeOf: got error: ", err) + t.Error("SizeOf: got error: ", err) } - return sz.Sum() -} - -func (h *dbHarness) sizeAssert(start, limit string, low, hi uint64) { - sz := h.sizeOf(start, limit) - if sz < low || sz > hi { - h.t.Errorf("sizeOf %q to %q not in range, want %d - %d, got %d", - shorten(start), shorten(limit), low, hi, sz) + if s.Sum() < low || s.Sum() > hi { + t.Errorf("sizeof %q to %q not in range, want %d - %d, got %d", + shorten(start), shorten(limit), low, hi, s.Sum()) } } @@ -2445,7 +2443,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) { if err != nil { t.Fatal(err) } - rec := &sessionRecord{} + rec := &sessionRecord{numLevel: s.o.GetNumLevel()} rec.addTableFile(i, tf) if err := s.commit(rec); err != nil { t.Fatal(err) @@ -2455,7 +2453,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) { // Build grandparent. v := s.version() c := newCompaction(s, v, 1, append(tFiles{}, v.tables[1]...)) - rec := &sessionRecord{} + rec := &sessionRecord{numLevel: s.o.GetNumLevel()} b := &tableCompactionBuilder{ s: s, c: c, @@ -2479,7 +2477,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) { // Build level-1. v = s.version() c = newCompaction(s, v, 0, append(tFiles{}, v.tables[0]...)) - rec = &sessionRecord{} + rec = &sessionRecord{numLevel: s.o.GetNumLevel()} b = &tableCompactionBuilder{ s: s, c: c, @@ -2523,7 +2521,7 @@ func TestDB_TableCompactionBuilder(t *testing.T) { // Compaction with transient error. v = s.version() c = newCompaction(s, v, 1, append(tFiles{}, v.tables[1]...)) - rec = &sessionRecord{} + rec = &sessionRecord{numLevel: s.o.GetNumLevel()} b = &tableCompactionBuilder{ s: s, c: c, @@ -2579,123 +2577,3 @@ func TestDB_TableCompactionBuilder(t *testing.T) { } v.release() } - -func testDB_IterTriggeredCompaction(t *testing.T, limitDiv int) { - const ( - vSize = 200 * opt.KiB - tSize = 100 * opt.MiB - mIter = 100 - n = tSize / vSize - ) - - h := newDbHarnessWopt(t, &opt.Options{ - Compression: opt.NoCompression, - DisableBlockCache: true, - }) - defer h.close() - - key := func(x int) string { - return fmt.Sprintf("v%06d", x) - } - - // Fill. - value := strings.Repeat("x", vSize) - for i := 0; i < n; i++ { - h.put(key(i), value) - } - h.compactMem() - - // Delete all. - for i := 0; i < n; i++ { - h.delete(key(i)) - } - h.compactMem() - - var ( - limit = n / limitDiv - - startKey = key(0) - limitKey = key(limit) - maxKey = key(n) - slice = &util.Range{Limit: []byte(limitKey)} - - initialSize0 = h.sizeOf(startKey, limitKey) - initialSize1 = h.sizeOf(limitKey, maxKey) - ) - - t.Logf("inital size %s [rest %s]", shortenb(int(initialSize0)), shortenb(int(initialSize1))) - - for r := 0; true; r++ { - if r >= mIter { - t.Fatal("taking too long to compact") - } - - // Iterates. - iter := h.db.NewIterator(slice, h.ro) - for iter.Next() { - } - if err := iter.Error(); err != nil { - t.Fatalf("Iter err: %v", err) - } - iter.Release() - - // Wait compaction. - h.waitCompaction() - - // Check size. - size0 := h.sizeOf(startKey, limitKey) - size1 := h.sizeOf(limitKey, maxKey) - t.Logf("#%03d size %s [rest %s]", r, shortenb(int(size0)), shortenb(int(size1))) - if size0 < initialSize0/10 { - break - } - } - - if initialSize1 > 0 { - h.sizeAssert(limitKey, maxKey, initialSize1/4-opt.MiB, initialSize1+opt.MiB) - } -} - -func TestDB_IterTriggeredCompaction(t *testing.T) { - testDB_IterTriggeredCompaction(t, 1) -} - -func TestDB_IterTriggeredCompactionHalf(t *testing.T) { - testDB_IterTriggeredCompaction(t, 2) -} - -func TestDB_ReadOnly(t *testing.T) { - h := newDbHarness(t) - defer h.close() - - h.put("foo", "v1") - h.put("bar", "v2") - h.compactMem() - - h.put("xfoo", "v1") - h.put("xbar", "v2") - - t.Log("Trigger read-only") - if err := h.db.SetReadOnly(); err != nil { - h.close() - t.Fatalf("SetReadOnly error: %v", err) - } - - h.stor.SetEmuErr(storage.TypeAll, tsOpCreate, tsOpReplace, tsOpRemove, tsOpWrite, tsOpWrite, tsOpSync) - - ro := func(key, value, wantValue string) { - if err := h.db.Put([]byte(key), []byte(value), h.wo); err != ErrReadOnly { - t.Fatalf("unexpected error: %v", err) - } - h.getVal(key, wantValue) - } - - ro("foo", "vx", "v1") - - h.o.ReadOnly = true - h.reopenDB() - - ro("foo", "vx", "v1") - ro("bar", "vx", "v2") - h.assertNumKeys(4) -} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go index a8a2bdf72e173d592b4eba894a2996595cb1af12..0cd4a99ec78d217d0e84d14e5f1eafece9903ade 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_util.go @@ -7,11 +7,11 @@ package leveldb import ( - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // Reader is the interface that wraps basic Get and NewIterator methods. diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go index 176ee893f10c6896ceb5e2cabaa2f38426c7c1c8..0f7ba29892ba34ba2badbd5d84d876a1e4ef9a74 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/db_write.go @@ -9,9 +9,9 @@ package leveldb import ( "time" - "github.com/syndtr/goleveldb/leveldb/memdb" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func (db *DB) writeJournal(b *Batch) error { @@ -63,24 +63,24 @@ func (db *DB) rotateMem(n int) (mem *memDB, err error) { return } -func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) { +func (db *DB) flush(n int) (mem *memDB, nn int, err error) { delayed := false flush := func() (retry bool) { v := db.s.version() defer v.release() - mdb = db.getEffectiveMem() + mem = db.getEffectiveMem() defer func() { if retry { - mdb.decref() - mdb = nil + mem.decref() + mem = nil } }() - mdbFree = mdb.Free() + nn = mem.mdb.Free() switch { case v.tLen(0) >= db.s.o.GetWriteL0SlowdownTrigger() && !delayed: delayed = true time.Sleep(time.Millisecond) - case mdbFree >= n: + case nn >= n: return false case v.tLen(0) >= db.s.o.GetWriteL0PauseTrigger(): delayed = true @@ -90,15 +90,15 @@ func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) { } default: // Allow memdb to grow if it has no entry. - if mdb.Len() == 0 { - mdbFree = n + if mem.mdb.Len() == 0 { + nn = n } else { - mdb.decref() - mdb, err = db.rotateMem(n) + mem.decref() + mem, err = db.rotateMem(n) if err == nil { - mdbFree = mdb.Free() + nn = mem.mdb.Free() } else { - mdbFree = 0 + nn = 0 } } return false @@ -157,18 +157,18 @@ func (db *DB) Write(b *Batch, wo *opt.WriteOptions) (err error) { } }() - mdb, mdbFree, err := db.flush(b.size()) + mem, memFree, err := db.flush(b.size()) if err != nil { return } - defer mdb.decref() + defer mem.decref() // Calculate maximum size of the batch. m := 1 << 20 if x := b.size(); x <= 128<<10 { m = x + (128 << 10) } - m = minInt(m, mdbFree) + m = minInt(m, memFree) // Merge with other batch. drain: @@ -197,7 +197,7 @@ drain: select { case db.journalC <- b: // Write into memdb - if berr := b.memReplay(mdb.DB); berr != nil { + if berr := b.memReplay(mem.mdb); berr != nil { panic(berr) } case err = <-db.compPerErrC: @@ -211,7 +211,7 @@ drain: case err = <-db.journalAckC: if err != nil { // Revert memdb if error detected - if berr := b.revertMemReplay(mdb.DB); berr != nil { + if berr := b.revertMemReplay(mem.mdb); berr != nil { panic(berr) } return @@ -225,7 +225,7 @@ drain: if err != nil { return } - if berr := b.memReplay(mdb.DB); berr != nil { + if berr := b.memReplay(mem.mdb); berr != nil { panic(berr) } } @@ -233,7 +233,7 @@ drain: // Set last seq number. db.addSeq(uint64(b.Len())) - if b.size() >= mdbFree { + if b.size() >= memFree { db.rotateMem(0) } return @@ -249,7 +249,8 @@ func (db *DB) Put(key, value []byte, wo *opt.WriteOptions) error { return db.Write(b, wo) } -// Delete deletes the value for the given key. +// Delete deletes the value for the given key. It returns ErrNotFound if +// the DB does not contain the key. // // It is safe to modify the contents of the arguments after Delete returns. func (db *DB) Delete(key []byte, wo *opt.WriteOptions) error { @@ -289,9 +290,9 @@ func (db *DB) CompactRange(r util.Range) error { } // Check for overlaps in memdb. - mdb := db.getEffectiveMem() - defer mdb.decref() - if isMemOverlaps(db.s.icmp, mdb.DB, r.Start, r.Limit) { + mem := db.getEffectiveMem() + defer mem.decref() + if isMemOverlaps(db.s.icmp, mem.mdb, r.Start, r.Limit) { // Memdb compaction. if _, err := db.rotateMem(0); err != nil { <-db.writeLockC @@ -308,31 +309,3 @@ func (db *DB) CompactRange(r util.Range) error { // Table compaction. return db.compSendRange(db.tcompCmdC, -1, r.Start, r.Limit) } - -// SetReadOnly makes DB read-only. It will stay read-only until reopened. -func (db *DB) SetReadOnly() error { - if err := db.ok(); err != nil { - return err - } - - // Lock writer. - select { - case db.writeLockC <- struct{}{}: - db.compWriteLocking = true - case err := <-db.compPerErrC: - return err - case _, _ = <-db.closeC: - return ErrClosed - } - - // Set compaction read-only. - select { - case db.compErrSetC <- ErrReadOnly: - case perr := <-db.compPerErrC: - return perr - case _, _ = <-db.closeC: - return ErrClosed - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go index c8bd66a5aa9ab6aded8e4782358e4621c3e019e7..d5ba768413b5d23b0ddbb4a4343a232e7bdd8d52 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors.go @@ -7,12 +7,11 @@ package leveldb import ( - "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" ) var ( ErrNotFound = errors.ErrNotFound - ErrReadOnly = errors.New("leveldb: read-only mode") ErrSnapshotReleased = errors.New("leveldb: snapshot released") ErrIterReleased = errors.New("leveldb: iterator released") ErrClosed = errors.New("leveldb: closed") diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go index 84b5d6b7b2149744c0098d7ca31b0669554be8ed..a22b4b9d5722df1336e8b14dffeb97d019140681 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors/errors.go @@ -11,8 +11,8 @@ import ( "errors" "fmt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go index b328ece4e2caffe0b1004bed2047d3a3cb56eb4d..8ae2e50e8ea41980e5a5e2a7c3e8fb147fe67a98 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/external_test.go @@ -10,8 +10,8 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) var _ = testutil.Defer(func() { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go index 37c1e146bcc088a5f7dc7ba621d68f3a9c7c8509..fcad1fbf8474328d7b01dd20f33e357f40176b40 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter.go @@ -7,7 +7,7 @@ package leveldb import ( - "github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" ) type iFilter struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go index bab0e99705f59201d6920633893012938dc8a592..68c925522f4fa25ced117d2b78a4785b53dcb51c 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom.go @@ -7,7 +7,7 @@ package filter import ( - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func bloomHash(key []byte) uint32 { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go index 1fb56f07136f23a4314455852a242109587fbcd6..70bfdaa54ea848419067098e7978a8f61cb9d94a 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter/bloom_test.go @@ -8,7 +8,7 @@ package filter import ( "encoding/binary" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" "testing" ) diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go index a23ab05f70fe8e45c0c0a8e0e4617884219a0cbf..3050fb86ae651d0dbf9de64f39df378b122825ba 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go @@ -7,7 +7,7 @@ package iterator import ( - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // BasicArray is the interface that wraps basic Len and Search method. diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go index 1ed6d07cbb6e041e4e999112fa3ccf0ec1328c6b..9c9c27a686462b1afa5b2a2ffbacfba8292d7c14 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/array_iter_test.go @@ -9,8 +9,8 @@ package iterator_test import ( . "github.com/onsi/ginkgo" - . "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/testutil" + . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) var _ = testutil.Defer(func() { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go index 939adbb9332bcc2ce462303b9f95c9601fada105..71843607f34ae43d607f25712c91feee5ff7d950 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go @@ -7,8 +7,8 @@ package iterator import ( - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // IteratorIndexer is the interface that wraps CommonIterator and basic Get diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go index 72a7978924ebf0aaa52eefd16ef79ac57a40f086..8d64ed8b4ad803a45f777107ebd51f695f5c692e 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter_test.go @@ -11,9 +11,9 @@ import ( . "github.com/onsi/ginkgo" - "github.com/syndtr/goleveldb/leveldb/comparer" - . "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) type keyValue struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go index c2522860b0b8c0477fec8d54068053e22de6a1d4..f6876eea87fbfd824c77831de93b911c06084f21 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter.go @@ -11,7 +11,7 @@ package iterator import ( "errors" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go index 5ef8d5bafb3f265754c74562d987ed2858bb174f..3e54f8b1977d9e29bf744acc78d28163231e77a5 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/iter_suite_test.go @@ -3,7 +3,7 @@ package iterator_test import ( "testing" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) func TestIterator(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go index 1a7e29df8fbd975902e5042031cd777b9a9764ce..df1daffa352f21c63c16e6c6a2429f90be74ec88 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go @@ -7,9 +7,9 @@ package iterator import ( - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type dir int diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go index e523b63e4b6694cf6e0a016b06830aefdf8e8831..8ef775f31657728ff39962dfda0f6fe890d130da 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter_test.go @@ -10,9 +10,9 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/comparer" - . "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) var _ = testutil.Defer(func() { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go index 6519ec660eb7110425d545d6e7154c0a447a869f..4e4aae982c72c8148dd3253050e6c02bc7f8c636 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal/journal.go @@ -82,8 +82,8 @@ import ( "fmt" "io" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // These constants are part of the wire format and should not be changed. diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go index 572ae8150c792dd43a3cc0477d1ff44075a51db3..eeff53321e810198c67d6920ea6c437bd22eab99 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key.go @@ -10,7 +10,7 @@ import ( "encoding/binary" "fmt" - "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" ) type ErrIkeyCorrupted struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go index 30eadf7847ed9b35495c2ee56f800de9fff79b84..eb9526f751f320238b90945a2dd4e8db359247cb 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/key_test.go @@ -10,7 +10,7 @@ import ( "bytes" "testing" - "github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" ) var defaultIComparer = &iComparer{comparer.DefaultComparer} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go index fefa007a7047c7c0f5dcf69769db92d74702a087..33be15d6b59ec77c8b2ff71f8e9bf146c9b106fa 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/leveldb_suite_test.go @@ -3,7 +3,7 @@ package leveldb import ( "testing" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) func TestLevelDB(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go index b05084caa65eb0a607b796d8819dcd0656acdf3f..51ca66ba7d1b1125136ff074d13f2b314f0d78a1 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/bench_test.go @@ -11,7 +11,7 @@ import ( "math/rand" "testing" - "github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" ) func BenchmarkPut(b *testing.B) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go index 1395bd928080f5514643e2c7d24a53d57025c702..67c7254c482f543afc91ef6ca2353cd488a39c87 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go @@ -11,10 +11,10 @@ import ( "math/rand" "sync" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( @@ -206,7 +206,6 @@ func (p *DB) randHeight() (h int) { return } -// Must hold RW-lock if prev == true, as it use shared prevNode slice. func (p *DB) findGE(key []byte, prev bool) (int, bool) { node := 0 h := p.maxHeight - 1 @@ -303,7 +302,7 @@ func (p *DB) Put(key []byte, value []byte) error { node := len(p.nodeData) p.nodeData = append(p.nodeData, kvOffset, len(key), len(value), h) for i, n := range p.prevNode[:h] { - m := n + nNext + i + m := n + 4 + i p.nodeData = append(p.nodeData, p.nodeData[m]) p.nodeData[m] = node } @@ -435,22 +434,20 @@ func (p *DB) Len() int { // Reset resets the DB to initial empty state. Allows reuse the buffer. func (p *DB) Reset() { - p.mu.Lock() p.rnd = rand.New(rand.NewSource(0xdeadbeef)) p.maxHeight = 1 p.n = 0 p.kvSize = 0 p.kvData = p.kvData[:0] - p.nodeData = p.nodeData[:nNext+tMaxHeight] + p.nodeData = p.nodeData[:4+tMaxHeight] p.nodeData[nKV] = 0 p.nodeData[nKey] = 0 p.nodeData[nVal] = 0 p.nodeData[nHeight] = tMaxHeight for n := 0; n < tMaxHeight; n++ { - p.nodeData[nNext+n] = 0 + p.nodeData[4+n] = 0 p.prevNode[n] = 0 } - p.mu.Unlock() } // New creates a new initalized in-memory key/value DB. The capacity diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go index 18c304b7f19a6c66b008e7fe2f6d879cf0a0a6ad..7be1214f39d1186edb10e096581599af7b08f5b7 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_suite_test.go @@ -3,7 +3,7 @@ package memdb import ( "testing" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) func TestMemDB(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go index 5dd6dbc7b7bbdb1d3e252c3cc1bb1995eb99ae4a..131333c16a033197f9ba0da6b7fdcd6a6bbbf39f 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/memdb/memdb_test.go @@ -10,10 +10,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/testutil" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func (p *DB) TestFindLT(key []byte) (rkey, value []byte, err error) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go index f9a309dac6f499fffaee3138179b1c0b46bd2912..abf0f7ea72ba55afa228e6986c92583d13a89572 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt/options.go @@ -8,9 +8,9 @@ package opt import ( - "github.com/syndtr/goleveldb/leveldb/cache" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" "math" ) @@ -34,11 +34,10 @@ var ( DefaultCompactionTotalSize = 10 * MiB DefaultCompactionTotalSizeMultiplier = 10.0 DefaultCompressionType = SnappyCompression - DefaultIteratorSamplingRate = 1 * MiB - DefaultMaxMemCompationLevel = 2 - DefaultNumLevel = 7 DefaultOpenFilesCacher = LRUCacher DefaultOpenFilesCacheCapacity = 500 + DefaultMaxMemCompationLevel = 2 + DefaultNumLevel = 7 DefaultWriteBuffer = 4 * MiB DefaultWriteL0PauseTrigger = 12 DefaultWriteL0SlowdownTrigger = 8 @@ -154,7 +153,7 @@ type Options struct { BlockCacher Cacher // BlockCacheCapacity defines the capacity of the 'sorted table' block caching. - // Use -1 for zero, this has same effect as specifying NoCacher to BlockCacher. + // Use -1 for zero, this has same effect with specifying NoCacher to BlockCacher. // // The default value is 8MiB. BlockCacheCapacity int @@ -250,11 +249,6 @@ type Options struct { // The default value (DefaultCompression) uses snappy compression. Compression Compression - // DisableBufferPool allows disable use of util.BufferPool functionality. - // - // The default value is false. - DisableBufferPool bool - // DisableBlockCache allows disable use of cache.Cache functionality on // 'sorted table' block. // @@ -294,13 +288,6 @@ type Options struct { // The default value is nil. Filter filter.Filter - // IteratorSamplingRate defines approximate gap (in bytes) between read - // sampling of an iterator. The samples will be used to determine when - // compaction should be triggered. - // - // The default is 1MiB. - IteratorSamplingRate int - // MaxMemCompationLevel defines maximum level a newly compacted 'memdb' // will be pushed into if doesn't creates overlap. This should less than // NumLevel. Use -1 for level-0. @@ -321,16 +308,11 @@ type Options struct { OpenFilesCacher Cacher // OpenFilesCacheCapacity defines the capacity of the open files caching. - // Use -1 for zero, this has same effect as specifying NoCacher to OpenFilesCacher. + // Use -1 for zero, this has same effect with specifying NoCacher to OpenFilesCacher. // // The default value is 500. OpenFilesCacheCapacity int - // If true then opens DB in read-only mode. - // - // The default value is false. - ReadOnly bool - // Strict defines the DB strict level. Strict Strict @@ -373,9 +355,9 @@ func (o *Options) GetBlockCacher() Cacher { } func (o *Options) GetBlockCacheCapacity() int { - if o == nil || o.BlockCacheCapacity == 0 { + if o == nil || o.BlockCacheCapacity <= 0 { return DefaultBlockCacheCapacity - } else if o.BlockCacheCapacity < 0 { + } else if o.BlockCacheCapacity == -1 { return 0 } return o.BlockCacheCapacity @@ -482,20 +464,6 @@ func (o *Options) GetCompression() Compression { return o.Compression } -func (o *Options) GetDisableBufferPool() bool { - if o == nil { - return false - } - return o.DisableBufferPool -} - -func (o *Options) GetDisableBlockCache() bool { - if o == nil { - return false - } - return o.DisableBlockCache -} - func (o *Options) GetDisableCompactionBackoff() bool { if o == nil { return false @@ -524,19 +492,12 @@ func (o *Options) GetFilter() filter.Filter { return o.Filter } -func (o *Options) GetIteratorSamplingRate() int { - if o == nil || o.IteratorSamplingRate <= 0 { - return DefaultIteratorSamplingRate - } - return o.IteratorSamplingRate -} - func (o *Options) GetMaxMemCompationLevel() int { level := DefaultMaxMemCompationLevel if o != nil { if o.MaxMemCompationLevel > 0 { level = o.MaxMemCompationLevel - } else if o.MaxMemCompationLevel < 0 { + } else if o.MaxMemCompationLevel == -1 { level = 0 } } @@ -564,21 +525,14 @@ func (o *Options) GetOpenFilesCacher() Cacher { } func (o *Options) GetOpenFilesCacheCapacity() int { - if o == nil || o.OpenFilesCacheCapacity == 0 { + if o == nil || o.OpenFilesCacheCapacity <= 0 { return DefaultOpenFilesCacheCapacity - } else if o.OpenFilesCacheCapacity < 0 { + } else if o.OpenFilesCacheCapacity == -1 { return 0 } return o.OpenFilesCacheCapacity } -func (o *Options) GetReadOnly() bool { - if o == nil { - return false - } - return o.ReadOnly -} - func (o *Options) GetStrict(strict Strict) bool { if o == nil || o.Strict == 0 { return DefaultStrict&strict != 0 diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go index a3d84ef60d53d4afb73ba7bdf1f848ebbb202808..a13abb675a960c430b5acb5084812c3794922d9e 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/options.go @@ -7,8 +7,8 @@ package leveldb import ( - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" ) func dupOptions(o *opt.Options) *opt.Options { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go index f0bba4602ca528493576243aaef1da156556cb58..e8c81572a542c1b0b14698e5b761beeca27e7d53 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session.go @@ -11,12 +11,14 @@ import ( "io" "os" "sync" + "sync/atomic" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/journal" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type ErrManifestCorrupted struct { @@ -125,16 +127,11 @@ func (s *session) recover() (err error) { return } defer reader.Close() + strict := s.o.GetStrict(opt.StrictManifest) + jr := journal.NewReader(reader, dropper{s, m}, strict, true) - var ( - // Options. - numLevel = s.o.GetNumLevel() - strict = s.o.GetStrict(opt.StrictManifest) - - jr = journal.NewReader(reader, dropper{s, m}, strict, true) - rec = &sessionRecord{} - staging = s.stVersion.newStaging() - ) + staging := s.stVersion.newStaging() + rec := &sessionRecord{numLevel: s.o.GetNumLevel()} for { var r io.Reader r, err = jr.Next() @@ -146,7 +143,7 @@ func (s *session) recover() (err error) { return errors.SetFile(err, m) } - err = rec.decode(r, numLevel) + err = rec.decode(r) if err == nil { // save compact pointers for _, r := range rec.compPtrs { @@ -209,3 +206,250 @@ func (s *session) commit(r *sessionRecord) (err error) { return } + +// Pick a compaction based on current state; need external synchronization. +func (s *session) pickCompaction() *compaction { + v := s.version() + + var level int + var t0 tFiles + if v.cScore >= 1 { + level = v.cLevel + cptr := s.stCompPtrs[level] + tables := v.tables[level] + for _, t := range tables { + if cptr == nil || s.icmp.Compare(t.imax, cptr) > 0 { + t0 = append(t0, t) + break + } + } + if len(t0) == 0 { + t0 = append(t0, tables[0]) + } + } else { + if p := atomic.LoadPointer(&v.cSeek); p != nil { + ts := (*tSet)(p) + level = ts.level + t0 = append(t0, ts.table) + } else { + v.release() + return nil + } + } + + return newCompaction(s, v, level, t0) +} + +// Create compaction from given level and range; need external synchronization. +func (s *session) getCompactionRange(level int, umin, umax []byte) *compaction { + v := s.version() + + t0 := v.tables[level].getOverlaps(nil, s.icmp, umin, umax, level == 0) + if len(t0) == 0 { + v.release() + return nil + } + + // Avoid compacting too much in one shot in case the range is large. + // But we cannot do this for level-0 since level-0 files can overlap + // and we must not pick one file and drop another older file if the + // two files overlap. + if level > 0 { + limit := uint64(v.s.o.GetCompactionSourceLimit(level)) + total := uint64(0) + for i, t := range t0 { + total += t.size + if total >= limit { + s.logf("table@compaction limiting F·%d -> F·%d", len(t0), i+1) + t0 = t0[:i+1] + break + } + } + } + + return newCompaction(s, v, level, t0) +} + +func newCompaction(s *session, v *version, level int, t0 tFiles) *compaction { + c := &compaction{ + s: s, + v: v, + level: level, + tables: [2]tFiles{t0, nil}, + maxGPOverlaps: uint64(s.o.GetCompactionGPOverlaps(level)), + tPtrs: make([]int, s.o.GetNumLevel()), + } + c.expand() + c.save() + return c +} + +// compaction represent a compaction state. +type compaction struct { + s *session + v *version + + level int + tables [2]tFiles + maxGPOverlaps uint64 + + gp tFiles + gpi int + seenKey bool + gpOverlappedBytes uint64 + imin, imax iKey + tPtrs []int + released bool + + snapGPI int + snapSeenKey bool + snapGPOverlappedBytes uint64 + snapTPtrs []int +} + +func (c *compaction) save() { + c.snapGPI = c.gpi + c.snapSeenKey = c.seenKey + c.snapGPOverlappedBytes = c.gpOverlappedBytes + c.snapTPtrs = append(c.snapTPtrs[:0], c.tPtrs...) +} + +func (c *compaction) restore() { + c.gpi = c.snapGPI + c.seenKey = c.snapSeenKey + c.gpOverlappedBytes = c.snapGPOverlappedBytes + c.tPtrs = append(c.tPtrs[:0], c.snapTPtrs...) +} + +func (c *compaction) release() { + if !c.released { + c.released = true + c.v.release() + } +} + +// Expand compacted tables; need external synchronization. +func (c *compaction) expand() { + limit := uint64(c.s.o.GetCompactionExpandLimit(c.level)) + vt0, vt1 := c.v.tables[c.level], c.v.tables[c.level+1] + + t0, t1 := c.tables[0], c.tables[1] + imin, imax := t0.getRange(c.s.icmp) + // We expand t0 here just incase ukey hop across tables. + t0 = vt0.getOverlaps(t0, c.s.icmp, imin.ukey(), imax.ukey(), c.level == 0) + if len(t0) != len(c.tables[0]) { + imin, imax = t0.getRange(c.s.icmp) + } + t1 = vt1.getOverlaps(t1, c.s.icmp, imin.ukey(), imax.ukey(), false) + // Get entire range covered by compaction. + amin, amax := append(t0, t1...).getRange(c.s.icmp) + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if len(t1) > 0 { + exp0 := vt0.getOverlaps(nil, c.s.icmp, amin.ukey(), amax.ukey(), c.level == 0) + if len(exp0) > len(t0) && t1.size()+exp0.size() < limit { + xmin, xmax := exp0.getRange(c.s.icmp) + exp1 := vt1.getOverlaps(nil, c.s.icmp, xmin.ukey(), xmax.ukey(), false) + if len(exp1) == len(t1) { + c.s.logf("table@compaction expanding L%d+L%d (F·%d S·%s)+(F·%d S·%s) -> (F·%d S·%s)+(F·%d S·%s)", + c.level, c.level+1, len(t0), shortenb(int(t0.size())), len(t1), shortenb(int(t1.size())), + len(exp0), shortenb(int(exp0.size())), len(exp1), shortenb(int(exp1.size()))) + imin, imax = xmin, xmax + t0, t1 = exp0, exp1 + amin, amax = append(t0, t1...).getRange(c.s.icmp) + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if c.level+2 < c.s.o.GetNumLevel() { + c.gp = c.v.tables[c.level+2].getOverlaps(c.gp, c.s.icmp, amin.ukey(), amax.ukey(), false) + } + + c.tables[0], c.tables[1] = t0, t1 + c.imin, c.imax = imin, imax +} + +// Check whether compaction is trivial. +func (c *compaction) trivial() bool { + return len(c.tables[0]) == 1 && len(c.tables[1]) == 0 && c.gp.size() <= c.maxGPOverlaps +} + +func (c *compaction) baseLevelForKey(ukey []byte) bool { + for level, tables := range c.v.tables[c.level+2:] { + for c.tPtrs[level] < len(tables) { + t := tables[c.tPtrs[level]] + if c.s.icmp.uCompare(ukey, t.imax.ukey()) <= 0 { + // We've advanced far enough. + if c.s.icmp.uCompare(ukey, t.imin.ukey()) >= 0 { + // Key falls in this file's range, so definitely not base level. + return false + } + break + } + c.tPtrs[level]++ + } + } + return true +} + +func (c *compaction) shouldStopBefore(ikey iKey) bool { + for ; c.gpi < len(c.gp); c.gpi++ { + gp := c.gp[c.gpi] + if c.s.icmp.Compare(ikey, gp.imax) <= 0 { + break + } + if c.seenKey { + c.gpOverlappedBytes += gp.size + } + } + c.seenKey = true + + if c.gpOverlappedBytes > c.maxGPOverlaps { + // Too much overlap for current output; start new output. + c.gpOverlappedBytes = 0 + return true + } + return false +} + +// Creates an iterator. +func (c *compaction) newIterator() iterator.Iterator { + // Creates iterator slice. + icap := len(c.tables) + if c.level == 0 { + // Special case for level-0 + icap = len(c.tables[0]) + 1 + } + its := make([]iterator.Iterator, 0, icap) + + // Options. + ro := &opt.ReadOptions{ + DontFillCache: true, + Strict: opt.StrictOverride, + } + strict := c.s.o.GetStrict(opt.StrictCompaction) + if strict { + ro.Strict |= opt.StrictReader + } + + for i, tables := range c.tables { + if len(tables) == 0 { + continue + } + + // Level-0 is not sorted and may overlaps each other. + if c.level+i == 0 { + for _, t := range tables { + its = append(its, c.s.tops.newIterator(t, nil, ro)) + } + } else { + it := iterator.NewIndexedIterator(tables.newIndexIterator(c.s.tops, c.s.icmp, nil, ro), strict) + its = append(its, it) + } + } + + return iterator.NewMergedIterator(its, c.s.icmp, strict) +} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go deleted file mode 100644 index 7c5a79418cc4bb2a3bf70ba7314c4804e04349f9..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_compaction.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package leveldb - -import ( - "sync/atomic" - - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/memdb" - "github.com/syndtr/goleveldb/leveldb/opt" -) - -func (s *session) pickMemdbLevel(umin, umax []byte) int { - v := s.version() - defer v.release() - return v.pickMemdbLevel(umin, umax) -} - -func (s *session) flushMemdb(rec *sessionRecord, mdb *memdb.DB, level int) (level_ int, err error) { - // Create sorted table. - iter := mdb.NewIterator(nil) - defer iter.Release() - t, n, err := s.tops.createFrom(iter) - if err != nil { - return level, err - } - - // Pick level and add to record. - if level < 0 { - level = s.pickMemdbLevel(t.imin.ukey(), t.imax.ukey()) - } - rec.addTableFile(level, t) - - s.logf("memdb@flush created L%d@%d N·%d S·%s %q:%q", level, t.file.Num(), n, shortenb(int(t.size)), t.imin, t.imax) - return level, nil -} - -// Pick a compaction based on current state; need external synchronization. -func (s *session) pickCompaction() *compaction { - v := s.version() - - var level int - var t0 tFiles - if v.cScore >= 1 { - level = v.cLevel - cptr := s.stCompPtrs[level] - tables := v.tables[level] - for _, t := range tables { - if cptr == nil || s.icmp.Compare(t.imax, cptr) > 0 { - t0 = append(t0, t) - break - } - } - if len(t0) == 0 { - t0 = append(t0, tables[0]) - } - } else { - if p := atomic.LoadPointer(&v.cSeek); p != nil { - ts := (*tSet)(p) - level = ts.level - t0 = append(t0, ts.table) - } else { - v.release() - return nil - } - } - - return newCompaction(s, v, level, t0) -} - -// Create compaction from given level and range; need external synchronization. -func (s *session) getCompactionRange(level int, umin, umax []byte) *compaction { - v := s.version() - - t0 := v.tables[level].getOverlaps(nil, s.icmp, umin, umax, level == 0) - if len(t0) == 0 { - v.release() - return nil - } - - // Avoid compacting too much in one shot in case the range is large. - // But we cannot do this for level-0 since level-0 files can overlap - // and we must not pick one file and drop another older file if the - // two files overlap. - if level > 0 { - limit := uint64(v.s.o.GetCompactionSourceLimit(level)) - total := uint64(0) - for i, t := range t0 { - total += t.size - if total >= limit { - s.logf("table@compaction limiting F·%d -> F·%d", len(t0), i+1) - t0 = t0[:i+1] - break - } - } - } - - return newCompaction(s, v, level, t0) -} - -func newCompaction(s *session, v *version, level int, t0 tFiles) *compaction { - c := &compaction{ - s: s, - v: v, - level: level, - tables: [2]tFiles{t0, nil}, - maxGPOverlaps: uint64(s.o.GetCompactionGPOverlaps(level)), - tPtrs: make([]int, s.o.GetNumLevel()), - } - c.expand() - c.save() - return c -} - -// compaction represent a compaction state. -type compaction struct { - s *session - v *version - - level int - tables [2]tFiles - maxGPOverlaps uint64 - - gp tFiles - gpi int - seenKey bool - gpOverlappedBytes uint64 - imin, imax iKey - tPtrs []int - released bool - - snapGPI int - snapSeenKey bool - snapGPOverlappedBytes uint64 - snapTPtrs []int -} - -func (c *compaction) save() { - c.snapGPI = c.gpi - c.snapSeenKey = c.seenKey - c.snapGPOverlappedBytes = c.gpOverlappedBytes - c.snapTPtrs = append(c.snapTPtrs[:0], c.tPtrs...) -} - -func (c *compaction) restore() { - c.gpi = c.snapGPI - c.seenKey = c.snapSeenKey - c.gpOverlappedBytes = c.snapGPOverlappedBytes - c.tPtrs = append(c.tPtrs[:0], c.snapTPtrs...) -} - -func (c *compaction) release() { - if !c.released { - c.released = true - c.v.release() - } -} - -// Expand compacted tables; need external synchronization. -func (c *compaction) expand() { - limit := uint64(c.s.o.GetCompactionExpandLimit(c.level)) - vt0, vt1 := c.v.tables[c.level], c.v.tables[c.level+1] - - t0, t1 := c.tables[0], c.tables[1] - imin, imax := t0.getRange(c.s.icmp) - // We expand t0 here just incase ukey hop across tables. - t0 = vt0.getOverlaps(t0, c.s.icmp, imin.ukey(), imax.ukey(), c.level == 0) - if len(t0) != len(c.tables[0]) { - imin, imax = t0.getRange(c.s.icmp) - } - t1 = vt1.getOverlaps(t1, c.s.icmp, imin.ukey(), imax.ukey(), false) - // Get entire range covered by compaction. - amin, amax := append(t0, t1...).getRange(c.s.icmp) - - // See if we can grow the number of inputs in "level" without - // changing the number of "level+1" files we pick up. - if len(t1) > 0 { - exp0 := vt0.getOverlaps(nil, c.s.icmp, amin.ukey(), amax.ukey(), c.level == 0) - if len(exp0) > len(t0) && t1.size()+exp0.size() < limit { - xmin, xmax := exp0.getRange(c.s.icmp) - exp1 := vt1.getOverlaps(nil, c.s.icmp, xmin.ukey(), xmax.ukey(), false) - if len(exp1) == len(t1) { - c.s.logf("table@compaction expanding L%d+L%d (F·%d S·%s)+(F·%d S·%s) -> (F·%d S·%s)+(F·%d S·%s)", - c.level, c.level+1, len(t0), shortenb(int(t0.size())), len(t1), shortenb(int(t1.size())), - len(exp0), shortenb(int(exp0.size())), len(exp1), shortenb(int(exp1.size()))) - imin, imax = xmin, xmax - t0, t1 = exp0, exp1 - amin, amax = append(t0, t1...).getRange(c.s.icmp) - } - } - } - - // Compute the set of grandparent files that overlap this compaction - // (parent == level+1; grandparent == level+2) - if c.level+2 < c.s.o.GetNumLevel() { - c.gp = c.v.tables[c.level+2].getOverlaps(c.gp, c.s.icmp, amin.ukey(), amax.ukey(), false) - } - - c.tables[0], c.tables[1] = t0, t1 - c.imin, c.imax = imin, imax -} - -// Check whether compaction is trivial. -func (c *compaction) trivial() bool { - return len(c.tables[0]) == 1 && len(c.tables[1]) == 0 && c.gp.size() <= c.maxGPOverlaps -} - -func (c *compaction) baseLevelForKey(ukey []byte) bool { - for level, tables := range c.v.tables[c.level+2:] { - for c.tPtrs[level] < len(tables) { - t := tables[c.tPtrs[level]] - if c.s.icmp.uCompare(ukey, t.imax.ukey()) <= 0 { - // We've advanced far enough. - if c.s.icmp.uCompare(ukey, t.imin.ukey()) >= 0 { - // Key falls in this file's range, so definitely not base level. - return false - } - break - } - c.tPtrs[level]++ - } - } - return true -} - -func (c *compaction) shouldStopBefore(ikey iKey) bool { - for ; c.gpi < len(c.gp); c.gpi++ { - gp := c.gp[c.gpi] - if c.s.icmp.Compare(ikey, gp.imax) <= 0 { - break - } - if c.seenKey { - c.gpOverlappedBytes += gp.size - } - } - c.seenKey = true - - if c.gpOverlappedBytes > c.maxGPOverlaps { - // Too much overlap for current output; start new output. - c.gpOverlappedBytes = 0 - return true - } - return false -} - -// Creates an iterator. -func (c *compaction) newIterator() iterator.Iterator { - // Creates iterator slice. - icap := len(c.tables) - if c.level == 0 { - // Special case for level-0. - icap = len(c.tables[0]) + 1 - } - its := make([]iterator.Iterator, 0, icap) - - // Options. - ro := &opt.ReadOptions{ - DontFillCache: true, - Strict: opt.StrictOverride, - } - strict := c.s.o.GetStrict(opt.StrictCompaction) - if strict { - ro.Strict |= opt.StrictReader - } - - for i, tables := range c.tables { - if len(tables) == 0 { - continue - } - - // Level-0 is not sorted and may overlaps each other. - if c.level+i == 0 { - for _, t := range tables { - its = append(its, c.s.tops.newIterator(t, nil, ro)) - } - } else { - it := iterator.NewIndexedIterator(tables.newIndexIterator(c.s.tops, c.s.icmp, nil, ro), strict) - its = append(its, it) - } - } - - return iterator.NewMergedIterator(its, c.s.icmp, strict) -} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go index 405e07bef4f1f7b881044a7e449d96b99c4bd68e..5fad6105b36eda1a7237e2007878e0110e955607 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record.go @@ -12,7 +12,7 @@ import ( "io" "strings" - "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" ) type byteReader interface { @@ -52,6 +52,8 @@ type dtRecord struct { } type sessionRecord struct { + numLevel int + hasRec int comparer string journalNum uint64 @@ -228,7 +230,7 @@ func (p *sessionRecord) readBytes(field string, r byteReader) []byte { return x } -func (p *sessionRecord) readLevel(field string, r io.ByteReader, numLevel int) int { +func (p *sessionRecord) readLevel(field string, r io.ByteReader) int { if p.err != nil { return 0 } @@ -236,14 +238,14 @@ func (p *sessionRecord) readLevel(field string, r io.ByteReader, numLevel int) i if p.err != nil { return 0 } - if x >= uint64(numLevel) { + if x >= uint64(p.numLevel) { p.err = errors.NewErrCorrupted(nil, &ErrManifestCorrupted{field, "invalid level number"}) return 0 } return int(x) } -func (p *sessionRecord) decode(r io.Reader, numLevel int) error { +func (p *sessionRecord) decode(r io.Reader) error { br, ok := r.(byteReader) if !ok { br = bufio.NewReader(r) @@ -284,13 +286,13 @@ func (p *sessionRecord) decode(r io.Reader, numLevel int) error { p.setSeqNum(x) } case recCompPtr: - level := p.readLevel("comp-ptr.level", br, numLevel) + level := p.readLevel("comp-ptr.level", br) ikey := p.readBytes("comp-ptr.ikey", br) if p.err == nil { p.addCompPtr(level, iKey(ikey)) } case recAddTable: - level := p.readLevel("add-table.level", br, numLevel) + level := p.readLevel("add-table.level", br) num := p.readUvarint("add-table.num", br) size := p.readUvarint("add-table.size", br) imin := p.readBytes("add-table.imin", br) @@ -299,7 +301,7 @@ func (p *sessionRecord) decode(r io.Reader, numLevel int) error { p.addTable(level, num, size, imin, imax) } case recDelTable: - level := p.readLevel("del-table.level", br, numLevel) + level := p.readLevel("del-table.level", br) num := p.readUvarint("del-table.num", br) if p.err == nil { p.delTable(level, num) diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go index 33c14875618b53cd0408e77f4819c47adf9a1994..ba3864b20828dd0452324765ddba8c780b91c73d 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_record_test.go @@ -10,7 +10,7 @@ import ( "bytes" "testing" - "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" ) func decodeEncode(v *sessionRecord) (res bool, err error) { @@ -19,8 +19,8 @@ func decodeEncode(v *sessionRecord) (res bool, err error) { if err != nil { return } - v2 := &sessionRecord{} - err = v.decode(b, opt.DefaultNumLevel) + v2 := &sessionRecord{numLevel: opt.DefaultNumLevel} + err = v.decode(b) if err != nil { return } @@ -34,7 +34,7 @@ func decodeEncode(v *sessionRecord) (res bool, err error) { func TestSessionRecord_EncodeDecode(t *testing.T) { big := uint64(1) << 50 - v := &sessionRecord{} + v := &sessionRecord{numLevel: opt.DefaultNumLevel} i := uint64(0) test := func() { res, err := decodeEncode(v) diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go index 399a788bad2de7b07974e09f14e400f99e484d06..23f3d80fab2b57e0fb7ac3ac3d42b3743e32d478 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/session_util.go @@ -10,8 +10,8 @@ import ( "fmt" "sync/atomic" - "github.com/syndtr/goleveldb/leveldb/journal" - "github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/journal" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" ) // Logging. @@ -182,7 +182,7 @@ func (s *session) newManifest(rec *sessionRecord, v *version) (err error) { defer v.release() } if rec == nil { - rec = &sessionRecord{} + rec = &sessionRecord{numLevel: s.o.GetNumLevel()} } s.fillRecord(rec, true) v.fillRecord(rec) diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go index 46cc9d07012e91141cae7c08903f8421c394c412..9329faf7a7676b75572f4ef612e6d7e320272858 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var errFileOpen = errors.New("leveldb/storage: file still open") diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go index fc1c8165df1a0d05d432e47889fe8ccb0b943c7f..8952193112728a24485df4d5cfca73ebae92ca6d 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go @@ -11,7 +11,7 @@ import ( "os" "sync" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) const typeShift = 3 diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go index 85dd70b06f9f6c8955d60b382d4a8652b1ba1292..bdda8c447e241d497b6dfc41fa6812b26ae157e2 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/storage.go @@ -12,7 +12,7 @@ import ( "fmt" "io" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type FileType uint32 diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go index 08be0bab3da3b28e9c889c50ef813f6c0603d29b..768dfc88ec200c74acadd8ef02acc6f399a02b42 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage_test.go @@ -17,8 +17,8 @@ import ( "sync" "testing" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) const typeShift = 4 @@ -42,8 +42,6 @@ type tsOp uint const ( tsOpOpen tsOp = iota tsOpCreate - tsOpReplace - tsOpRemove tsOpRead tsOpReadAt tsOpWrite @@ -243,10 +241,6 @@ func (tf tsFile) Replace(newfile storage.File) (err error) { if err != nil { return } - if tf.shouldErr(tsOpReplace) { - err = errors.New("leveldb.testStorage: emulated create error") - return - } err = tf.File.Replace(newfile.(tsFile).File) if err != nil { ts.t.Errorf("E: cannot replace file, num=%d type=%v: %v", tf.Num(), tf.Type(), err) @@ -264,10 +258,6 @@ func (tf tsFile) Remove() (err error) { if err != nil { return } - if tf.shouldErr(tsOpRemove) { - err = errors.New("leveldb.testStorage: emulated create error") - return - } err = tf.File.Remove() if err != nil { ts.t.Errorf("E: cannot remove file, num=%d type=%v: %v", tf.Num(), tf.Type(), err) diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go index db386f3b5465b68faff4b7f709482bdfdb830b6f..357e51845d1618453e65117b1f80f09726ee0a23 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table.go @@ -11,12 +11,12 @@ import ( "sort" "sync/atomic" - "github.com/syndtr/goleveldb/leveldb/cache" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/table" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) // tFile holds basic information about a table. @@ -441,26 +441,22 @@ func newTableOps(s *session) *tOps { var ( cacher cache.Cacher bcache *cache.Cache - bpool *util.BufferPool ) if s.o.GetOpenFilesCacheCapacity() > 0 { cacher = cache.NewLRU(s.o.GetOpenFilesCacheCapacity()) } - if !s.o.GetDisableBlockCache() { + if !s.o.DisableBlockCache { var bcacher cache.Cacher if s.o.GetBlockCacheCapacity() > 0 { bcacher = cache.NewLRU(s.o.GetBlockCacheCapacity()) } bcache = cache.NewCache(bcacher) } - if !s.o.GetDisableBufferPool() { - bpool = util.NewBufferPool(s.o.GetBlockSize() + 5) - } return &tOps{ s: s, cache: cache.NewCache(cacher), bcache: bcache, - bpool: bpool, + bpool: util.NewBufferPool(s.o.GetBlockSize() + 5), } } diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go index 00e6f9eea0dd97ae892eab1934d4f096f73a1b65..a8580cf324784e3d1122680de1e26477db26a4f2 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/block_test.go @@ -13,10 +13,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/testutil" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type blockTesting struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go index 691ffc2aa8118f7e5c864853d34580ddbbf9b9aa..1bfc3978768c2126690c6aa9f707532539e1a8f0 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/reader.go @@ -14,16 +14,16 @@ import ( "strings" "sync" - "github.comgoogle/go-snappy/snappy" - - "github.com/syndtr/goleveldb/leveldb/cache" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/gosnappy/snappy" + + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/cache" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go index 6465da6e3707c48ab28ebc176c33b80b66c0c8b3..d35a13051497c79133aa293560897c9b63276e67 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_suite_test.go @@ -3,7 +3,7 @@ package table import ( "testing" - "github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" ) func TestTable(t *testing.T) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go index 4b59b31f52b42f12e8e098ea3a20d3b10d6b334e..5429c465b6938b75d1f7e39662b66f1d4a507797 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/table_test.go @@ -12,10 +12,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/testutil" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type tableWrapper struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go index 42285b5f29e98be0f40528bae2625e26d8fe1648..51f9fc7173978511abb9ab83a1e91bfd5b60197e 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/table/writer.go @@ -12,12 +12,12 @@ import ( "fmt" "io" - "github.comgoogle/go-snappy/snappy" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/gosnappy/snappy" - "github.com/syndtr/goleveldb/leveldb/comparer" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/filter" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func sharedPrefixLen(a, b []byte) int { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go index ec3f177a12febb5259fb9d88a5b8b58e7d37dca7..a0995a4b7b7c83efb955bb97f46b319b35b69d3b 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/db.go @@ -12,9 +12,9 @@ import ( . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type DB interface{} diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go index df6d9db6a335bf388ba844ee0af918707e9caf34..5e3cbb160d543800a09960a01c63b1c60e6ed4fd 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/iter.go @@ -12,7 +12,7 @@ import ( . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" ) type IterAct int diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go index 471d5708c37d826d7c5e75139f209c816b13f7c5..83a01a4719b84ab5da4aa0e23258fa9e057089bb 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kv.go @@ -12,7 +12,7 @@ import ( "sort" "strings" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type KeyValueEntry struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go index a0b58f0e7252b632651a6480f32fc47e973cca01..78d981c7dcd38fc198fa4c70fd3b46a9c134d83a 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/kvtest.go @@ -13,8 +13,8 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) func KeyValueTesting(rnd *rand.Rand, kv KeyValue, p DB, setup func(KeyValue) DB, teardown func(DB)) { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go index 59c496d54c62e90afe4cd057d81f412b10edef6b..d515438b175e1ae785a6ae3ee500808dc7c62cdb 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/storage.go @@ -18,8 +18,8 @@ import ( . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/storage" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) var ( diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go index 97c5294b1b5dd0c16162cd49fb55ad27274cb89a..7ac261ddba2bd4c5056f737f2af07dd0cdca1f61 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil/util.go @@ -15,7 +15,7 @@ import ( "github.com/onsi/ginkgo/config" - "github.com/syndtr/goleveldb/leveldb/comparer" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/comparer" ) var ( diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go index 25bf2b29f99310e6af6ab1532ccfc9cdf1621e87..868f7ffab3e0df8ba7c583e05b1960529148e8ad 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil_test.go @@ -9,10 +9,10 @@ package leveldb import ( . "github.com/onsi/gomega" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/testutil" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/testutil" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type testingDB struct { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go index 1a5bf71a3254044964beba9aee5362e5da1ed763..7de9260d0d38eb3b21e5e2c5d2841695bda8a4ad 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util.go @@ -10,7 +10,7 @@ import ( "fmt" "sort" - "github.com/syndtr/goleveldb/leveldb/storage" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage" ) func shorten(str string) string { diff --git a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go index 011d982da82c13eaf18b9b2abb9c106f2c4a012e..e8268286f1938ed25cfcb5371cd7708a59f6b273 100644 --- a/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go +++ b/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/version.go @@ -10,9 +10,9 @@ import ( "sync/atomic" "unsafe" - "github.com/syndtr/goleveldb/leveldb/iterator" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/util" ) type tSet struct { @@ -136,8 +136,9 @@ func (v *version) get(ikey iKey, ro *opt.ReadOptions, noValue bool) (value []byt if !tseek { if tset == nil { tset = &tSet{level, t} - } else { + } else if tset.table.consumeSeek() <= 0 { tseek = true + tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset)) } } @@ -202,28 +203,6 @@ func (v *version) get(ikey iKey, ro *opt.ReadOptions, noValue bool) (value []byt return true }) - if tseek && tset.table.consumeSeek() <= 0 { - tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset)) - } - - return -} - -func (v *version) sampleSeek(ikey iKey) (tcomp bool) { - var tset *tSet - - v.walkOverlapping(ikey, func(level int, t *tFile) bool { - if tset == nil { - tset = &tSet{level, t} - return true - } else { - if tset.table.consumeSeek() <= 0 { - tcomp = atomic.CompareAndSwapPointer(&v.cSeek, nil, unsafe.Pointer(tset)) - } - return false - } - }, nil) - return } @@ -300,7 +279,7 @@ func (v *version) offsetOf(ikey iKey) (n uint64, err error) { return } -func (v *version) pickMemdbLevel(umin, umax []byte) (level int) { +func (v *version) pickLevel(umin, umax []byte) (level int) { if !v.tables[0].overlaps(v.s.icmp, umin, umax, true) { var overlaps tFiles maxLevel := v.s.o.GetMaxMemCompationLevel() diff --git a/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go b/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go index 48ac4a423ec0452caf979154573e15485834a25a..6c7e5cbc4109740ed3d2ecb517d02d63e89b84cd 100644 --- a/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go +++ b/Godeps/_workspace/src/github.com/tendermint/ed25519/ed25519.go @@ -14,7 +14,7 @@ import ( "crypto/subtle" "io" - "github.com/agl/ed25519/edwards25519" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/agl/ed25519/edwards25519" ) const ( diff --git a/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go b/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go index 571218f5516f5f679364e57cb3db1fcbf3fb3225..bbda91686372ac2982d68a41dac8b7fb446eb67a 100644 --- a/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go +++ b/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519/extra25519.go @@ -7,7 +7,7 @@ package extra25519 import ( "crypto/sha512" - "github.com/agl/ed25519/edwards25519" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/agl/ed25519/edwards25519" ) // PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/handler.go b/Godeps/_workspace/src/github.com/tendermint/log15/handler.go index 4c771b4ba65c25eddec2741d29863af9cb17222b..5dc7299843978865fec11d9103ea519e1ee5af89 100644 --- a/Godeps/_workspace/src/github.com/tendermint/log15/handler.go +++ b/Godeps/_workspace/src/github.com/tendermint/log15/handler.go @@ -11,7 +11,7 @@ import ( "sync/atomic" "unsafe" - "github.com/inconshreveable/log15/stack" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack" ) // A Logger prints its log records by writing to a Handler. diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/logger.go b/Godeps/_workspace/src/github.com/tendermint/log15/logger.go index 325448d218b1d476af1efca14ec11845ff8a6dfc..8ddf3ffd05e32b43d93bffa8748119de9665a512 100644 --- a/Godeps/_workspace/src/github.com/tendermint/log15/logger.go +++ b/Godeps/_workspace/src/github.com/tendermint/log15/logger.go @@ -30,7 +30,7 @@ func (l Lvl) String() string { case LvlInfo: return "info" case LvlNotice: - return "notice" + return "note" case LvlWarn: return "warn" case LvlError: @@ -50,7 +50,7 @@ func LvlFromString(lvlString string) (Lvl, error) { return LvlDebug, nil case "info": return LvlInfo, nil - case "notice", "note": + case "note", "notice": return LvlNotice, nil case "warn": return LvlWarn, nil diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/root.go b/Godeps/_workspace/src/github.com/tendermint/log15/root.go index 98103173063315850752f8c4752b70d09799325b..7034447afaeab3524567b74eb98c7bd3c65f7d7e 100644 --- a/Godeps/_workspace/src/github.com/tendermint/log15/root.go +++ b/Godeps/_workspace/src/github.com/tendermint/log15/root.go @@ -3,8 +3,8 @@ package log15 import ( "os" - "github.com/inconshreveable/log15/term" - "github.com/mattn/go-colorable" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/term" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/mattn/go-colorable" ) var ( diff --git a/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go b/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go index 52371b1e45ab1ac08469a56607133e18cc6716d5..64cd7d08075a7c43b884ce6076545c30a0564990 100644 --- a/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go +++ b/Godeps/_workspace/src/github.com/tendermint/log15/stack/stack_test.go @@ -9,7 +9,7 @@ import ( "runtime" "testing" - "github.com/inconshreveable/log15/stack" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/inconshreveable/log15/stack" ) type testType struct{} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go index c47633091d786c9c51ed40861ce8b890de856de0..497be012cd64708407554ad46cf04fbf7209ea46 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/alert/alert.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/sfreiberg/gotwilio" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/sfreiberg/gotwilio" ) var lastAlertUnix int64 = 0 diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go index 66be4dc820cd983b702ddd6349473fd8a5192c76..b781dd3dc0973a15ad850157c770506a6f9ee58b 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/pool.go @@ -12,8 +12,8 @@ import ( const ( requestIntervalMS = 250 - maxTotalRequests = 300 - maxPendingRequests = maxTotalRequests + maxTotalRequesters = 300 + maxPendingRequests = maxTotalRequesters maxPendingRequestsPerPeer = 75 peerTimeoutSeconds = 15 minRecvRate = 10240 // 10Kb/s @@ -36,8 +36,8 @@ type BlockPool struct { // block requests mtx sync.Mutex - requests map[int]*bpRequester - height int // the lowest key in requests. + requesters map[int]*bpRequester + height int // the lowest key in requesters. numPending int32 // number of requests pending assignment or block response // peers @@ -52,7 +52,7 @@ func NewBlockPool(start int, requestsCh chan<- BlockRequest, timeoutsCh chan<- s bp := &BlockPool{ peers: make(map[string]*bpPeer), - requests: make(map[int]*bpRequester), + requesters: make(map[int]*bpRequester), height: start, numPending: 0, @@ -65,7 +65,7 @@ func NewBlockPool(start int, requestsCh chan<- BlockRequest, timeoutsCh chan<- s func (pool *BlockPool) OnStart() error { pool.QuitService.OnStart() - go pool.makeRequestsRoutine() + go pool.makeRequestersRoutine() pool.startTime = time.Now() return nil } @@ -74,8 +74,8 @@ func (pool *BlockPool) OnStop() { pool.QuitService.OnStop() } -// Run spawns requests as needed. -func (pool *BlockPool) makeRequestsRoutine() { +// Run spawns requesters as needed. +func (pool *BlockPool) makeRequestersRoutine() { for { if !pool.IsRunning() { break @@ -86,14 +86,14 @@ func (pool *BlockPool) makeRequestsRoutine() { time.Sleep(requestIntervalMS * time.Millisecond) // check for timed out peers pool.removeTimedoutPeers() - } else if len(pool.requests) >= maxTotalRequests { + } else if len(pool.requesters) >= maxTotalRequesters { // sleep for a bit. time.Sleep(requestIntervalMS * time.Millisecond) // check for timed out peers pool.removeTimedoutPeers() } else { // request for more blocks. - pool.makeNextRequest() + pool.makeNextRequester() } } } @@ -147,10 +147,10 @@ func (pool *BlockPool) PeekTwoBlocks() (first *types.Block, second *types.Block) pool.mtx.Lock() // Lock defer pool.mtx.Unlock() - if r := pool.requests[pool.height]; r != nil { + if r := pool.requesters[pool.height]; r != nil { first = r.getBlock() } - if r := pool.requests[pool.height+1]; r != nil { + if r := pool.requesters[pool.height+1]; r != nil { second = r.getBlock() } return @@ -162,14 +162,18 @@ func (pool *BlockPool) PopRequest() { pool.mtx.Lock() // Lock defer pool.mtx.Unlock() - /* The block can disappear at any time, due to removePeer(). - if r := pool.requests[pool.height]; r == nil || r.block == nil { - PanicSanity("PopRequest() requires a valid block") + if r := pool.requesters[pool.height]; r != nil { + /* The block can disappear at any time, due to removePeer(). + if r := pool.requesters[pool.height]; r == nil || r.block == nil { + PanicSanity("PopRequest() requires a valid block") + } + */ + r.Stop() + delete(pool.requesters, pool.height) + pool.height++ + } else { + PanicSanity(Fmt("Expected requester to pop, got nothing at height %v", pool.height)) } - */ - - delete(pool.requests, pool.height) - pool.height++ } // Invalidates the block at pool.height, @@ -178,11 +182,11 @@ func (pool *BlockPool) RedoRequest(height int) { pool.mtx.Lock() // Lock defer pool.mtx.Unlock() - request := pool.requests[height] + request := pool.requesters[height] if request.block == nil { PanicSanity("Expected block to be non-nil") } - // RemovePeer will redo all requests associated with this peer. + // RemovePeer will redo all requesters associated with this peer. // TODO: record this malfeasance pool.RemovePeer(request.peerID) // Lock on peersMtx. } @@ -192,12 +196,12 @@ func (pool *BlockPool) AddBlock(peerID string, block *types.Block, blockSize int pool.mtx.Lock() // Lock defer pool.mtx.Unlock() - request := pool.requests[block.Height] - if request == nil { + requester := pool.requesters[block.Height] + if requester == nil { return } - if request.setBlock(block, peerID) { + if requester.setBlock(block, peerID) { pool.numPending-- peer := pool.getPeer(peerID) peer.decrPending(blockSize) @@ -228,10 +232,10 @@ func (pool *BlockPool) RemovePeer(peerID string) { } func (pool *BlockPool) removePeer(peerID string) { - for _, request := range pool.requests { - if request.getPeerID() == peerID { + for _, requester := range pool.requesters { + if requester.getPeerID() == peerID { pool.numPending++ - go request.redo() // pick another peer and ... + go requester.redo() // pick another peer and ... } } delete(pool.peers, peerID) @@ -269,14 +273,14 @@ func (pool *BlockPool) pickIncrAvailablePeer(minHeight int) *bpPeer { return nil } -func (pool *BlockPool) makeNextRequest() { +func (pool *BlockPool) makeNextRequester() { pool.mtx.Lock() // Lock defer pool.mtx.Unlock() - nextHeight := pool.height + len(pool.requests) + nextHeight := pool.height + len(pool.requesters) request := newBPRequester(pool, nextHeight) - pool.requests[nextHeight] = request + pool.requesters[nextHeight] = request pool.numPending++ request.Start() @@ -301,12 +305,12 @@ func (pool *BlockPool) debug() string { defer pool.mtx.Unlock() str := "" - for h := pool.height; h < pool.height+len(pool.requests); h++ { - if pool.requests[h] == nil { + for h := pool.height; h < pool.height+len(pool.requesters); h++ { + if pool.requesters[h] == nil { str += Fmt("H(%v):X ", h) } else { str += Fmt("H(%v):", h) - str += Fmt("B?(%v) ", pool.requests[h].block != nil) + str += Fmt("B?(%v) ", pool.requesters[h].block != nil) } } return str diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go index bd50d5a679588550e537f29b1f174fe6089831db..1cab4ce61093eefd3fecc1631d45fe7f255071e3 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain/reactor.go @@ -192,7 +192,7 @@ FOR_LOOP: case _ = <-switchToConsensusTicker.C: height, numPending := bcR.pool.GetStatus() outbound, inbound, _ := bcR.Switch.NumPeers() - log.Info("Consensus ticker", "numPending", numPending, "total", len(bcR.pool.requests), + log.Info("Consensus ticker", "numPending", numPending, "total", len(bcR.pool.requesters), "outbound", outbound, "inbound", inbound) if bcR.pool.IsCaughtUp() { log.Notice("Time to switch to consensus reactor!", "height", height) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go index 0c33b07569c3977bab84e037a7c567a759ebd923..378c19fc6a7361e9ba49877f2e2df471db19a40c 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/common/io.go @@ -1,6 +1,8 @@ package common import ( + "bytes" + "errors" "io" ) @@ -22,3 +24,52 @@ func (pr *PrefixedReader) Read(p []byte) (n int, err error) { return pr.reader.Read(p) } } + +// NOTE: Not goroutine safe +type BufferCloser struct { + bytes.Buffer + Closed bool +} + +func NewBufferCloser(buf []byte) *BufferCloser { + return &BufferCloser{ + *bytes.NewBuffer(buf), + false, + } +} + +func (bc *BufferCloser) Close() error { + if bc.Closed { + return errors.New("BufferCloser already closed") + } + bc.Closed = true + return nil +} + +func (bc *BufferCloser) Write(p []byte) (n int, err error) { + if bc.Closed { + return 0, errors.New("Cannot write to closed BufferCloser") + } + return bc.Buffer.Write(p) +} + +func (bc *BufferCloser) WriteByte(c byte) error { + if bc.Closed { + return errors.New("Cannot write to closed BufferCloser") + } + return bc.Buffer.WriteByte(c) +} + +func (bc *BufferCloser) WriteRune(r rune) (n int, err error) { + if bc.Closed { + return 0, errors.New("Cannot write to closed BufferCloser") + } + return bc.Buffer.WriteRune(r) +} + +func (bc *BufferCloser) WriteString(s string) (n int, err error) { + if bc.Closed { + return 0, errors.New("Cannot write to closed BufferCloser") + } + return bc.Buffer.WriteString(s) +} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go index 1a6b0225d78e20ab574f839f8acfc207723eec96..503af24fc26a0d1a89de5dc32f75d04971f0147e 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint/config.go @@ -1,7 +1,7 @@ package tendermint import ( - "github.com/naoina/toml" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml" "os" "path" "strings" @@ -25,7 +25,6 @@ func initTMRoot(rootDir string) { EnsureDir(rootDir) configFilePath := path.Join(rootDir, "config.toml") - genesisFilePath := path.Join(rootDir, "genesis.json") // Write default config file if missing. if !FileExists(configFilePath) { @@ -33,9 +32,6 @@ func initTMRoot(rootDir string) { // moniker := cfg.Prompt("Type hostname: ", "anonymous") MustWriteFile(configFilePath, []byte(defaultConfig("anonymous"))) } - if !FileExists(genesisFilePath) { - MustWriteFile(genesisFilePath, []byte(defaultGenesis)) - } } func GetConfig(rootDir string) cfg.Config { @@ -54,7 +50,10 @@ func GetConfig(rootDir string) cfg.Config { if mapConfig.IsSet("chain_id") { Exit("Cannot set 'chain_id' via config.toml") } - mapConfig.SetDefault("chain_id", "tendermint_testnet_10") + if mapConfig.IsSet("revision_file") { + Exit("Cannot set 'revision_file' via config.toml. It must match what's in the Makefile") + } + mapConfig.SetDefault("chain_id", "tendermint_testnet_11.c") // TODO ALSO UPDATE GENESIS BELOW!!! mapConfig.SetDefault("genesis_file", rootDir+"/genesis.json") mapConfig.SetDefault("moniker", "anonymous") mapConfig.SetDefault("node_laddr", "0.0.0.0:46656") @@ -65,9 +64,12 @@ func GetConfig(rootDir string) cfg.Config { mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json") mapConfig.SetDefault("db_backend", "leveldb") mapConfig.SetDefault("db_dir", rootDir+"/data") + mapConfig.SetDefault("vm_log", true) mapConfig.SetDefault("log_level", "info") mapConfig.SetDefault("rpc_laddr", "0.0.0.0:46657") - mapConfig.SetDefault("revisions_file", rootDir+"/revisions") + mapConfig.SetDefault("prof_laddr", "") + mapConfig.SetDefault("revision_file", rootDir+"/revision") + mapConfig.SetDefault("local_routing", false) return mapConfig } @@ -82,7 +84,7 @@ var defaultConfigTmpl = `# This is a TOML config file. moniker = "__MONIKER__" node_laddr = "0.0.0.0:46656" -seeds = "goldenalchemist.chaintest.net:46656" +seeds = "" fast_sync = true db_backend = "leveldb" log_level = "notice" @@ -93,63 +95,3 @@ func defaultConfig(moniker string) (defaultConfig string) { defaultConfig = strings.Replace(defaultConfigTmpl, "__MONIKER__", moniker, -1) return } - -var defaultGenesis = `{ - "chain_id": "tendermint_testnet_11", - "accounts": [ - { - "address": "9FCBA7F840A0BFEBBE755E853C9947270A912D04", - "amount": 1995999998000000 - }, - { - "address": "964B1493BBE3312278B7DEB94C39149F7899A345", - "amount": 100000000000000 - }, - { - "address": "B9FA4AB462B9C6BF6A62DB4AE77C9E7087209A04", - "amount": 1000000000000 - }, - { - "address": "F171824590D69386F709E7B6704B369C5A370D60", - "amount": 1000000000000 - }, - { - "address": "56EFE746A13D9A6054AC89C3E2A361C2DB8B9EAE", - "amount": 1000000000000 - }, - { - "address": "7C2E032D8407EDF66A04D88CF0E1D9B15D98AE2D", - "amount": 1000000000000 - }, - { - "address": "A88A61069B6660F30F65E8786AFDD4F1D8F625E9", - "amount": 1000000 - }, - { - "address": "EE2EE9247973B4AFC3867CFE5F415410AC251B61", - "amount": 1000000 - } - ], - "validators": [ - { - "pub_key": [1, "178EC6008A4364508979C70CBF100BD4BCBAA12DDE6251F5F486B4FD09014F06"], - "amount": 100000000000 - }, - { - "pub_key": [1, "2A77777CC51467DE42350D4A8F34720D527734189BE64C7A930DD169E1FED3C6"], - "amount": 100000000000 - }, - { - "pub_key": [1, "3718E69D09B11B3AD3FA31AEF07EC416D2AEED241CACE7B0F30AE9803FFB0F08"], - "amount": 100000000000 - }, - { - "pub_key": [1, "C6B0440DEACD1E4CF1C736CEB8E38E788B700BA2B2045A55CB657A455CF5F889"], - "amount": 100000000000 - }, - { - "pub_key": [1, "3BA1190D54F91EFBF8B0125F7EC116AD4BA2894B6EE38564A5D5FD3230D91F7B"], - "amount": 100000000000 - } - ] -}` diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go index 108d37a3f9ac8fd758fbcfc3ed14c374ef45c432..150bc64ffd8866e4d3aa54c7140bdfffebca0f00 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test/config.go @@ -3,7 +3,7 @@ package tendermint_test import ( - "github.com/naoina/toml" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/naoina/toml" "os" "path" "strings" @@ -70,8 +70,11 @@ func GetConfig(rootDir string) cfg.Config { mapConfig.SetDefault("db_backend", "memdb") mapConfig.SetDefault("db_dir", rootDir+"/data") mapConfig.SetDefault("log_level", "debug") + mapConfig.SetDefault("vm_log", true) mapConfig.SetDefault("rpc_laddr", "0.0.0.0:36657") - mapConfig.SetDefault("revisions_file", rootDir+"/revisions") + mapConfig.SetDefault("prof_laddr", "") + mapConfig.SetDefault("revision_file", rootDir+"/revision") + mapConfig.SetDefault("local_routing", false) return mapConfig } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go index 0b4378ee0fe4570c2a74a96d640df4d83a1a84ba..ad79bf52fa43f426c794b1b1810dd28e37e1dfba 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/reactor.go @@ -22,8 +22,6 @@ const ( DataChannel = byte(0x21) VoteChannel = byte(0x22) - PeerStateKey = "ConsensusReactor.peerState" - peerGossipSleepDuration = 100 * time.Millisecond // Time to sleep if there's nothing to send. ) @@ -107,7 +105,7 @@ func (conR *ConsensusReactor) AddPeer(peer *p2p.Peer) { // Create peerState for peer peerState := NewPeerState(peer) - peer.Data.Set(PeerStateKey, peerState) + peer.Data.Set(types.PeerStateKey, peerState) // Begin gossip routines for this peer. go conR.gossipDataRoutine(peer, peerState) @@ -138,7 +136,7 @@ func (conR *ConsensusReactor) Receive(chID byte, peer *p2p.Peer, msgBytes []byte } // Get peer states - ps := peer.Data.Get(PeerStateKey).(*PeerState) + ps := peer.Data.Get(types.PeerStateKey).(*PeerState) _, msg, err := DecodeMessage(msgBytes) if err != nil { log.Warn("Error decoding message", "channel", chID, "peer", peer, "msg", msg, "error", err, "bytes", msgBytes) @@ -455,35 +453,21 @@ OUTER_LOOP: } } // If there are prevotes to send... - if rs.Round == prs.Round && prs.Step <= RoundStepPrevote { - if ps.PickSendVote(rs.Votes.Prevotes(rs.Round)) { - log.Info("Picked rs.Prevotes(rs.Round) to send") - continue OUTER_LOOP - } - } - // If there are precommits to send... - if rs.Round == prs.Round && prs.Step <= RoundStepPrecommit { - if ps.PickSendVote(rs.Votes.Precommits(rs.Round)) { - log.Info("Picked rs.Precommits(rs.Round) to send") - continue OUTER_LOOP - } - } - // If there are prevotes to send for the last round... - if rs.Round == prs.Round+1 && prs.Step <= RoundStepPrevote { + if prs.Step <= RoundStepPrevote && prs.Round != -1 && prs.Round <= rs.Round { if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) { log.Info("Picked rs.Prevotes(prs.Round) to send") continue OUTER_LOOP } } - // If there are precommits to send for the last round... - if rs.Round == prs.Round+1 && prs.Step <= RoundStepPrecommit { + // If there are precommits to send... + if prs.Step <= RoundStepPrecommit && prs.Round != -1 && prs.Round <= rs.Round { if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) { log.Info("Picked rs.Precommits(prs.Round) to send") continue OUTER_LOOP } } // If there are POLPrevotes to send... - if 0 <= prs.ProposalPOLRound { + if prs.ProposalPOLRound != -1 { if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil { if ps.PickSendVote(polPrevotes) { log.Info("Picked rs.Prevotes(prs.ProposalPOLRound) to send") @@ -548,8 +532,8 @@ type PeerRoundState struct { Precommits *BitArray // All precommits peer has for this round LastCommitRound int // Round of commit for last height. -1 if none. LastCommit *BitArray // All commit precommits of commit for last height. - CatchupCommitRound int // Round that we believe commit round is. -1 if none. - CatchupCommit *BitArray // All commit precommits peer has for this height + CatchupCommitRound int // Round that we have commit for. Not necessarily unique. -1 if none. + CatchupCommit *BitArray // All commit precommits peer has for this height & CatchupCommitRound } //----------------------------------------------------------------------------- @@ -588,6 +572,14 @@ func (ps *PeerState) GetRoundState() *PeerRoundState { return &prs } +// Returns an atomic snapshot of the PeerRoundState's height +// used by the mempool to ensure peers are caught up before broadcasting new txs +func (ps *PeerState) GetHeight() int { + ps.mtx.Lock() + defer ps.mtx.Unlock() + return ps.PeerRoundState.Height +} + func (ps *PeerState) SetHasProposal(proposal *types.Proposal) { ps.mtx.Lock() defer ps.mtx.Unlock() @@ -696,14 +688,18 @@ func (ps *PeerState) getVoteBitArray(height, round int, type_ byte) *BitArray { return nil } -// NOTE: 'round' is what we know to be the commit round for height. +// 'round': A round for which we have a +2/3 commit. func (ps *PeerState) ensureCatchupCommitRound(height, round int, numValidators int) { if ps.Height != height { return } - if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round { - PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round)) - } + /* + NOTE: This is wrong, 'round' could change. + e.g. if orig round is not the same as block LastValidation round. + if ps.CatchupCommitRound != -1 && ps.CatchupCommitRound != round { + PanicSanity(Fmt("Conflicting CatchupCommitRound. Height: %v, Orig: %v, New: %v", height, ps.CatchupCommitRound, round)) + } + */ if ps.CatchupCommitRound == round { return // Nothing to do! } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go index 72ec17c6b4bb0df9a0e86900bc755e5f7d941f9c..2f8c5e746880374abe125e4901e65c24bf0b5b98 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/state.go @@ -1308,14 +1308,12 @@ func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSe cs.stagedState.Save() // Update mempool. - cs.mempoolReactor.Mempool.ResetForBlockAndState(block, cs.stagedState) + cs.mempoolReactor.ResetForBlockAndState(block, cs.stagedState) // Fire off event if cs.evsw != nil && cs.evc != nil { - go func(block *types.Block) { - cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block}) - cs.evc.Flush() - }(block) + cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block}) + go cs.evc.Flush() } } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go index eb5ac9391afa748238672187cccd1df2d81e6aba..6c4b7d38a308f037bba8bc03df999417656e9e9f 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus/test.go @@ -8,6 +8,7 @@ import ( bc "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain" dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" mempl "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" @@ -206,6 +207,9 @@ func simpleConsensusState(nValidators int) ([]*ConsensusState, []*types.PrivVali cs := NewConsensusState(state, blockStore, mempoolReactor) cs.SetPrivValidator(privVals[i]) + evsw := events.NewEventSwitch() + cs.SetFireable(evsw) + // read off the NewHeightStep <-cs.NewStepCh() diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go index 587c3ee3f0c70306225280c0c8ae12d5ce771409..66cf9190a9f773a6b432bd379ab9ddcaead54415 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/db/level_db.go @@ -2,9 +2,9 @@ package db import ( "fmt" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/errors" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/opt" "path" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go index c1b580f481742ec2a078a971e329749f5f372140..625b56010117b9dcc1783a339070884b1b2aeae3 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/mempool.go @@ -19,7 +19,7 @@ type Mempool struct { mtx sync.Mutex state *sm.State cache *sm.BlockCache - txs []types.Tx + txs []types.Tx // TODO: we need to add a map to facilitate replace-by-fee } func NewMempool(state *sm.State) *Mempool { @@ -37,6 +37,12 @@ func (mem *Mempool) GetCache() *sm.BlockCache { return mem.cache } +func (mem *Mempool) GetHeight() int { + mem.mtx.Lock() + defer mem.mtx.Unlock() + return mem.state.LastBlockHeight +} + // Apply tx to the state and remember it. func (mem *Mempool) AddTx(tx types.Tx) (err error) { mem.mtx.Lock() @@ -59,11 +65,23 @@ func (mem *Mempool) GetProposalTxs() []types.Tx { return mem.txs } +// We use this to inform peer routines of how the mempool has been updated +type ResetInfo struct { + Height int + Included []Range + Invalid []Range +} + +type Range struct { + Start int + Length int +} + // "block" is the new block being committed. // "state" is the result of state.AppendBlock("block"). // Txs that are present in "block" are discarded from mempool. // Txs that have become invalid in the new "state" are also discarded. -func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) { +func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) ResetInfo { mem.mtx.Lock() defer mem.mtx.Unlock() mem.state = state.Copy() @@ -75,33 +93,51 @@ func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) { blockTxsMap[string(types.TxID(state.ChainID, tx))] = struct{}{} } - // Next, filter all txs from mem.txs that are in blockTxsMap - txs := []types.Tx{} - for _, tx := range mem.txs { + // Now we filter all txs from mem.txs that are in blockTxsMap, + // and ExecTx on what remains. Only valid txs are kept. + // We track the ranges of txs included in the block and invalidated by it + // so we can tell peer routines + var ri = ResetInfo{Height: block.Height} + var validTxs []types.Tx + includedStart, invalidStart := -1, -1 + for i, tx := range mem.txs { txID := types.TxID(state.ChainID, tx) if _, ok := blockTxsMap[string(txID)]; ok { + startRange(&includedStart, i) // start counting included txs + endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs log.Info("Filter out, already committed", "tx", tx, "txID", txID) - continue - } else { - log.Info("Filter in, still new", "tx", tx, "txID", txID) - txs = append(txs, tx) - } - } - - // Next, filter all txs that aren't valid given new state. - validTxs := []types.Tx{} - for _, tx := range txs { - err := sm.ExecTx(mem.cache, tx, false, nil) - if err == nil { - log.Info("Filter in, valid", "tx", tx) - validTxs = append(validTxs, tx) } else { - // tx is no longer valid. - log.Info("Filter out, no longer valid", "tx", tx, "error", err) + endRange(&includedStart, i, &ri.Included) // stop counting included txs + err := sm.ExecTx(mem.cache, tx, false, nil) + if err != nil { + startRange(&invalidStart, i) // start counting invalid txs + log.Info("Filter out, no longer valid", "tx", tx, "error", err) + } else { + endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs + log.Info("Filter in, new, valid", "tx", tx, "txID", txID) + validTxs = append(validTxs, tx) + } } } + endRange(&includedStart, len(mem.txs)-1, &ri.Included) // stop counting included txs + endRange(&invalidStart, len(mem.txs)-1, &ri.Invalid) // stop counting invalid txs // We're done! log.Info("New txs", "txs", validTxs, "oldTxs", mem.txs) mem.txs = validTxs + return ri +} + +func startRange(start *int, i int) { + if *start < 0 { + *start = i + } +} + +func endRange(start *int, i int, ranger *[]Range) { + if *start >= 0 { + length := i - *start + *ranger = append(*ranger, Range{*start, length}) + *start = -1 + } } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go index fb3ff7d74cb6b7eaa235a5868fc0c527a2884b6c..01d714666a0c45a0432eff26bf6643e689470e1d 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool/reactor.go @@ -2,18 +2,25 @@ package mempool import ( "bytes" + "errors" "fmt" "reflect" + "time" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" + sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" ) var ( MempoolChannel = byte(0x30) + + checkExecutedTxsMilliseconds = 1 // check for new mempool txs to send to peer + txsToSendPerCheck = 64 // send up to this many txs from the mempool per check + newBlockChCapacity = 100 // queue to process this many ResetInfos per peer ) // MempoolReactor handles mempool tx broadcasting amongst peers. @@ -44,11 +51,17 @@ func (memR *MempoolReactor) GetChannels() []*p2p.ChannelDescriptor { } // Implements Reactor -func (pexR *MempoolReactor) AddPeer(peer *p2p.Peer) { +func (memR *MempoolReactor) AddPeer(peer *p2p.Peer) { + // Each peer gets a go routine on which we broadcast transactions in the same order we applied them to our state. + newBlockChan := make(chan ResetInfo, newBlockChCapacity) + peer.Data.Set(types.PeerMempoolChKey, newBlockChan) + timer := time.NewTicker(time.Millisecond * time.Duration(checkExecutedTxsMilliseconds)) + go memR.broadcastTxRoutine(timer.C, newBlockChan, peer) } // Implements Reactor -func (pexR *MempoolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) { +func (memR *MempoolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) { + // broadcast routine checks if peer is gone and returns } // Implements Reactor @@ -70,29 +83,128 @@ func (memR *MempoolReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) { } else { log.Info("Added valid tx", "tx", msg.Tx) } - // Share tx. - // We use a simple shotgun approach for now. - // TODO: improve efficiency - for _, peer := range memR.Switch.Peers().List() { - if peer.Key == src.Key { + // broadcasting happens from go routines per peer + default: + log.Warn(Fmt("Unknown message type %v", reflect.TypeOf(msg))) + } +} + +// "block" is the new block being committed. +// "state" is the result of state.AppendBlock("block"). +// Txs that are present in "block" are discarded from mempool. +// Txs that have become invalid in the new "state" are also discarded. +func (memR *MempoolReactor) ResetForBlockAndState(block *types.Block, state *sm.State) { + ri := memR.Mempool.ResetForBlockAndState(block, state) + for _, peer := range memR.Switch.Peers().List() { + peerMempoolCh := peer.Data.Get(types.PeerMempoolChKey).(chan ResetInfo) + select { + case peerMempoolCh <- ri: + default: + memR.Switch.StopPeerForError(peer, errors.New("Peer's mempool push channel full")) + } + } +} + +// Just an alias for AddTx since broadcasting happens in peer routines +func (memR *MempoolReactor) BroadcastTx(tx types.Tx) error { + return memR.Mempool.AddTx(tx) +} + +type PeerState interface { + GetHeight() int +} + +type Peer interface { + IsRunning() bool + Send(byte, interface{}) bool + Get(string) interface{} +} + +// send new mempool txs to peer, strictly in order we applied them to our state. +// new blocks take chunks out of the mempool, but we've already sent some txs to the peer. +// so we wait to hear that the peer has progressed to the new height, and then continue sending txs from where we left off +func (memR *MempoolReactor) broadcastTxRoutine(tickerChan <-chan time.Time, newBlockChan chan ResetInfo, peer Peer) { + var height = memR.Mempool.GetHeight() + var txsSent int // new txs sent for height. (reset every new height) + + for { + select { + case <-tickerChan: + if !peer.IsRunning() { + return + } + + // make sure the peer is up to date + if peerState_i := peer.Get(types.PeerStateKey); peerState_i != nil { + peerState := peerState_i.(PeerState) + if peerState.GetHeight() < height { + continue + } + } else { continue } - peer.TrySend(MempoolChannel, msg) + + // check the mempool for new transactions + newTxs := memR.getNewTxs(height) + txsSentLoop := 0 + start := time.Now() + + TX_LOOP: + for i := txsSent; i < len(newTxs) && txsSentLoop < txsToSendPerCheck; i++ { + tx := newTxs[i] + msg := &TxMessage{Tx: tx} + success := peer.Send(MempoolChannel, msg) + if !success { + break TX_LOOP + } else { + txsSentLoop += 1 + } + } + + if txsSentLoop > 0 { + txsSent += txsSentLoop + log.Info("Sent txs to peer", "txsSentLoop", txsSentLoop, + "took", time.Since(start), "txsSent", txsSent, "newTxs", len(newTxs)) + } + + case ri := <-newBlockChan: + height = ri.Height + + // find out how many txs below what we've sent were included in a block and how many became invalid + included := tallyRangesUpTo(ri.Included, txsSent) + invalidated := tallyRangesUpTo(ri.Invalid, txsSent) + + txsSent -= included + invalidated } + } +} - default: - log.Warn(Fmt("Unknown message type %v", reflect.TypeOf(msg))) +// fetch new txs from the mempool +func (memR *MempoolReactor) getNewTxs(height int) (txs []types.Tx) { + memR.Mempool.mtx.Lock() + defer memR.Mempool.mtx.Unlock() + + // if the mempool got ahead of us just return empty txs + if memR.Mempool.state.LastBlockHeight != height { + return } + return memR.Mempool.txs } -func (memR *MempoolReactor) BroadcastTx(tx types.Tx) error { - err := memR.Mempool.AddTx(tx) - if err != nil { - return err +// return the size of ranges less than upTo +func tallyRangesUpTo(ranger []Range, upTo int) int { + totalUpTo := 0 + for _, r := range ranger { + if r.Start >= upTo { + break + } + if r.Start+r.Length >= upTo { + totalUpTo += upTo - r.Start + break + } + totalUpTo += r.Length } - msg := &TxMessage{Tx: tx} - memR.Switch.Broadcast(MempoolChannel, msg) - return nil + return totalUpTo } // implements events.Eventable diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go index c30a958ce03dbcf8b1912a8c3b17693dd0f64f9e..92ef5aafe25004bff6f5711ea6006377c56f017d 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go @@ -5,7 +5,6 @@ import ( "math/rand" "net" "net/http" - "os" "strconv" "strings" "time" @@ -24,6 +23,7 @@ import ( sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" ) @@ -75,18 +75,8 @@ func NewNode() *Node { config.Set("chain_id", state.ChainID) // Get PrivValidator - var privValidator *types.PrivValidator privValidatorFile := config.GetString("priv_validator_file") - if _, err := os.Stat(privValidatorFile); err == nil { - privValidator = types.LoadPrivValidator(privValidatorFile) - log.Notice("Loaded PrivValidator", - "file", privValidatorFile, "privValidator", privValidator) - } else { - privValidator = types.GenPrivValidator() - privValidator.SetFile(privValidatorFile) - privValidator.Save() - log.Notice("Generated PrivValidator", "file", privValidatorFile) - } + privValidator := types.LoadOrGenPrivValidator(privValidatorFile) // Generate node PrivKey privKey := acm.GenPrivKeyEd25519() @@ -127,6 +117,17 @@ func NewNode() *Node { // they should all satisfy events.Eventable SetFireable(eventSwitch, pexReactor, bcReactor, mempoolReactor, consensusReactor) + // run the profile server + profileHost := config.GetString("prof_laddr") + if profileHost != "" { + go func() { + log.Warn("Profile server", "error", http.ListenAndServe(profileHost, nil)) + }() + } + + // set vm log level + vm.SetDebug(config.GetBool("vm_log")) + return &Node{ sw: sw, evsw: eventSwitch, @@ -256,7 +257,7 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo { } // include git hash in the nodeInfo if available - if rev, err := ReadFile(config.GetString("revisions_file")); err == nil { + if rev, err := ReadFile(config.GetString("revision_file")); err == nil { nodeInfo.Version.Revision = string(rev) } @@ -286,6 +287,19 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo { //------------------------------------------------------------------------------ func RunNode() { + + // Wait until the genesis doc becomes available + genDocFile := config.GetString("genesis_file") + if !FileExists(genDocFile) { + log.Notice(Fmt("Waiting for genesis file %v...", genDocFile)) + for { + time.Sleep(time.Second) + if FileExists(genDocFile) { + break + } + } + } + // Create & start node n := NewNode() l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr")) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go index 8588ff73b82a3f2276698b1f8127a652f726e5c6..983cda622219e16c1c680dfb0e5b5d62ba254840 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/netaddress.go @@ -110,6 +110,10 @@ func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { } func (na *NetAddress) Routable() bool { + if config.GetBool("local_routing") { + return na.Valid() + } + // TODO(oga) bitcoind doesn't include RFC3849 here, but should we? return na.Valid() && !(na.RFC1918() || na.RFC3927() || na.RFC4862() || na.RFC4193() || na.RFC4843() || na.Local()) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go index 82ff986b917618ac1f9b5c5e74a27e522d3e2570..7b291f80371e69647de9ca4b87e3be741f9f0d20 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/peer.go @@ -128,3 +128,7 @@ func (p *Peer) String() string { func (p *Peer) Equals(other *Peer) bool { return p.Key == other.Key } + +func (p *Peer) Get(key string) interface{} { + return p.Data.Get(key) +} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go index d0f3a71e52bd4e7d1aac6f6a68769331137014c4..4bec4e620a86cf98da448f49724155cff80e8bc4 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/consensus.go @@ -31,7 +31,7 @@ func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) { peerRoundStates := []string{} for _, peer := range p2pSwitch.Peers().List() { // TODO: clean this up? - peerState := peer.Data.Get(cm.PeerStateKey).(*cm.PeerState) + peerState := peer.Data.Get(types.PeerStateKey).(*cm.PeerState) peerRoundState := peerState.GetRoundState() peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState)) peerRoundStates = append(peerRoundStates, peerRoundStateStr) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go index 61cd4b95ed0e592c09531515e7370db77e9c0039..c2c7f95f0842c6b095623332cc293955132b9a8d 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/mempool.go @@ -30,5 +30,6 @@ func BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { } func ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) { - return &ctypes.ResultListUnconfirmedTxs{mempoolReactor.Mempool.GetProposalTxs()}, nil + txs := mempoolReactor.Mempool.GetProposalTxs() + return &ctypes.ResultListUnconfirmedTxs{len(txs), txs}, nil } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go index bfc35523094de0ec21731046fac236a28fc845d3..45d4a2f305d1854efc5a612761465045e4cf3cfc 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types/responses.go @@ -98,6 +98,7 @@ type Receipt struct { } type ResultListUnconfirmedTxs struct { + N int `json:"n_txs"` Txs []types.Tx `json:"txs"` } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go index 2ca57bc7b9b8eaa4bbd6b3188f507861486b06bd..e150e001af96fe692ecbbfef864a58c58eba62be 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core_client/ws_client.go @@ -5,11 +5,11 @@ import ( "strings" "time" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" - "github.com/gorilla/websocket" ) const ( diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go index 51473b2def1705a142eb6d0fddc6ed0e26803d11..b57be3057caaad545faa161a4585abc2f1a54aee 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/server/handlers.go @@ -11,13 +11,13 @@ import ( "sort" "time" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" - "github.com/gorilla/websocket" ) func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc) { diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go index fce8b1332b40cb1891dbde38ad84a32cd0196c09..bce4efe6b43173efc0deaf700027edfe8b141383 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/test/ws_helpers.go @@ -7,12 +7,12 @@ import ( "testing" "time" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/gorilla/websocket" _ "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test" ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" - "github.com/gorilla/websocket" ) //-------------------------------------------------------------------------------- diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go index 4abbc242e6481bca9515cec4a7c6372d13e9d3e1..a5cfc458bde8ff1361aaa3202f910eea77614cbb 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/state.go @@ -473,3 +473,11 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State { nameReg: nameReg, } } + +func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) { + db := dbm.NewMemDB() + genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded) + s0 := MakeGenesisState(db, genDoc) + s0.Save() + return s0, privAccounts, privValidators +} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go deleted file mode 100644 index ca6eae68c62a593e0d0292a26d5edb59a7a604f3..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/test.go +++ /dev/null @@ -1,76 +0,0 @@ -package state - -import ( - "sort" - "time" - - acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" - . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" - dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db" - ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" - . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" - "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" -) - -func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) { - privAccount := acm.GenPrivAccount() - perms := ptypes.DefaultAccountPermissions - acc := &acm.Account{ - Address: privAccount.PubKey.Address(), - PubKey: privAccount.PubKey, - Sequence: RandInt(), - Balance: minBalance, - Permissions: perms, - } - if randBalance { - acc.Balance += int64(RandUint32()) - } - return acc, privAccount -} - -func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) { - accounts := make([]GenesisAccount, numAccounts) - privAccounts := make([]*acm.PrivAccount, numAccounts) - defaultPerms := ptypes.DefaultAccountPermissions - for i := 0; i < numAccounts; i++ { - account, privAccount := RandAccount(randBalance, minBalance) - accounts[i] = GenesisAccount{ - Address: account.Address, - Amount: account.Balance, - Permissions: &defaultPerms, // This will get copied into each state.Account. - } - privAccounts[i] = privAccount - } - validators := make([]GenesisValidator, numValidators) - privValidators := make([]*types.PrivValidator, numValidators) - for i := 0; i < numValidators; i++ { - valInfo, _, privVal := types.RandValidator(randBonded, minBonded) - validators[i] = GenesisValidator{ - PubKey: valInfo.PubKey, - Amount: valInfo.FirstBondAmount, - UnbondTo: []BasicAccount{ - { - Address: valInfo.PubKey.Address(), - Amount: valInfo.FirstBondAmount, - }, - }, - } - privValidators[i] = privVal - } - sort.Sort(types.PrivValidatorsByAddress(privValidators)) - return &GenesisDoc{ - GenesisTime: time.Now(), - ChainID: "tendermint_test", - Accounts: accounts, - Validators: validators, - }, privAccounts, privValidators - -} - -func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) { - db := dbm.NewMemDB() - genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded) - s0 := MakeGenesisState(db, genDoc) - s0.Save() - return s0, privAccounts, privValidators -} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go index ef6544925948eab6ddaad9b681f4331bf2454cfa..ee8e96a058a61d51211cbed37de5a33b8a6b619f 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/tx_cache_test.go @@ -4,11 +4,12 @@ import ( "bytes" "testing" + stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" ) func TestStateToFromVMAccount(t *testing.T) { - acmAcc1, _ := RandAccount(true, 456) + acmAcc1, _ := stypes.RandAccount(true, 456) vmAcc := toVMAccount(acmAcc1) acmAcc2 := toStateAccount(vmAcc) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go index ed90b01bf6623ac4079194db7876d513480b9aef..d850fcb1a3a877b83384808fa3f4b449d2d551c4 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types/genesis.go @@ -1,11 +1,13 @@ package types import ( + "sort" "time" acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" ) @@ -59,3 +61,61 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) { } return } + +//------------------------------------------------------------ +// Make random genesis state + +func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) { + privAccount := acm.GenPrivAccount() + perms := ptypes.DefaultAccountPermissions + acc := &acm.Account{ + Address: privAccount.PubKey.Address(), + PubKey: privAccount.PubKey, + Sequence: RandInt(), + Balance: minBalance, + Permissions: perms, + } + if randBalance { + acc.Balance += int64(RandUint32()) + } + return acc, privAccount +} + +func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) { + accounts := make([]GenesisAccount, numAccounts) + privAccounts := make([]*acm.PrivAccount, numAccounts) + defaultPerms := ptypes.DefaultAccountPermissions + for i := 0; i < numAccounts; i++ { + account, privAccount := RandAccount(randBalance, minBalance) + accounts[i] = GenesisAccount{ + Address: account.Address, + Amount: account.Balance, + Permissions: &defaultPerms, // This will get copied into each state.Account. + } + privAccounts[i] = privAccount + } + validators := make([]GenesisValidator, numValidators) + privValidators := make([]*types.PrivValidator, numValidators) + for i := 0; i < numValidators; i++ { + valInfo, _, privVal := types.RandValidator(randBonded, minBonded) + validators[i] = GenesisValidator{ + PubKey: valInfo.PubKey, + Amount: valInfo.FirstBondAmount, + UnbondTo: []BasicAccount{ + { + Address: valInfo.PubKey.Address(), + Amount: valInfo.FirstBondAmount, + }, + }, + } + privValidators[i] = privVal + } + sort.Sort(types.PrivValidatorsByAddress(privValidators)) + return &GenesisDoc{ + GenesisTime: time.Now(), + ChainID: "tendermint_test", + Accounts: accounts, + Validators: validators, + }, privAccounts, privValidators + +} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go index e548a5779c46c7e2515bd67355705f4ee9613250..8e320cba28f249fc9c44e357f474ab21273773fe 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go @@ -19,7 +19,7 @@ type NodeInfo struct { type Versions struct { Revision string `json:"revision"` - Tendermint string `json"tendermint"` + Tendermint string `json:"tendermint"` P2P string `json:"p2p"` RPC string `json:"rpc"` Wire string `json:"wire"` diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go index aad8d118c9561fd4931e89b77f71fbef5036154b..e97befbcbbc6dd39e07a87e711b084082f1fcf9c 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "math" + "os" "sync" acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" @@ -79,6 +80,21 @@ func LoadPrivValidator(filePath string) *PrivValidator { return privVal } +func LoadOrGenPrivValidator(filePath string) *PrivValidator { + var privValidator *PrivValidator + if _, err := os.Stat(filePath); err == nil { + privValidator = LoadPrivValidator(filePath) + log.Notice("Loaded PrivValidator", + "file", filePath, "privValidator", privValidator) + } else { + privValidator = GenPrivValidator() + privValidator.SetFile(filePath) + privValidator.Save() + log.Notice("Generated PrivValidator", "file", filePath) + } + return privValidator +} + func (privVal *PrivValidator) SetFile(filePath string) { privVal.mtx.Lock() defer privVal.mtx.Unlock() diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go index e6d572ab693c61ada3ff4f8615e8bbbb1a265bfe..ff2534e518f3e371fda0c96c0b23b53acfebbf0d 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/tx.go @@ -4,7 +4,9 @@ import ( "encoding/json" "errors" "io" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/ripemd160" + acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go index a1c551e9202f7b7fcf16fdaadd8b42ab143c7f5e..4aaa772fc0ca4d85ed34912f2260cdcf96083c7f 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/vote_set.go @@ -204,6 +204,9 @@ func (voteSet *VoteSet) IsCommit() bool { if voteSet == nil { return false } + if voteSet.type_ != VoteTypePrecommit { + return false + } voteSet.mtx.Lock() defer voteSet.mtx.Unlock() return len(voteSet.maj23Hash) > 0 diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go index 38ce23f7919d9bf453d2e40945314ef0a6b5825a..410d433ef0994a5e26ec7c154e2e381bd98b95bf 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/vm.go @@ -36,15 +36,20 @@ func (err ErrPermission) Error() string { return fmt.Sprintf("Contract does not have permission to %s", err.typ) } -type Debug bool - const ( - dataStackCapacity = 1024 - callStackCapacity = 100 // TODO ensure usage. - memoryCapacity = 1024 * 1024 // 1 MB - dbg Debug = true + dataStackCapacity = 1024 + callStackCapacity = 100 // TODO ensure usage. + memoryCapacity = 1024 * 1024 // 1 MB ) +type Debug bool + +var dbg Debug + +func SetDebug(d bool) { + dbg = Debug(d) +} + func (d Debug) Printf(s string, a ...interface{}) { if d { fmt.Printf(s, a...) @@ -109,6 +114,8 @@ func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *A } // CONTRACT appState is aware of caller and callee, so we can just mutate them. +// CONTRACT code and input are not mutated. +// CONTRACT returned 'ret' is a new compact slice. // value: To be transferred from caller to callee. Refunded upon error. // gas: Available gas. No refunds for gas. // code: May be nil, since the CALL opcode may be used to send value from contracts to accounts @@ -691,6 +698,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } + data = copyslice(data) if vm.evc != nil { eventID := types.EventStringLogEvent(callee.Address.Postfix(20)) fmt.Printf("eventID: %s\n", eventID) @@ -724,11 +732,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas newAccount := vm.appState.CreateAccount(callee) // Run the input to get the contract code. + // NOTE: no need to copy 'input' as per Call contract. ret, err_ := vm.Call(callee, newAccount, input, input, contractValue, gas) if err_ != nil { stack.Push(Zero256) } else { - newAccount.Code = ret // Set the code + newAccount.Code = ret // Set the code (ret need not be copied as per Call contract) stack.Push(newAccount.Address) } @@ -747,6 +756,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas if !ok { return nil, firstErr(err, ErrMemoryOutOfBounds) } + args = copyslice(args) // Ensure that gasLimit is reasonable if *gas < gasLimit { @@ -827,7 +837,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas return nil, firstErr(err, ErrMemoryOutOfBounds) } dbg.Printf(" => [%v, %v] (%d) 0x%X\n", offset, size, len(ret), ret) - return ret, nil + output = copyslice(ret) + return output, nil case SUICIDE: // 0xFF addr := stack.Pop() @@ -870,10 +881,15 @@ func subslice(data []byte, offset, length int64) (ret []byte, ok bool) { } else { ret, ok = data[offset:offset+length], true } - return } +func copyslice(src []byte) (dest []byte) { + dest = make([]byte, len(src)) + copy(dest, src) + return dest +} + func rightMostBytes(data []byte, n int) []byte { size := MinInt(len(data), n) offset := len(data) - size diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go index a940f516926f7d99847410cec8a582d5e0d3da1c..05868b65ca1572d12c1dde0a9301ec795a12ea58 100644 --- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go +++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go @@ -18,9 +18,9 @@ This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html. package box import ( - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/curve25519" - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox" - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/curve25519" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa" "io" ) diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go index 5d48f3b0a65d7d84c2b8fcceb36c48d04ac96482..dbae504ecf475d63ca29a46ec0a8b50b67b9b07c 100644 --- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go +++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go @@ -10,7 +10,7 @@ import ( "encoding/hex" "testing" - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/curve25519" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/curve25519" ) func TestSealOpen(t *testing.T) { diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go index fc4a6f5b7d0dae013624b5b870cb3ff67d273e7c..800cc5b5ccfb91a7cbeb974e7d53b5c880e49ae0 100644 --- a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go +++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go @@ -18,8 +18,8 @@ This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html. package secretbox import ( - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/poly1305" - "github.com/tendermint/tendermint/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/poly1305" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa" ) // Overhead is the number of bytes of overhead when boxing a message. diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go index faf67722a0f975f8b60ee314e3ef2b84f0dc1a5f..05345fc5e5fb856499057fef5d1b9ea59bdb69ef 100644 --- a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go +++ b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go @@ -375,7 +375,7 @@ func TestAllocs(t *testing.T) { <-c.Done() }, limit: 8, - gccgoLimit: 13, + gccgoLimit: 15, }, { desc: "WithCancel(bg)", @@ -536,7 +536,7 @@ func testLayers(t *testing.T, seed int64, testTimeout bool) { if testTimeout { select { case <-ctx.Done(): - case <-time.After(timeout + timeout/10): + case <-time.After(timeout + 100*time.Millisecond): errorf("ctx should have timed out") } checkValues("after timeout") diff --git a/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go index ac87e0ee4a9a688622541088d0f77f9d8ffcd03e..c0d5bc2a70f6877a7a5c8cdc9855b5d0f0175ce9 100644 --- a/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go +++ b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go @@ -20,17 +20,20 @@ import ( "sync/atomic" "testing" "time" + + "golang.org/x/net/internal/nettest" ) func TestLimitListener(t *testing.T) { - const ( - max = 5 - num = 200 - ) + const max = 5 + attempts := (nettest.MaxOpenFiles() - max) / 2 + if attempts > 256 { // maximum length of accept queue is 128 by default + attempts = 256 + } l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { - t.Fatalf("Listen: %v", err) + t.Fatal(err) } defer l.Close() l = LimitListener(l, max) @@ -47,14 +50,14 @@ func TestLimitListener(t *testing.T) { var wg sync.WaitGroup var failed int32 - for i := 0; i < num; i++ { + for i := 0; i < attempts; i++ { wg.Add(1) go func() { defer wg.Done() c := http.Client{Timeout: 3 * time.Second} r, err := c.Get("http://" + l.Addr().String()) if err != nil { - t.Logf("Get: %v", err) + t.Log(err) atomic.AddInt32(&failed, 1) return } @@ -66,8 +69,8 @@ func TestLimitListener(t *testing.T) { // We expect some Gets to fail as the kernel's accept queue is filled, // but most should succeed. - if failed >= num/2 { - t.Errorf("too many Gets failed: %v", failed) + if int(failed) >= attempts/2 { + t.Errorf("%d requests failed within %d attempts", failed, attempts) } } diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore index 415902041c853f9d77290ef92c94043b0d30abfc..7e9b50032d207cedcd10de2796dc4203d9889332 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore @@ -23,4 +23,6 @@ _testmain.go *.test *.prof *.test -*.out \ No newline at end of file +*.out +cover.html +README.html \ No newline at end of file diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml deleted file mode 100644 index 68398d9f152d5b07e90a55adc00e5006436e58dd..0000000000000000000000000000000000000000 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -notificaitons: - email: - recipients: bluesuncorp01@gmail.com - on_success: change - on_failure: always - -go: - - 1.2 - - 1.3 - - 1.4 - - tip \ No newline at end of file diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md index c1e9d00cfddae372708ada9681bf588026df55f9..1a78bec3c3f0b07dcb9b7a56083558362817b247 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md @@ -1,33 +1,143 @@ Package validator ================ -[](https://travis-ci.org/bluesuncorp/validator) -[](https://godoc.org/gopkg.in/bluesuncorp/validator.v5) + +[](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[](https://semaphoreci.com/joeybloggs/validator) +[](https://coveralls.io/r/go-playground/validator?branch=v5) +[](https://godoc.org/gopkg.in/go-playground/validator.v5) Package validator implements value validations for structs and individual fields based on tags. -It is also capable of Cross Field and Cross Struct validations. + +It has the following **unique** features: + +- Cross Field and Cross Struct validations. +- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. +- Handles type interface by determining it's underlying type prior to validation. Installation -============ +------------ Use go get. - go get gopkg.in/bluesuncorp/validator.v5 + go get gopkg.in/go-playground/validator.v5 or to update - go get -u gopkg.in/bluesuncorp/validator.v5 + go get -u gopkg.in/go-playground/validator.v5 Then import the validator package into your own code. - import "gopkg.in/bluesuncorp/validator.v5" + import "gopkg.in/go-playground/validator.v5" Usage and documentation -======================= +------ + +Please see http://godoc.org/gopkg.in/go-playground/validator.v5 for detailed usage docs. + +##### Example: +```go +package main + +import ( + "fmt" + + "gopkg.in/go-playground/validator.v5" +) + +// User contains user information +type User struct { + FirstName string `validate:"required"` + LastName string `validate:"required"` + Age uint8 `validate:"gte=0,lte=130"` + Email string `validate:"required,email"` + FavouriteColor string `validate:"hexcolor|rgb|rgba"` + Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... +} + +// Address houses a users address information +type Address struct { + Street string `validate:"required"` + City string `validate:"required"` + Planet string `validate:"required"` + Phone string `validate:"required"` +} + +var validate *validator.Validate + +func main() { + + validate = validator.New("validate", validator.BakedInValidators) + + address := &Address{ + Street: "Eavesdown Docks", + Planet: "Persphone", + Phone: "none", + } + + user := &User{ + FirstName: "Badger", + LastName: "Smith", + Age: 135, + Email: "Badger.Smith@gmail.com", + FavouriteColor: "#000", + Addresses: []*Address{address}, + } + + // returns nil or *StructErrors + errs := validate.Struct(user) + + if errs != nil { + + // err will be of type *FieldError + err := errs.Errors["Age"] + fmt.Println(err.Error()) // output: Field validation for "Age" failed on the "lte" tag + fmt.Println(err.Field) // output: Age + fmt.Println(err.Tag) // output: lte + fmt.Println(err.Kind) // output: uint8 + fmt.Println(err.Type) // output: uint8 + fmt.Println(err.Param) // output: 130 + fmt.Println(err.Value) // output: 135 + + // or if you prefer you can use the Flatten function + // NOTE: I find this usefull when using a more hard static approach of checking field errors. + // The above, is best for passing to some generic code to say parse the errors. i.e. I pass errs + // to a routine which loops through the errors, creates and translates the error message into the + // users locale and returns a map of map[string]string // field and error which I then use + // within the HTML rendering. + + flat := errs.Flatten() + fmt.Println(flat) // output: map[Age:Field validation for "Age" failed on the "lte" tag Addresses[0].Address.City:Field validation for "City" failed on the "required" tag] + err = flat["Addresses[0].Address.City"] + fmt.Println(err.Field) // output: City + fmt.Println(err.Tag) // output: required + fmt.Println(err.Kind) // output: string + fmt.Println(err.Type) // output: string + fmt.Println(err.Param) // output: + fmt.Println(err.Value) // output: + + // from here you can create your own error messages in whatever language you wish + return + } + + // save user to database +} +``` -Please see http://godoc.org/gopkg.in/bluesuncorp/validator.v5 for detailed usage docs. +Benchmarks +------ +###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 +```go +$ go test -cpu=4 -bench=. -benchmem=true +PASS +BenchmarkValidateField-4 3000000 429 ns/op 192 B/op 2 allocs/op +BenchmarkValidateStructSimple-4 500000 2877 ns/op 657 B/op 10 allocs/op +BenchmarkTemplateParallelSimple-4 500000 3097 ns/op 657 B/op 10 allocs/op +BenchmarkValidateStructLarge-4 100000 15228 ns/op 4350 B/op 62 allocs/op +BenchmarkTemplateParallelLarge-4 100000 14257 ns/op 4354 B/op 62 allocs/op +``` How to Contribute -================= +------ There will always be a development branch for each version i.e. `v1-development`. In order to contribute, please make your pull requests against those branches. @@ -40,5 +150,5 @@ I strongly encourage everyone whom creates a custom validation function to contr help make this package even better. License -======= +------ Distributed under MIT License, please see license file in code for more details. diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go index 22746adae10d34f704f7cc9f63203de3264bc4ec..82868ccfd0f09d83819f9d23b86eae002a2e8ce0 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go @@ -424,10 +424,12 @@ func hasValue(top interface{}, current interface{}, field interface{}, param str st := reflect.ValueOf(field) switch st.Kind() { - - case reflect.Slice, reflect.Map, reflect.Array: - return field != nil && int64(st.Len()) > 0 - + case reflect.Invalid: + return false + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: + return !st.IsNil() + case reflect.Array: + return field != reflect.Zero(reflect.TypeOf(field)).Interface() default: return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface() } @@ -592,7 +594,7 @@ func isGte(top interface{}, current interface{}, field interface{}, param string case reflect.String: p := asInt(param) - return int64(len(st.String())) >= p + return int64(utf8.RuneCountInString(st.String())) >= p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) @@ -637,7 +639,7 @@ func isGt(top interface{}, current interface{}, field interface{}, param string) case reflect.String: p := asInt(param) - return int64(len(st.String())) > p + return int64(utf8.RuneCountInString(st.String())) > p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) @@ -681,7 +683,7 @@ func hasLengthOf(top interface{}, current interface{}, field interface{}, param case reflect.String: p := asInt(param) - return int64(len(st.String())) == p + return int64(utf8.RuneCountInString(st.String())) == p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) @@ -875,7 +877,7 @@ func isLte(top interface{}, current interface{}, field interface{}, param string case reflect.String: p := asInt(param) - return int64(len(st.String())) <= p + return int64(utf8.RuneCountInString(st.String())) <= p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) @@ -920,7 +922,7 @@ func isLt(top interface{}, current interface{}, field interface{}, param string) case reflect.String: p := asInt(param) - return int64(len(st.String())) < p + return int64(utf8.RuneCountInString(st.String())) < p case reflect.Slice, reflect.Map, reflect.Array: p := asInt(param) diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go index 25172092b937f1c26596c7adc7551f82bef5fcd8..ee836c288be215917335d3ddb28914e3f3b2426a 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/benchmarks_test.go @@ -24,23 +24,23 @@ func BenchmarkValidateStructSimple(b *testing.B) { } } -// func BenchmarkTemplateParallelSimple(b *testing.B) { +func BenchmarkTemplateParallelSimple(b *testing.B) { -// type Foo struct { -// StringValue string `validate:"min=5,max=10"` -// IntValue int `validate:"min=5,max=10"` -// } + type Foo struct { + StringValue string `validate:"min=5,max=10"` + IntValue int `validate:"min=5,max=10"` + } -// validFoo := &Foo{StringValue: "Foobar", IntValue: 7} -// invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} + validFoo := &Foo{StringValue: "Foobar", IntValue: 7} + invalidFoo := &Foo{StringValue: "Fo", IntValue: 3} -// b.RunParallel(func(pb *testing.PB) { -// for pb.Next() { -// validate.Struct(validFoo) -// validate.Struct(invalidFoo) -// } -// }) -// } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + validate.Struct(validFoo) + validate.Struct(invalidFoo) + } + }) +} func BenchmarkValidateStructLarge(b *testing.B) { @@ -101,63 +101,63 @@ func BenchmarkValidateStructLarge(b *testing.B) { } } -// func BenchmarkTemplateParallelLarge(b *testing.B) { - -// tFail := &TestString{ -// Required: "", -// Len: "", -// Min: "", -// Max: "12345678901", -// MinMax: "", -// Lt: "0123456789", -// Lte: "01234567890", -// Gt: "1", -// Gte: "1", -// OmitEmpty: "12345678901", -// Sub: &SubTest{ -// Test: "", -// }, -// Anonymous: struct { -// A string `validate:"required"` -// }{ -// A: "", -// }, -// Iface: &Impl{ -// F: "12", -// }, -// } - -// tSuccess := &TestString{ -// Required: "Required", -// Len: "length==10", -// Min: "min=1", -// Max: "1234567890", -// MinMax: "12345", -// Lt: "012345678", -// Lte: "0123456789", -// Gt: "01234567890", -// Gte: "0123456789", -// OmitEmpty: "", -// Sub: &SubTest{ -// Test: "1", -// }, -// SubIgnore: &SubTest{ -// Test: "", -// }, -// Anonymous: struct { -// A string `validate:"required"` -// }{ -// A: "1", -// }, -// Iface: &Impl{ -// F: "123", -// }, -// } - -// b.RunParallel(func(pb *testing.PB) { -// for pb.Next() { -// validate.Struct(tSuccess) -// validate.Struct(tFail) -// } -// }) -// } +func BenchmarkTemplateParallelLarge(b *testing.B) { + + tFail := &TestString{ + Required: "", + Len: "", + Min: "", + Max: "12345678901", + MinMax: "", + Lt: "0123456789", + Lte: "01234567890", + Gt: "1", + Gte: "1", + OmitEmpty: "12345678901", + Sub: &SubTest{ + Test: "", + }, + Anonymous: struct { + A string `validate:"required"` + }{ + A: "", + }, + Iface: &Impl{ + F: "12", + }, + } + + tSuccess := &TestString{ + Required: "Required", + Len: "length==10", + Min: "min=1", + Max: "1234567890", + MinMax: "12345", + Lt: "012345678", + Lte: "0123456789", + Gt: "01234567890", + Gte: "0123456789", + OmitEmpty: "", + Sub: &SubTest{ + Test: "1", + }, + SubIgnore: &SubTest{ + Test: "", + }, + Anonymous: struct { + A string `validate:"required"` + }{ + A: "1", + }, + Iface: &Impl{ + F: "123", + }, + } + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + validate.Struct(tSuccess) + validate.Struct(tFail) + } + }) +} diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go index 89142e0751e120d75529a1fd6c785ede43ab057d..74db756f954c5304994be5ed36a62dee4d1f229d 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go @@ -167,16 +167,44 @@ Here is a list of the current built in validators: inside of you program you know the struct will be valid, but need to verify it has been assigned. + exists + Is a special tag without a validation function attached. It is used when a field + is a Pointer, Interface or Invalid and you wish to validate that it exists. + Example: want to ensure a bool exists if you define the bool as a pointer and + use exists it will ensure there is a value; couldn't use required as it would + fail when the bool was false. exists will fail is the value is a Pointer, Interface + or Invalid and is nil. (Usage: exists) + omitempty Allows conditional validation, for example if a field is not set with a value (Determined by the required validator) then other validation such as min or max won't run, but if a value is set validation will run. (Usage: omitempty) + dive + This tells the validator to dive into a slice, array or map and validate that + level of the slice, array or map with the validation tags that follow. + Multidimensional nesting is also supported, each level you wish to dive will + require another dive tag. (Usage: dive) + Example: [][]string with validation tag "gt=0,dive,len=1,dive,required" + gt=0 will be applied to [] + len=1 will be applied to []string + required will be applied to string + Example2: [][]string with validation tag "gt=0,dive,dive,required" + gt=0 will be applied to [] + []string will be spared validation + required will be applied to string + NOTE: in Example2 if the required validation failed, but all others passed + the hierarchy of FieldError's in the middle with have their IsPlaceHolder field + set to true. If a FieldError has IsSliceOrMap=true or IsMap=true then the + FieldError is a Slice or Map field and if IsPlaceHolder=true then contains errors + within its SliceOrArrayErrs or MapErrs fields. + required - This validates that the value is not the data types default value. + This validates that the value is not the data types default zero value. For numbers ensures value is not zero. For strings ensures value is - not "". For slices, arrays, and maps, ensures the length is not zero. + not "". For slices, maps, pointers, interfaces, channels and functions + ensures the value is not nil. (Usage: required) len diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go index c5dd3517d1812ba8559a31783860971df2079555..0acdaa0c2d35a7ead14e7f02e846dd36bd2ea2f1 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/examples_test.go @@ -3,7 +3,7 @@ package validator_test import ( "fmt" - "../validator" + "gopkg.in/go-playground/validator.v5" ) func ExampleValidate_new() { diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go index 5f0c18afa0100c890106b93a0ffa307dc6ec25d4..f195647baed6d1d24c03f8c0c9259cd1b654c74d 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go @@ -20,56 +20,31 @@ import ( ) const ( - utf8HexComma = "0x2C" - tagSeparator = "," - orSeparator = "|" - noValidationTag = "-" - tagKeySeparator = "=" - structOnlyTag = "structonly" - omitempty = "omitempty" - fieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag" - structErrMsg = "Struct:%s\n" + utf8HexComma = "0x2C" + tagSeparator = "," + orSeparator = "|" + noValidationTag = "-" + tagKeySeparator = "=" + structOnlyTag = "structonly" + omitempty = "omitempty" + required = "required" + fieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag" + sliceErrMsg = "Field validation for \"%s\" failed at index \"%d\" with error(s): %s" + mapErrMsg = "Field validation for \"%s\" failed on key \"%v\" with error(s): %s" + structErrMsg = "Struct:%s\n" + diveTag = "dive" + existsTag = "exists" + arrayIndexFieldName = "%s[%d]" + mapIndexFieldName = "%s[%v]" ) -var structPool *pool +var structPool *sync.Pool -// Pool holds a channelStructErrors. -type pool struct { - pool chan *StructErrors -} - -// NewPool creates a new pool of Clients. -func newPool(max int) *pool { - return &pool{ - pool: make(chan *StructErrors, max), - } -} - -// Borrow a StructErrors from the pool. -func (p *pool) Borrow() *StructErrors { - var c *StructErrors - - select { - case c = <-p.pool: - default: - c = &StructErrors{ - Errors: map[string]*FieldError{}, - StructErrors: map[string]*StructErrors{}, - } - } - - return c -} - -// Return returns a StructErrors to the pool. -func (p *pool) Return(c *StructErrors) { - - // c.Struct = "" - - select { - case p.pool <- c: - default: - // let it go, let it go... +// returns new *StructErrors to the pool +func newStructErrors() interface{} { + return &StructErrors{ + Errors: map[string]*FieldError{}, + StructErrors: map[string]*StructErrors{}, } } @@ -79,13 +54,22 @@ type cachedTags struct { } type cachedField struct { - index int - name string - tags []*cachedTags - tag string - kind reflect.Kind - typ reflect.Type - isTime bool + index int + name string + tags []*cachedTags + tag string + kind reflect.Kind + typ reflect.Type + isTime bool + isSliceOrArray bool + isMap bool + isTimeSubtype bool + sliceSubtype reflect.Type + mapSubtype reflect.Type + sliceSubKind reflect.Kind + mapSubKind reflect.Kind + dive bool + diveTag string } type cachedStruct struct { @@ -138,20 +122,123 @@ var fieldsCache = &fieldsCacheMap{m: map[string][]*cachedTags{}} // FieldError contains a single field's validation error along // with other properties that may be needed for error message creation type FieldError struct { - Field string - Tag string - Kind reflect.Kind - Type reflect.Type - Param string - Value interface{} + Field string + Tag string + Kind reflect.Kind + Type reflect.Type + Param string + Value interface{} + IsPlaceholderErr bool + IsSliceOrArray bool + IsMap bool + SliceOrArrayErrs map[int]error // counld be FieldError, StructErrors + MapErrs map[interface{}]error // counld be FieldError, StructErrors } // This is intended for use in development + debugging and not intended to be a production error message. // it also allows FieldError to be used as an Error interface func (e *FieldError) Error() string { + + if e.IsPlaceholderErr { + + buff := bytes.NewBufferString("") + + if e.IsSliceOrArray { + + for j, err := range e.SliceOrArrayErrs { + buff.WriteString("\n") + buff.WriteString(fmt.Sprintf(sliceErrMsg, e.Field, j, "\n"+err.Error())) + } + + } else if e.IsMap { + + for key, err := range e.MapErrs { + buff.WriteString(fmt.Sprintf(mapErrMsg, e.Field, key, "\n"+err.Error())) + } + } + + return strings.TrimSpace(buff.String()) + } + return fmt.Sprintf(fieldErrMsg, e.Field, e.Tag) } +// Flatten flattens the FieldError hierarchical structure into a flat namespace style field name +// for those that want/need it. +// This is now needed because of the new dive functionality +func (e *FieldError) Flatten() map[string]*FieldError { + + errs := map[string]*FieldError{} + + if e.IsPlaceholderErr { + + if e.IsSliceOrArray { + for key, err := range e.SliceOrArrayErrs { + + fe, ok := err.(*FieldError) + + if ok { + + if flat := fe.Flatten(); flat != nil && len(flat) > 0 { + for k, v := range flat { + if fe.IsPlaceholderErr { + errs[fmt.Sprintf("[%#v]%s", key, k)] = v + } else { + errs[fmt.Sprintf("[%#v]", key)] = v + } + + } + } + } else { + + se := err.(*StructErrors) + + if flat := se.Flatten(); flat != nil && len(flat) > 0 { + for k, v := range flat { + errs[fmt.Sprintf("[%#v].%s.%s", key, se.Struct, k)] = v + } + } + } + } + } + + if e.IsMap { + for key, err := range e.MapErrs { + + fe, ok := err.(*FieldError) + + if ok { + + if flat := fe.Flatten(); flat != nil && len(flat) > 0 { + for k, v := range flat { + if fe.IsPlaceholderErr { + errs[fmt.Sprintf("[%#v]%s", key, k)] = v + } else { + errs[fmt.Sprintf("[%#v]", key)] = v + } + } + } + } else { + + se := err.(*StructErrors) + + if flat := se.Flatten(); flat != nil && len(flat) > 0 { + for k, v := range flat { + errs[fmt.Sprintf("[%#v].%s.%s", key, se.Struct, k)] = v + } + } + } + } + } + + return errs + } + + errs[e.Field] = e + + return errs +} + // StructErrors is hierarchical list of field and struct validation errors // for a non hierarchical representation please see the Flatten method for StructErrors type StructErrors struct { @@ -178,7 +265,7 @@ func (e *StructErrors) Error() string { buff.WriteString(err.Error()) } - return buff.String() + return strings.TrimSpace(buff.String()) } // Flatten flattens the StructErrors hierarchical structure into a flat namespace style field name @@ -193,7 +280,17 @@ func (e *StructErrors) Flatten() map[string]*FieldError { for _, f := range e.Errors { - errs[f.Field] = f + if flat := f.Flatten(); flat != nil && len(flat) > 0 { + + for k, fe := range flat { + + if f.IsPlaceholderErr { + errs[f.Field+k] = fe + } else { + errs[k] = fe + } + } + } } for key, val := range e.StructErrors { @@ -231,7 +328,7 @@ type Validate struct { // New creates a new Validate instance for use. func New(tagName string, funcs map[string]Func) *Validate { - structPool = newPool(10) + structPool = &sync.Pool{New: newStructErrors} return &Validate{ tagName: tagName, @@ -251,9 +348,8 @@ func (v *Validate) SetTag(tagName string) { // nearly all cases. only increase if you have a deeply nested struct structure. // NOTE: this method is not thread-safe // NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed -// and the max pool size will be passed into the New function func (v *Validate) SetMaxStructPoolSize(max int) { - structPool = newPool(max) + structPool = &sync.Pool{New: newStructErrors} } // AddFunction adds a validation Func to a Validate's map of validators denoted by the key @@ -312,10 +408,9 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter structName = structType.Name() numFields = structValue.NumField() cs = &cachedStruct{name: structName, children: numFields} - structCache.Set(structType, cs) } - validationErrors := structPool.Borrow() + validationErrors := structPool.Get().(*StructErrors) validationErrors.Struct = structName for i := 0; i < numFields; i++ { @@ -340,7 +435,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter typeField = structType.Field(i) - cField = &cachedField{index: i, tag: typeField.Tag.Get(v.tagName)} + cField = &cachedField{index: i, tag: typeField.Tag.Get(v.tagName), isTime: (valueField.Type() == reflect.TypeOf(time.Time{}) || valueField.Type() == reflect.TypeOf(&time.Time{}))} if cField.tag == noValidationTag { cs.children-- @@ -373,9 +468,7 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter continue } - if cField.isTime || valueField.Type() == reflect.TypeOf(time.Time{}) { - - cField.isTime = true + if cField.isTime { if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil { validationErrors.Errors[fieldError.Field] = fieldError @@ -390,6 +483,62 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter continue } + if (valueField.Kind() == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() { + + if strings.Contains(cField.tag, omitempty) { + goto CACHEFIELD + } + + tags := strings.Split(cField.tag, tagSeparator) + + if len(tags) > 0 { + + var param string + vals := strings.SplitN(tags[0], tagKeySeparator, 2) + + if len(vals) > 1 { + param = vals[1] + } + + validationErrors.Errors[cField.name] = &FieldError{ + Field: cField.name, + Tag: vals[0], + Param: param, + Value: valueField.Interface(), + Kind: valueField.Kind(), + Type: valueField.Type(), + } + + goto CACHEFIELD + } + } + + // if we get here, the field is interface and could be a struct or a field + // and we need to check the inner type and validate + if cField.kind == reflect.Interface { + + valueField = valueField.Elem() + + if valueField.Kind() == reflect.Ptr && !valueField.IsNil() { + valueField = valueField.Elem() + } + + if valueField.Kind() == reflect.Struct { + goto VALIDATESTRUCT + } + + // sending nil for cField as it was type interface and could be anything + // each time and so must be calculated each time and can't be cached reliably + if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, nil); fieldError != nil { + validationErrors.Errors[fieldError.Field] = fieldError + // free up memory reference + fieldError = nil + } + + goto CACHEFIELD + } + + VALIDATESTRUCT: if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil { validationErrors.StructErrors[cField.name] = structErrors // free up memory map no longer needed @@ -397,22 +546,48 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter } } - default: + case reflect.Slice, reflect.Array: + cField.isSliceOrArray = true + cField.sliceSubtype = cField.typ.Elem() + cField.isTimeSubtype = (cField.sliceSubtype == reflect.TypeOf(time.Time{}) || cField.sliceSubtype == reflect.TypeOf(&time.Time{})) + cField.sliceSubKind = cField.sliceSubtype.Kind() if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil { validationErrors.Errors[fieldError.Field] = fieldError // free up memory reference fieldError = nil } + + case reflect.Map: + cField.isMap = true + cField.mapSubtype = cField.typ.Elem() + cField.isTimeSubtype = (cField.mapSubtype == reflect.TypeOf(time.Time{}) || cField.mapSubtype == reflect.TypeOf(&time.Time{})) + cField.mapSubKind = cField.mapSubtype.Kind() + + if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil { + validationErrors.Errors[fieldError.Field] = fieldError + // free up memory reference + fieldError = nil + } + + default: + if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil { + validationErrors.Errors[fieldError.Field] = fieldError + // free up memory reference + fieldError = nil + } } + CACHEFIELD: if !isCached { cs.fields = append(cs.fields, cField) } } + structCache.Set(structType, cs) + if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 { - structPool.Return(validationErrors) + structPool.Put(validationErrors) return nil } @@ -421,13 +596,11 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter // Field allows validation of a single field, still using tag style validation to check multiple errors func (v *Validate) Field(f interface{}, tag string) *FieldError { - return v.FieldWithValue(nil, f, tag) } // FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors func (v *Validate) FieldWithValue(val interface{}, f interface{}, tag string) *FieldError { - return v.fieldWithNameAndValue(nil, val, f, tag, "", true, nil) } @@ -435,9 +608,10 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f var cField *cachedField var isCached bool + var valueField reflect.Value // This is a double check if coming from validate.Struct but need to be here in case function is called directly - if tag == noValidationTag { + if tag == noValidationTag || tag == "" { return nil } @@ -445,25 +619,51 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f return nil } + valueField = reflect.ValueOf(f) + if cacheField == nil { - valueField := reflect.ValueOf(f) if valueField.Kind() == reflect.Ptr && !valueField.IsNil() { valueField = valueField.Elem() f = valueField.Interface() } - cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag, typ: valueField.Type()} + cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag} + + if cField.kind != reflect.Invalid { + cField.typ = valueField.Type() + } + + switch cField.kind { + case reflect.Slice, reflect.Array: + isSingleField = false // cached tags mean nothing because it will be split up while diving + cField.isSliceOrArray = true + cField.sliceSubtype = cField.typ.Elem() + cField.isTimeSubtype = (cField.sliceSubtype == reflect.TypeOf(time.Time{}) || cField.sliceSubtype == reflect.TypeOf(&time.Time{})) + cField.sliceSubKind = cField.sliceSubtype.Kind() + case reflect.Map: + isSingleField = false // cached tags mean nothing because it will be split up while diving + cField.isMap = true + cField.mapSubtype = cField.typ.Elem() + cField.isTimeSubtype = (cField.mapSubtype == reflect.TypeOf(time.Time{}) || cField.mapSubtype == reflect.TypeOf(&time.Time{})) + cField.mapSubKind = cField.mapSubtype.Kind() + } } else { cField = cacheField } switch cField.kind { + case reflect.Invalid: + return &FieldError{ + Field: cField.name, + Tag: cField.tag, + Kind: cField.kind, + } - case reflect.Struct, reflect.Interface, reflect.Invalid: + case reflect.Struct, reflect.Interface: if cField.typ != reflect.TypeOf(time.Time{}) { - panic("Invalid field passed to ValidateFieldWithTag") + panic("Invalid field passed to fieldWithNameAndValue") } } @@ -477,6 +677,13 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f for _, t := range strings.Split(tag, tagSeparator) { + if t == diveTag { + + cField.dive = true + cField.diveTag = strings.TrimLeft(strings.SplitN(tag, diveTag, 2)[1], ",") + break + } + orVals := strings.Split(t, orSeparator) cTag := &cachedTags{isOrVal: len(orVals) > 1, keyVals: make([][]string, len(orVals))} cField.tags = append(cField.tags, cTag) @@ -516,7 +723,22 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f for _, val := range cTag.keyVals { + // if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() { + // if val[0] == existsTag { + // if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() { + // fieldErr = &FieldError{ + // Field: name, + // Tag: val[0], + // Value: f, + // Param: val[1], + // } + // err = errors.New(fieldErr.Tag) + // } + + // } else { + fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, val[0], val[1], name) + // } if err == nil { return nil @@ -534,6 +756,18 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f return fieldErr } + if cTag.keyVals[0][0] == existsTag { + if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() { + return &FieldError{ + Field: name, + Tag: cTag.keyVals[0][0], + Value: f, + Param: cTag.keyVals[0][1], + } + } + continue + } + if fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, cTag.keyVals[0][0], cTag.keyVals[0][1], name); err != nil { fieldErr.Kind = cField.kind @@ -543,9 +777,231 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f } } + if cField.dive { + + if cField.isSliceOrArray { + + if errs := v.traverseSliceOrArray(val, current, valueField, cField); errs != nil && len(errs) > 0 { + + return &FieldError{ + Field: cField.name, + Kind: cField.kind, + Type: cField.typ, + Value: f, + IsPlaceholderErr: true, + IsSliceOrArray: true, + SliceOrArrayErrs: errs, + } + } + + } else if cField.isMap { + if errs := v.traverseMap(val, current, valueField, cField); errs != nil && len(errs) > 0 { + + return &FieldError{ + Field: cField.name, + Kind: cField.kind, + Type: cField.typ, + Value: f, + IsPlaceholderErr: true, + IsMap: true, + MapErrs: errs, + } + } + } else { + // throw error, if not a slice or map then should not have gotten here + panic("dive error! can't dive on a non slice or map") + } + } + return nil } +func (v *Validate) traverseMap(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[interface{}]error { + + errs := map[interface{}]error{} + + for _, key := range valueField.MapKeys() { + + idxField := valueField.MapIndex(key) + + if cField.mapSubKind == reflect.Ptr && !idxField.IsNil() { + idxField = idxField.Elem() + cField.mapSubKind = idxField.Kind() + } + + switch cField.mapSubKind { + case reflect.Struct, reflect.Interface: + + if cField.isTimeSubtype { + + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil { + errs[key.Interface()] = fieldError + } + + continue + } + + if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() { + + if strings.Contains(cField.diveTag, omitempty) { + continue + } + + tags := strings.Split(cField.diveTag, tagSeparator) + + if len(tags) > 0 { + + var param string + vals := strings.SplitN(tags[0], tagKeySeparator, 2) + + if len(vals) > 1 { + param = vals[1] + } + + errs[key.Interface()] = &FieldError{ + Field: fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), + Tag: vals[0], + Param: param, + Value: idxField.Interface(), + Kind: idxField.Kind(), + Type: cField.mapSubtype, + } + } + + continue + } + + // if we get here, the field is interface and could be a struct or a field + // and we need to check the inner type and validate + if idxField.Kind() == reflect.Interface { + + idxField = idxField.Elem() + + if idxField.Kind() == reflect.Ptr && !idxField.IsNil() { + idxField = idxField.Elem() + } + + if idxField.Kind() == reflect.Struct { + goto VALIDATESTRUCT + } + + // sending nil for cField as it was type interface and could be anything + // each time and so must be calculated each time and can't be cached reliably + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil { + errs[key.Interface()] = fieldError + } + + continue + } + + VALIDATESTRUCT: + if structErrors := v.structRecursive(val, current, idxField.Interface()); structErrors != nil { + errs[key.Interface()] = structErrors + } + + default: + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(mapIndexFieldName, cField.name, key.Interface()), false, nil); fieldError != nil { + errs[key.Interface()] = fieldError + } + } + } + + return errs +} + +func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[int]error { + + errs := map[int]error{} + + for i := 0; i < valueField.Len(); i++ { + + idxField := valueField.Index(i) + + if cField.sliceSubKind == reflect.Ptr && !idxField.IsNil() { + idxField = idxField.Elem() + cField.sliceSubKind = idxField.Kind() + } + + switch cField.sliceSubKind { + case reflect.Struct, reflect.Interface: + + if cField.isTimeSubtype { + + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil { + errs[i] = fieldError + } + + continue + } + + if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() { + + if strings.Contains(cField.diveTag, omitempty) { + continue + } + + tags := strings.Split(cField.diveTag, tagSeparator) + + if len(tags) > 0 { + + var param string + vals := strings.SplitN(tags[0], tagKeySeparator, 2) + + if len(vals) > 1 { + param = vals[1] + } + + errs[i] = &FieldError{ + Field: fmt.Sprintf(arrayIndexFieldName, cField.name, i), + Tag: vals[0], + Param: param, + Value: idxField.Interface(), + Kind: idxField.Kind(), + Type: cField.sliceSubtype, + } + } + + continue + } + + // if we get here, the field is interface and could be a struct or a field + // and we need to check the inner type and validate + if idxField.Kind() == reflect.Interface { + + idxField = idxField.Elem() + + if idxField.Kind() == reflect.Ptr && !idxField.IsNil() { + idxField = idxField.Elem() + } + + if idxField.Kind() == reflect.Struct { + goto VALIDATESTRUCT + } + + // sending nil for cField as it was type interface and could be anything + // each time and so must be calculated each time and can't be cached reliably + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil { + errs[i] = fieldError + } + + continue + } + + VALIDATESTRUCT: + if structErrors := v.structRecursive(val, current, idxField.Interface()); structErrors != nil { + errs[i] = structErrors + } + + default: + if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, fmt.Sprintf(arrayIndexFieldName, cField.name, i), false, nil); fieldError != nil { + errs[i] = fieldError + } + } + } + + return errs +} + func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{}, f interface{}, key string, param string, name string) (*FieldError, error) { // OK to continue because we checked it's existance before getting into this loop @@ -553,6 +1009,10 @@ func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{ return nil, nil } + // if key == existsTag { + // continue + // } + valFunc, ok := v.validationFuncs[key] if !ok { panic(fmt.Sprintf("Undefined validation function on field %s", name)) diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go index a2d5394a54ff7fd5ddd4db55ec88ac82ab35795a..0752932e13175ef597a18744612c88c34e687e4e 100644 --- a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go +++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go @@ -1,6 +1,7 @@ package validator import ( + "encoding/json" "fmt" "path" "reflect" @@ -14,6 +15,11 @@ import ( // - Run "gocov test | gocov report" to report on test converage by file // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called // +// or +// +// -- may be a good idea to change to output path to somewherelike /tmp +// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html +// // // go test -cpuprofile cpu.out // ./validator.test -test.bench=. -test.cpuprofile=cpu.prof @@ -226,6 +232,1116 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e EqualSkip(t, 2, val.Tag, expectedTag) } +func TestExistsValidation(t *testing.T) { + + jsonText := "{ \"truthiness2\": true }" + + type Thing struct { + Truthiness *bool `json:"truthiness" validate:"exists,required"` + } + + var ting Thing + + err := json.Unmarshal([]byte(jsonText), &ting) + Equal(t, err, nil) + NotEqual(t, ting, nil) + Equal(t, ting.Truthiness, nil) + + errs := validate.Struct(ting) + NotEqual(t, errs, nil) + AssertFieldError(t, errs, "Truthiness", "exists") + + jsonText = "{ \"truthiness\": true }" + + err = json.Unmarshal([]byte(jsonText), &ting) + Equal(t, err, nil) + NotEqual(t, ting, nil) + Equal(t, ting.Truthiness, true) + + errs = validate.Struct(ting) + Equal(t, errs, nil) +} + +func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) { + + var m map[string]string + + errs := validate.Field(m, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + m = map[string]string{} + errs = validate.Field(m, "required") + Equal(t, errs, nil) + + var arr [5]string + errs = validate.Field(arr, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + arr[0] = "ok" + errs = validate.Field(arr, "required") + Equal(t, errs, nil) + + var s []string + errs = validate.Field(s, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + s = []string{} + errs = validate.Field(s, "required") + Equal(t, errs, nil) + + var c chan string + errs = validate.Field(c, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + c = make(chan string) + errs = validate.Field(c, "required") + Equal(t, errs, nil) + + var tst *int + errs = validate.Field(tst, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + one := 1 + tst = &one + errs = validate.Field(tst, "required") + Equal(t, errs, nil) + + var iface interface{} + + errs = validate.Field(iface, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + errs = validate.Field(iface, "omitempty,required") + Equal(t, errs, nil) + + errs = validate.Field(iface, "") + Equal(t, errs, nil) + + errs = validate.Field(iface, "len=1") + NotEqual(t, errs, nil) + + var f func(string) + + errs = validate.Field(f, "required") + NotEqual(t, errs, nil) + // AssertError(t, errs, "", "", "required") + + f = func(name string) {} + + errs = validate.Field(f, "required") + Equal(t, errs, nil) +} + +func TestBadKeyValidation(t *testing.T) { + type Test struct { + Name string `validate:"required, "` + } + + tst := &Test{ + Name: "test", + } + + PanicMatches(t, func() { validate.Struct(tst) }, "Invalid validation tag on field Name") +} + +func TestFlattenValidation(t *testing.T) { + + type Inner struct { + Name string `validate:"required"` + } + + type TestMultiDimensionalStructsPtr struct { + Errs [][]*Inner `validate:"gt=0,dive,dive,required"` + } + + var errStructPtrArray [][]*Inner + + errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {"ok"}}) + + tmsp := &TestMultiDimensionalStructsPtr{ + Errs: errStructPtrArray, + } + + errs := validate.Struct(tmsp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + // for full test coverage + fmt.Sprint(errs.Error()) + + fieldErr := errs.Errors["Errs"] + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, fieldErr.Field, "Errs") + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerSlice1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSlice1.IsPlaceholderErr, true) + Equal(t, innerSlice1.Field, "Errs[0]") + + flatFieldErr, ok := fieldErr.Flatten()["[0][1].Inner.Name"] + Equal(t, ok, true) + Equal(t, flatFieldErr.Field, "Name") + Equal(t, flatFieldErr.Tag, "required") + + structErrFlatten, ok := errs.Flatten()["Errs[0][1].Inner.Name"] + Equal(t, ok, true) + Equal(t, structErrFlatten.Field, "Name") + Equal(t, structErrFlatten.Tag, "required") + + errStructPtrArray = [][]*Inner{} + errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, nil, {"ok"}}) + + tmsp = &TestMultiDimensionalStructsPtr{ + Errs: errStructPtrArray, + } + + errs = validate.Struct(tmsp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + // for full test coverage + fmt.Sprint(errs.Error()) + + fieldErr = errs.Errors["Errs"] + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, fieldErr.Field, "Errs") + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerSlice1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSlice1.IsPlaceholderErr, true) + Equal(t, innerSlice1.Field, "Errs[0]") + + flatFieldErr, ok = fieldErr.Flatten()["[0][1]"] + Equal(t, ok, true) + Equal(t, flatFieldErr.Field, "Errs[0][1]") + Equal(t, flatFieldErr.Tag, "required") + + type TestMapStructPtr struct { + Errs map[int]*Inner `validate:"gt=0,dive,required"` + } + + mip := map[int]*Inner{0: {"ok"}, 3: {""}, 4: {"ok"}} + + msp := &TestMapStructPtr{ + Errs: mip, + } + + errs = validate.Struct(msp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldError := errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 1) + + innerStructError, ok := fieldError.MapErrs[3].(*StructErrors) + Equal(t, ok, true) + Equal(t, innerStructError.Struct, "Inner") + Equal(t, len(innerStructError.Errors), 1) + + innerInnerFieldError, ok := innerStructError.Errors["Name"] + Equal(t, ok, true) + Equal(t, innerInnerFieldError.IsPlaceholderErr, false) + Equal(t, innerInnerFieldError.IsSliceOrArray, false) + Equal(t, innerInnerFieldError.Field, "Name") + Equal(t, innerInnerFieldError.Tag, "required") + + flatErrs, ok := errs.Flatten()["Errs[3].Inner.Name"] + Equal(t, ok, true) + Equal(t, flatErrs.Field, "Name") + Equal(t, flatErrs.Tag, "required") + + mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} + + msp2 := &TestMapStructPtr{ + Errs: mip2, + } + + errs = validate.Struct(msp2) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldError = errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 1) + + innerFieldError, ok := fieldError.MapErrs[3].(*FieldError) + Equal(t, ok, true) + Equal(t, innerFieldError.IsPlaceholderErr, false) + Equal(t, innerFieldError.IsSliceOrArray, false) + Equal(t, innerFieldError.Field, "Errs[3]") + Equal(t, innerFieldError.Tag, "required") + + flatErrs, ok = errs.Flatten()["Errs[3]"] + Equal(t, ok, true) + Equal(t, flatErrs.Field, "Errs[3]") + Equal(t, flatErrs.Tag, "required") + + type TestMapInnerArrayStruct struct { + Errs map[int][]string `validate:"gt=0,dive,dive,required"` + } + + mias := map[int][]string{0: {"ok"}, 3: {"ok", ""}, 4: {"ok"}} + + mia := &TestMapInnerArrayStruct{ + Errs: mias, + } + + errs = validate.Struct(mia) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + flatErrs, ok = errs.Flatten()["Errs[3][1]"] + Equal(t, ok, true) + Equal(t, flatErrs.Field, "Errs[3][1]") + Equal(t, flatErrs.Tag, "required") +} + +func TestInterfaceErrValidation(t *testing.T) { + + var v1 interface{} + var v2 interface{} + + v2 = 1 + v1 = v2 + + err := validate.Field(v1, "len=1") + Equal(t, err, nil) + err = validate.Field(v2, "len=1") + Equal(t, err, nil) + + type ExternalCMD struct { + Userid string `json:"userid"` + Action uint32 `json:"action"` + Data interface{} `json:"data,omitempty" validate:"required"` + } + + s := &ExternalCMD{ + Userid: "123456", + Action: 10000, + // Data: 1, + } + + errs := validate.Struct(s) + NotEqual(t, errs, nil) + Equal(t, errs.Errors["Data"].Field, "Data") + Equal(t, errs.Errors["Data"].Tag, "required") + + type ExternalCMD2 struct { + Userid string `json:"userid"` + Action uint32 `json:"action"` + Data interface{} `json:"data,omitempty" validate:"len=1"` + } + + s2 := &ExternalCMD2{ + Userid: "123456", + Action: 10000, + // Data: 1, + } + + errs = validate.Struct(s2) + NotEqual(t, errs, nil) + Equal(t, errs.Errors["Data"].Field, "Data") + Equal(t, errs.Errors["Data"].Tag, "len") + Equal(t, errs.Errors["Data"].Param, "1") + + s3 := &ExternalCMD2{ + Userid: "123456", + Action: 10000, + Data: 2, + } + + errs = validate.Struct(s3) + NotEqual(t, errs, nil) + Equal(t, errs.Errors["Data"].Field, "Data") + Equal(t, errs.Errors["Data"].Tag, "len") + Equal(t, errs.Errors["Data"].Param, "1") + + type Inner struct { + Name string `validate:"required"` + } + + inner := &Inner{ + Name: "", + } + + s4 := &ExternalCMD{ + Userid: "123456", + Action: 10000, + Data: inner, + } + + errs = validate.Struct(s4) + NotEqual(t, errs, nil) + Equal(t, errs.StructErrors["Data"].Struct, "Inner") + Equal(t, errs.StructErrors["Data"].Errors["Name"].Field, "Name") + Equal(t, errs.StructErrors["Data"].Errors["Name"].Tag, "required") + + type TestMapStructPtr struct { + Errs map[int]interface{} `validate:"gt=0,dive,len=2"` + } + + mip := map[int]interface{}{0: &Inner{"ok"}, 3: nil, 4: &Inner{"ok"}} + + msp := &TestMapStructPtr{ + Errs: mip, + } + + errs = validate.Struct(msp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldError := errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 1) + + innerFieldError, ok := fieldError.MapErrs[3].(*FieldError) + Equal(t, ok, true) + Equal(t, innerFieldError.IsPlaceholderErr, false) + Equal(t, innerFieldError.IsMap, false) + Equal(t, len(innerFieldError.MapErrs), 0) + Equal(t, innerFieldError.Field, "Errs[3]") + Equal(t, innerFieldError.Tag, "len") + + type TestMultiDimensionalStructs struct { + Errs [][]interface{} `validate:"gt=0,dive,dive,len=2"` + } + + var errStructArray [][]interface{} + + errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) + errStructArray = append(errStructArray, []interface{}{&Inner{"ok"}, &Inner{""}, &Inner{""}}) + + tms := &TestMultiDimensionalStructs{ + Errs: errStructArray, + } + + errs = validate.Struct(tms) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok := errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 2) + + sliceError1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok := sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerInnersliceError1 := innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + type TestMultiDimensionalStructsPtr2 struct { + Errs [][]*Inner `validate:"gt=0,dive,dive,len=2"` + } + + var errStructPtr2Array [][]*Inner + + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) + + tmsp2 := &TestMultiDimensionalStructsPtr2{ + Errs: errStructPtr2Array, + } + + errs = validate.Struct(tmsp2) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 3) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerSliceStructError2, ok := sliceError1.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSliceStructError2.IsPlaceholderErr, false) + Equal(t, innerSliceStructError2.IsSliceOrArray, false) + Equal(t, len(innerSliceStructError2.SliceOrArrayErrs), 0) + Equal(t, innerSliceStructError2.Field, "Errs[2][2]") + + innerInnersliceError1 = innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + m := map[int]interface{}{0: "ok", 3: "", 4: "ok"} + + err = validate.Field(m, "len=3,dive,len=2") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, true) + Equal(t, err.IsMap, true) + Equal(t, len(err.MapErrs), 1) + + err = validate.Field(m, "len=2,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, false) + Equal(t, err.IsMap, false) + Equal(t, len(err.MapErrs), 0) + + arr := []interface{}{"ok", "", "ok"} + + err = validate.Field(arr, "len=3,dive,len=2") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, true) + Equal(t, err.IsSliceOrArray, true) + Equal(t, len(err.SliceOrArrayErrs), 1) + + err = validate.Field(arr, "len=2,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, false) + Equal(t, err.IsSliceOrArray, false) + Equal(t, len(err.SliceOrArrayErrs), 0) + + type MyStruct struct { + A, B string + C interface{} + } + + var a MyStruct + + a.A = "value" + a.C = "nu" + + errs = validate.Struct(a) + Equal(t, errs, nil) +} + +func TestMapDiveValidation(t *testing.T) { + + n := map[int]interface{}{0: nil} + err := validate.Field(n, "omitempty,required") + + m := map[int]string{0: "ok", 3: "", 4: "ok"} + + err = validate.Field(m, "len=3,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, true) + Equal(t, err.IsMap, true) + Equal(t, len(err.MapErrs), 1) + + err = validate.Field(m, "len=2,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, false) + Equal(t, err.IsMap, false) + Equal(t, len(err.MapErrs), 0) + + type Inner struct { + Name string `validate:"required"` + } + + type TestMapStruct struct { + Errs map[int]Inner `validate:"gt=0,dive"` + } + + mi := map[int]Inner{0: {"ok"}, 3: {""}, 4: {"ok"}} + + ms := &TestMapStruct{ + Errs: mi, + } + + errs := validate.Struct(ms) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + // for full test coverage + fmt.Sprint(errs.Error()) + + fieldError := errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 1) + + structErr, ok := fieldError.MapErrs[3].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(structErr.Errors), 1) + + innerErr := structErr.Errors["Name"] + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.IsMap, false) + Equal(t, len(innerErr.MapErrs), 0) + Equal(t, innerErr.Field, "Name") + Equal(t, innerErr.Tag, "required") + + type TestMapTimeStruct struct { + Errs map[int]*time.Time `validate:"gt=0,dive,required"` + } + + t1 := time.Now().UTC() + + mta := map[int]*time.Time{0: &t1, 3: nil, 4: nil} + + mt := &TestMapTimeStruct{ + Errs: mta, + } + + errs = validate.Struct(mt) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldError = errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 2) + + innerErr, ok = fieldError.MapErrs[3].(*FieldError) + Equal(t, ok, true) + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.IsMap, false) + Equal(t, len(innerErr.MapErrs), 0) + Equal(t, innerErr.Field, "Errs[3]") + Equal(t, innerErr.Tag, "required") + + type TestMapStructPtr struct { + Errs map[int]*Inner `validate:"gt=0,dive,required"` + } + + mip := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} + + msp := &TestMapStructPtr{ + Errs: mip, + } + + errs = validate.Struct(msp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldError = errs.Errors["Errs"] + Equal(t, fieldError.IsPlaceholderErr, true) + Equal(t, fieldError.IsMap, true) + Equal(t, len(fieldError.MapErrs), 1) + + innerFieldError, ok := fieldError.MapErrs[3].(*FieldError) + Equal(t, ok, true) + Equal(t, innerFieldError.IsPlaceholderErr, false) + Equal(t, innerFieldError.IsMap, false) + Equal(t, len(innerFieldError.MapErrs), 0) + Equal(t, innerFieldError.Field, "Errs[3]") + Equal(t, innerFieldError.Tag, "required") + + type TestMapStructPtr2 struct { + Errs map[int]*Inner `validate:"gt=0,dive,omitempty,required"` + } + + mip2 := map[int]*Inner{0: {"ok"}, 3: nil, 4: {"ok"}} + + msp2 := &TestMapStructPtr2{ + Errs: mip2, + } + + errs = validate.Struct(msp2) + Equal(t, errs, nil) +} + +func TestArrayDiveValidation(t *testing.T) { + + arr := []string{"ok", "", "ok"} + + err := validate.Field(arr, "len=3,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, true) + Equal(t, err.IsSliceOrArray, true) + Equal(t, len(err.SliceOrArrayErrs), 1) + + // flat := err.Flatten() + // fe, ok := flat["[1]"] + // Equal(t, ok, true) + // Equal(t, fe.Tag, "required") + + err = validate.Field(arr, "len=2,dive,required") + NotEqual(t, err, nil) + Equal(t, err.IsPlaceholderErr, false) + Equal(t, err.IsSliceOrArray, false) + Equal(t, len(err.SliceOrArrayErrs), 0) + + type BadDive struct { + Name string `validate:"dive"` + } + + bd := &BadDive{ + Name: "TEST", + } + + PanicMatches(t, func() { validate.Struct(bd) }, "dive error! can't dive on a non slice or map") + + type Test struct { + Errs []string `validate:"gt=0,dive,required"` + } + + test := &Test{ + Errs: []string{"ok", "", "ok"}, + } + + errs := validate.Struct(test) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + // flat = errs.Flatten() + // me, ok := flat["Errs[1]"] + // Equal(t, ok, true) + // Equal(t, me.Field, "Errs[1]") + // Equal(t, me.Tag, "required") + + fieldErr, ok := errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerErr, ok := fieldErr.SliceOrArrayErrs[1].(*FieldError) + Equal(t, ok, true) + Equal(t, innerErr.Tag, required) + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.Field, "Errs[1]") + + test = &Test{ + Errs: []string{"ok", "ok", ""}, + } + + errs = validate.Struct(test) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerErr, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, innerErr.Tag, required) + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.Field, "Errs[2]") + + type TestMultiDimensional struct { + Errs [][]string `validate:"gt=0,dive,dive,required"` + } + + var errArray [][]string + + errArray = append(errArray, []string{"ok", "", ""}) + errArray = append(errArray, []string{"ok", "", ""}) + + tm := &TestMultiDimensional{ + Errs: errArray, + } + + errs = validate.Struct(tm) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 2) + + sliceError1, ok := fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + Equal(t, sliceError1.Field, "Errs[0]") + + innerSliceError1, ok := sliceError1.SliceOrArrayErrs[1].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSliceError1.IsPlaceholderErr, false) + Equal(t, innerSliceError1.Tag, required) + Equal(t, innerSliceError1.IsSliceOrArray, false) + Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0) + Equal(t, innerSliceError1.Field, "Errs[0][1]") + + type Inner struct { + Name string `validate:"required"` + } + + type TestMultiDimensionalStructs struct { + Errs [][]Inner `validate:"gt=0,dive,dive"` + } + + var errStructArray [][]Inner + + errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) + errStructArray = append(errStructArray, []Inner{{"ok"}, {""}, {""}}) + + tms := &TestMultiDimensionalStructs{ + Errs: errStructArray, + } + + errs = validate.Struct(tms) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 2) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok := sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerInnersliceError1 := innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + type TestMultiDimensionalStructsPtr struct { + Errs [][]*Inner `validate:"gt=0,dive,dive"` + } + + var errStructPtrArray [][]*Inner + + errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) + errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, {""}}) + errStructPtrArray = append(errStructPtrArray, []*Inner{{"ok"}, {""}, nil}) + + tmsp := &TestMultiDimensionalStructsPtr{ + Errs: errStructPtrArray, + } + + errs = validate.Struct(tmsp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + // for full test coverage + fmt.Sprint(errs.Error()) + + // flat := errs.Flatten() + // // fmt.Println(errs) + // fmt.Println(flat) + // expect Errs[0][1].Inner.Name + // me, ok := flat["Errs[1]"] + // Equal(t, ok, true) + // Equal(t, me.Field, "Errs[1]") + // Equal(t, me.Tag, "required") + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 3) + + // flat := fieldErr.Flatten() + // fmt.Println(errs) + // fmt.Println(flat) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerInnersliceError1 = innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + type TestMultiDimensionalStructsPtr2 struct { + Errs [][]*Inner `validate:"gt=0,dive,dive,required"` + } + + var errStructPtr2Array [][]*Inner + + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr2Array = append(errStructPtr2Array, []*Inner{{"ok"}, {""}, nil}) + + tmsp2 := &TestMultiDimensionalStructsPtr2{ + Errs: errStructPtr2Array, + } + + errs = validate.Struct(tmsp2) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 3) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerSliceStructError2, ok := sliceError1.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSliceStructError2.IsPlaceholderErr, false) + Equal(t, innerSliceStructError2.IsSliceOrArray, false) + Equal(t, len(innerSliceStructError2.SliceOrArrayErrs), 0) + Equal(t, innerSliceStructError2.Field, "Errs[2][2]") + + innerInnersliceError1 = innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + type TestMultiDimensionalStructsPtr3 struct { + Errs [][]*Inner `validate:"gt=0,dive,dive,omitempty"` + } + + var errStructPtr3Array [][]*Inner + + errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, {""}}) + errStructPtr3Array = append(errStructPtr3Array, []*Inner{{"ok"}, {""}, nil}) + + tmsp3 := &TestMultiDimensionalStructsPtr3{ + Errs: errStructPtr3Array, + } + + errs = validate.Struct(tmsp3) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 3) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[0].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceStructError1, ok = sliceError1.SliceOrArrayErrs[1].(*StructErrors) + Equal(t, ok, true) + Equal(t, len(innerSliceStructError1.Errors), 1) + + innerInnersliceError1 = innerSliceStructError1.Errors["Name"] + Equal(t, innerInnersliceError1.IsPlaceholderErr, false) + Equal(t, innerInnersliceError1.IsSliceOrArray, false) + Equal(t, len(innerInnersliceError1.SliceOrArrayErrs), 0) + + type TestMultiDimensionalTimeTime struct { + Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` + } + + var errTimePtr3Array [][]*time.Time + + t1 := time.Now().UTC() + t2 := time.Now().UTC() + t3 := time.Now().UTC().Add(time.Hour * 24) + + errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, &t3}) + errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, &t2, nil}) + errTimePtr3Array = append(errTimePtr3Array, []*time.Time{&t1, nil, nil}) + + tmtp3 := &TestMultiDimensionalTimeTime{ + Errs: errTimePtr3Array, + } + + errs = validate.Struct(tmtp3) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 2) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceError1, ok = sliceError1.SliceOrArrayErrs[1].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSliceError1.IsPlaceholderErr, false) + Equal(t, innerSliceError1.IsSliceOrArray, false) + Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0) + Equal(t, innerSliceError1.Field, "Errs[2][1]") + Equal(t, innerSliceError1.Tag, required) + + type TestMultiDimensionalTimeTime2 struct { + Errs [][]*time.Time `validate:"gt=0,dive,dive,required"` + } + + var errTimeArray [][]*time.Time + + t1 = time.Now().UTC() + t2 = time.Now().UTC() + t3 = time.Now().UTC().Add(time.Hour * 24) + + errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, &t3}) + errTimeArray = append(errTimeArray, []*time.Time{&t1, &t2, nil}) + errTimeArray = append(errTimeArray, []*time.Time{&t1, nil, nil}) + + tmtp := &TestMultiDimensionalTimeTime2{ + Errs: errTimeArray, + } + + errs = validate.Struct(tmtp) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 2) + + sliceError1, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, sliceError1.IsPlaceholderErr, true) + Equal(t, sliceError1.IsSliceOrArray, true) + Equal(t, len(sliceError1.SliceOrArrayErrs), 2) + + innerSliceError1, ok = sliceError1.SliceOrArrayErrs[1].(*FieldError) + Equal(t, ok, true) + Equal(t, innerSliceError1.IsPlaceholderErr, false) + Equal(t, innerSliceError1.IsSliceOrArray, false) + Equal(t, len(innerSliceError1.SliceOrArrayErrs), 0) + Equal(t, innerSliceError1.Field, "Errs[2][1]") + Equal(t, innerSliceError1.Tag, required) +} + +func TestNilStructPointerValidation(t *testing.T) { + type Inner struct { + Data string + } + + type Outer struct { + Inner *Inner `validate:"omitempty"` + } + + inner := &Inner{ + Data: "test", + } + + outer := &Outer{ + Inner: inner, + } + + errs := validate.Struct(outer) + Equal(t, errs, nil) + + outer = &Outer{ + Inner: nil, + } + + errs = validate.Struct(outer) + Equal(t, errs, nil) + + type Inner2 struct { + Data string + } + + type Outer2 struct { + Inner2 *Inner2 `validate:"required"` + } + + inner2 := &Inner2{ + Data: "test", + } + + outer2 := &Outer2{ + Inner2: inner2, + } + + errs = validate.Struct(outer2) + Equal(t, errs, nil) + + outer2 = &Outer2{ + Inner2: nil, + } + + errs = validate.Struct(outer2) + NotEqual(t, errs, nil) + + type Inner3 struct { + Data string + } + + type Outer3 struct { + Inner3 *Inner3 + } + + inner3 := &Inner3{ + Data: "test", + } + + outer3 := &Outer3{ + Inner3: inner3, + } + + errs = validate.Struct(outer3) + Equal(t, errs, nil) + + type Inner4 struct { + Data string + } + + type Outer4 struct { + Inner4 *Inner4 `validate:"-"` + } + + inner4 := &Inner4{ + Data: "test", + } + + outer4 := &Outer4{ + Inner4: inner4, + } + + errs = validate.Struct(outer4) + Equal(t, errs, nil) +} + func TestSSNValidation(t *testing.T) { tests := []struct { param string @@ -1100,7 +2216,7 @@ func TestStructOnlyValidation(t *testing.T) { InnerStruct: nil, } - errs := validate.Struct(outer).Flatten() + errs := validate.Struct(outer) NotEqual(t, errs, nil) inner := &Inner{ @@ -1111,9 +2227,8 @@ func TestStructOnlyValidation(t *testing.T) { InnerStruct: inner, } - errs = validate.Struct(outer).Flatten() - NotEqual(t, errs, nil) - Equal(t, len(errs), 0) + errs = validate.Struct(outer) + Equal(t, errs, nil) } func TestGtField(t *testing.T) { @@ -2727,14 +3842,14 @@ func TestStructSliceValidation(t *testing.T) { Min: []int{1, 2}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, MinMax: []int{1, 2, 3, 4, 5}, - OmitEmpty: []int{}, + OmitEmpty: nil, } err := validate.Struct(tSuccess) Equal(t, err, nil) tFail := &TestSlice{ - Required: []int{}, + Required: nil, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, Min: []int{}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, @@ -2772,7 +3887,7 @@ func TestInvalidField(t *testing.T) { Test: "1", } - PanicMatches(t, func() { validate.Field(s, "required") }, "Invalid field passed to ValidateFieldWithTag") + PanicMatches(t, func() { validate.Field(s, "required") }, "Invalid field passed to fieldWithNameAndValue") } func TestInvalidTagField(t *testing.T) { @@ -2790,3 +3905,23 @@ func TestInvalidValidatorFunction(t *testing.T) { PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, fmt.Sprintf("Undefined validation function on field %s", "")) } + +func TestPoolObjectMaxSizeValidation(t *testing.T) { + // this will ensure that the pool objects are let go + // when the pool is saturated + validate.SetMaxStructPoolSize(0) + + tSuccess := &TestSlice{ + Required: []int{1}, + Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + Min: []int{1, 2}, + Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + MinMax: []int{1, 2, 3, 4, 5}, + OmitEmpty: nil, + } + + for i := 0; i < 2; i++ { + err := validate.Struct(tSuccess) + Equal(t, err, nil) + } +}