diff --git a/example/golang/counter.go b/example/golang/counter.go index 56546700f..46edcb413 100644 --- a/example/golang/counter.go +++ b/example/golang/counter.go @@ -29,7 +29,7 @@ func (app *CounterApplication) SetOption(key string, value string) types.RetCode if key == "serial" && value == "on" { app.serial = true } - return 0 + return types.RetCodeOK } func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { @@ -42,7 +42,7 @@ func (app *CounterApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode } } app.txCount += 1 - return nil, 0 + return nil, types.RetCodeOK } func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { @@ -54,25 +54,29 @@ func (app *CounterApplication) CheckTx(tx []byte) types.RetCode { return types.RetCodeBadNonce } } - return 0 + return types.RetCodeOK } func (app *CounterApplication) GetHash() ([]byte, types.RetCode) { app.hashCount += 1 if app.txCount == 0 { - return nil, 0 + return nil, types.RetCodeOK } else { hash := make([]byte, 32) binary.LittleEndian.PutUint64(hash, uint64(app.txCount)) - return hash, 0 + return hash, types.RetCodeOK } } func (app *CounterApplication) AddListener(key string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *CounterApplication) RemListener(key string) types.RetCode { - return 0 + return types.RetCodeOK +} + +func (app *CounterApplication) Query(query []byte) (types.RetCode, []byte) { + return types.RetCodeOK, nil } diff --git a/example/golang/dummy.go b/example/golang/dummy.go index 13c2c5828..543e865b8 100644 --- a/example/golang/dummy.go +++ b/example/golang/dummy.go @@ -27,27 +27,31 @@ func (app *DummyApplication) Info() []string { } func (app *DummyApplication) SetOption(key string, value string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *DummyApplication) AppendTx(tx []byte) ([]types.Event, types.RetCode) { app.state.Set(tx, tx) - return nil, 0 + return nil, types.RetCodeOK } func (app *DummyApplication) CheckTx(tx []byte) types.RetCode { - return 0 // all txs are valid + return types.RetCodeOK // all txs are valid } func (app *DummyApplication) GetHash() ([]byte, types.RetCode) { hash := app.state.Hash() - return hash, 0 + return hash, types.RetCodeOK } func (app *DummyApplication) AddListener(key string) types.RetCode { - return 0 + return types.RetCodeOK } func (app *DummyApplication) RemListener(key string) types.RetCode { - return 0 + return types.RetCodeOK +} + +func (app *DummyApplication) Query(query []byte) (types.RetCode, []byte) { + return types.RetCodeOK, nil } diff --git a/server/server.go b/server/server.go index a8d014c25..8a6a16d91 100644 --- a/server/server.go +++ b/server/server.go @@ -127,6 +127,9 @@ func handleRequest(app types.Application, req types.Request, responses chan<- ty case types.RequestRemListener: retCode := app.RemListener(req.EventKey) responses <- types.ResponseRemListener{retCode} + case types.RequestQuery: + retCode, result := app.Query(req.QueryBytes) + responses <- types.ResponseQuery{retCode, result} default: responses <- types.ResponseException{"Unknown request"} } diff --git a/tests/benchmarks/blank.go b/tests/benchmarks/blank.go new file mode 100644 index 000000000..20f08f14b --- /dev/null +++ b/tests/benchmarks/blank.go @@ -0,0 +1 @@ +package benchmarks diff --git a/tests/benchmarks/parallel/parallel.go b/tests/benchmarks/parallel/parallel.go new file mode 100644 index 000000000..481c14326 --- /dev/null +++ b/tests/benchmarks/parallel/parallel.go @@ -0,0 +1,58 @@ +package main + +import ( + "bufio" + "fmt" + //"encoding/hex" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func main() { + + conn, err := Connect("unix://test.sock") + if err != nil { + Exit(err.Error()) + } + + // Read a bunch of responses + go func() { + counter := 0 + for { + var res types.Response + var n int + var err error + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println("Read", counter) + } + } + }() + + // Write a bunch of requests + counter := 0 + for i := 0; ; i++ { + var bufWriter = bufio.NewWriter(conn) + var req types.Request = types.RequestEcho{"foobar"} + var n int + var err error + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + if err != nil { + Exit(err.Error()) + } + err = bufWriter.Flush() + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println("Write", counter) + } + } +} diff --git a/tests/benchmarks/simple/simple.go b/tests/benchmarks/simple/simple.go new file mode 100644 index 000000000..4009f8489 --- /dev/null +++ b/tests/benchmarks/simple/simple.go @@ -0,0 +1,70 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "net" + "reflect" + //"encoding/hex" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func main() { + + conn, err := Connect("unix://test.sock") + if err != nil { + Exit(err.Error()) + } + + // Make a bunch of requests + counter := 0 + for i := 0; ; i++ { + req := types.RequestEcho{"foobar"} + _, err := makeRequest(conn, req) + if err != nil { + Exit(err.Error()) + } + counter += 1 + if counter%1000 == 0 { + fmt.Println(counter) + } + } +} + +func makeRequest(conn net.Conn, req types.Request) (types.Response, error) { + var bufWriter = bufio.NewWriter(conn) + var n int + var err error + + // Write desired request + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, bufWriter, &n, &err) + if err != nil { + return nil, err + } + bufWriter.Write([]byte{0x01, 0x01, types.RequestTypeFlush}) // Write flush msg + err = bufWriter.Flush() + if err != nil { + return nil, err + } + + // Read desired response + var res types.Response + wire.ReadBinaryPtrLengthPrefixed(&res, conn, 0, &n, &err) + if err != nil { + return nil, err + } + var resFlush types.Response // Read flush msg + wire.ReadBinaryPtrLengthPrefixed(&resFlush, conn, 0, &n, &err) + if err != nil { + return nil, err + } + if _, ok := resFlush.(types.ResponseFlush); !ok { + return nil, errors.New(Fmt("Expected flush response but got something else", reflect.TypeOf(resFlush))) + } + + return res, nil +} diff --git a/tests/benchmarks/wire_test.go b/tests/benchmarks/wire_test.go new file mode 100644 index 000000000..c730089aa --- /dev/null +++ b/tests/benchmarks/wire_test.go @@ -0,0 +1,44 @@ +package benchmarks + +import ( + "bytes" + "testing" + + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "github.com/tendermint/tmsp/types" +) + +func BenchmarkRequestWire(b *testing.B) { + b.StopTimer() + var bz = make([]byte, 1024) + copy(bz, []byte{1, 9, 0x01, 1, 6, 34, 34, 34, 34, 34, 34}) + var buf = bytes.NewBuffer(bz) + var req types.Request + b.StartTimer() + + for i := 0; i < b.N; i++ { + { + buf = bytes.NewBuffer(bz) + var n int + var err error + wire.ReadBinaryPtrLengthPrefixed(&req, buf, 0, &n, &err) + if err != nil { + Exit(err.Error()) + return + } + } + { + buf = bytes.NewBuffer(bz) + var n int + var err error + wire.WriteBinaryLengthPrefixed(struct{ types.Request }{req}, buf, &n, &err) + if err != nil { + Exit(err.Error()) + return + } + + } + } + +} diff --git a/types/application.go b/types/application.go index d77b6c35e..4a0818fdc 100644 --- a/types/application.go +++ b/types/application.go @@ -25,4 +25,7 @@ type Application interface { // Remove event listener RemListener(key string) RetCode + + // Query for state + Query(query []byte) (RetCode, []byte) } diff --git a/types/messages.go b/types/messages.go index e98f1d3e3..fa9b30d98 100644 --- a/types/messages.go +++ b/types/messages.go @@ -3,32 +3,34 @@ package types import "github.com/tendermint/go-wire" const ( - requestTypeEcho = byte(0x01) - requestTypeFlush = byte(0x02) - requestTypeInfo = byte(0x03) - requestTypeSetOption = byte(0x04) + RequestTypeEcho = byte(0x01) + RequestTypeFlush = byte(0x02) + RequestTypeInfo = byte(0x03) + RequestTypeSetOption = byte(0x04) // reserved for GetOption = byte(0x05) - responseTypeException = byte(0x10) - responseTypeEcho = byte(0x11) - responseTypeFlush = byte(0x12) - responseTypeInfo = byte(0x13) - responseTypeSetOption = byte(0x14) + ResponseTypeException = byte(0x10) + ResponseTypeEcho = byte(0x11) + ResponseTypeFlush = byte(0x12) + ResponseTypeInfo = byte(0x13) + ResponseTypeSetOption = byte(0x14) // reserved for GetOption = byte(0x15) - requestTypeAppendTx = byte(0x21) - requestTypeCheckTx = byte(0x22) - requestTypeGetHash = byte(0x23) - requestTypeAddListener = byte(0x24) - requestTypeRemListener = byte(0x25) - // reserved for responseTypeEvent 0x26 - - responseTypeAppendTx = byte(0x31) - responseTypeCheckTx = byte(0x32) - responseTypeGetHash = byte(0x33) - responseTypeAddListener = byte(0x34) - responseTypeRemListener = byte(0x35) - responseTypeEvent = byte(0x36) + RequestTypeAppendTx = byte(0x21) + RequestTypeCheckTx = byte(0x22) + RequestTypeGetHash = byte(0x23) + RequestTypeAddListener = byte(0x24) + RequestTypeRemListener = byte(0x25) + // reserved for ResponseTypeEvent 0x26 + RequestTypeQuery = byte(0x27) + + ResponseTypeAppendTx = byte(0x31) + ResponseTypeCheckTx = byte(0x32) + ResponseTypeGetHash = byte(0x33) + ResponseTypeAddListener = byte(0x34) + ResponseTypeRemListener = byte(0x35) + ResponseTypeEvent = byte(0x36) + ResponseTypeQuery = byte(0x37) ) //---------------------------------------- @@ -67,6 +69,10 @@ type RequestRemListener struct { EventKey string } +type RequestQuery struct { + QueryBytes []byte +} + type Request interface { AssertRequestType() } @@ -80,18 +86,20 @@ func (_ RequestCheckTx) AssertRequestType() {} func (_ RequestGetHash) AssertRequestType() {} func (_ RequestAddListener) AssertRequestType() {} func (_ RequestRemListener) AssertRequestType() {} +func (_ RequestQuery) AssertRequestType() {} var _ = wire.RegisterInterface( struct{ Request }{}, - wire.ConcreteType{RequestEcho{}, requestTypeEcho}, - wire.ConcreteType{RequestFlush{}, requestTypeFlush}, - wire.ConcreteType{RequestInfo{}, requestTypeInfo}, - wire.ConcreteType{RequestSetOption{}, requestTypeSetOption}, - wire.ConcreteType{RequestAppendTx{}, requestTypeAppendTx}, - wire.ConcreteType{RequestCheckTx{}, requestTypeCheckTx}, - wire.ConcreteType{RequestGetHash{}, requestTypeGetHash}, - wire.ConcreteType{RequestAddListener{}, requestTypeAddListener}, - wire.ConcreteType{RequestRemListener{}, requestTypeRemListener}, + wire.ConcreteType{RequestEcho{}, RequestTypeEcho}, + wire.ConcreteType{RequestFlush{}, RequestTypeFlush}, + wire.ConcreteType{RequestInfo{}, RequestTypeInfo}, + wire.ConcreteType{RequestSetOption{}, RequestTypeSetOption}, + wire.ConcreteType{RequestAppendTx{}, RequestTypeAppendTx}, + wire.ConcreteType{RequestCheckTx{}, RequestTypeCheckTx}, + wire.ConcreteType{RequestGetHash{}, RequestTypeGetHash}, + wire.ConcreteType{RequestAddListener{}, RequestTypeAddListener}, + wire.ConcreteType{RequestRemListener{}, RequestTypeRemListener}, + wire.ConcreteType{RequestQuery{}, RequestTypeQuery}, ) //---------------------------------------- @@ -140,6 +148,11 @@ type ResponseEvent struct { Event } +type ResponseQuery struct { + RetCode + Result []byte +} + type Response interface { AssertResponseType() } @@ -155,18 +168,20 @@ func (_ ResponseAddListener) AssertResponseType() {} func (_ ResponseRemListener) AssertResponseType() {} func (_ ResponseException) AssertResponseType() {} func (_ ResponseEvent) AssertResponseType() {} +func (_ ResponseQuery) AssertResponseType() {} var _ = wire.RegisterInterface( struct{ Response }{}, - wire.ConcreteType{ResponseEcho{}, responseTypeEcho}, - wire.ConcreteType{ResponseFlush{}, responseTypeFlush}, - wire.ConcreteType{ResponseInfo{}, responseTypeInfo}, - wire.ConcreteType{ResponseSetOption{}, responseTypeSetOption}, - wire.ConcreteType{ResponseAppendTx{}, responseTypeAppendTx}, - wire.ConcreteType{ResponseCheckTx{}, responseTypeCheckTx}, - wire.ConcreteType{ResponseGetHash{}, responseTypeGetHash}, - wire.ConcreteType{ResponseAddListener{}, responseTypeAddListener}, - wire.ConcreteType{ResponseRemListener{}, responseTypeRemListener}, - wire.ConcreteType{ResponseException{}, responseTypeException}, - wire.ConcreteType{ResponseEvent{}, responseTypeEvent}, + wire.ConcreteType{ResponseEcho{}, ResponseTypeEcho}, + wire.ConcreteType{ResponseFlush{}, ResponseTypeFlush}, + wire.ConcreteType{ResponseInfo{}, ResponseTypeInfo}, + wire.ConcreteType{ResponseSetOption{}, ResponseTypeSetOption}, + wire.ConcreteType{ResponseAppendTx{}, ResponseTypeAppendTx}, + wire.ConcreteType{ResponseCheckTx{}, ResponseTypeCheckTx}, + wire.ConcreteType{ResponseGetHash{}, ResponseTypeGetHash}, + wire.ConcreteType{ResponseAddListener{}, ResponseTypeAddListener}, + wire.ConcreteType{ResponseRemListener{}, ResponseTypeRemListener}, + wire.ConcreteType{ResponseException{}, ResponseTypeException}, + wire.ConcreteType{ResponseEvent{}, ResponseTypeEvent}, + wire.ConcreteType{ResponseQuery{}, ResponseTypeQuery}, )