diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-06 19:49:01 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-06 19:49:01 +0000 |
commit | f038dae646bac2b31be98ab592c0e5206d2d96f5 (patch) | |
tree | 39530b071991b2326f881b2a30a2d82d6c133fd6 /libgo/go/net/rpc | |
parent | f20f261304993444741e0f0a14d3147e591bc660 (diff) | |
download | gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.zip gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.tar.gz gcc-f038dae646bac2b31be98ab592c0e5206d2d96f5.tar.bz2 |
libgo: Update to October 24 version of master library.
From-SVN: r204466
Diffstat (limited to 'libgo/go/net/rpc')
-rw-r--r-- | libgo/go/net/rpc/client.go | 7 | ||||
-rw-r--r-- | libgo/go/net/rpc/debug.go | 3 | ||||
-rw-r--r-- | libgo/go/net/rpc/jsonrpc/server.go | 3 | ||||
-rw-r--r-- | libgo/go/net/rpc/server.go | 24 | ||||
-rw-r--r-- | libgo/go/net/rpc/server_test.go | 52 |
5 files changed, 75 insertions, 14 deletions
diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go index 4b0c9c3..c524d0a 100644 --- a/libgo/go/net/rpc/client.go +++ b/libgo/go/net/rpc/client.go @@ -58,6 +58,7 @@ type Client struct { // argument to force the body of the response to be read and then // discarded. type ClientCodec interface { + // WriteRequest must be safe for concurrent use by multiple goroutines. WriteRequest(*Request, interface{}) error ReadResponseHeader(*Response) error ReadResponseBody(interface{}) error @@ -160,7 +161,7 @@ func (client *Client) input() { } client.mutex.Unlock() client.sending.Unlock() - if err != io.EOF && !closing { + if debugLog && err != io.EOF && !closing { log.Println("rpc: client protocol error:", err) } } @@ -172,7 +173,9 @@ func (call *Call) done() { default: // We don't want to block here. It is the caller's responsibility to make // sure the channel has enough buffer space. See comment in Go(). - log.Println("rpc: discarding Call reply due to insufficient Done chan capacity") + if debugLog { + log.Println("rpc: discarding Call reply due to insufficient Done chan capacity") + } } } diff --git a/libgo/go/net/rpc/debug.go b/libgo/go/net/rpc/debug.go index 663663f..926466d 100644 --- a/libgo/go/net/rpc/debug.go +++ b/libgo/go/net/rpc/debug.go @@ -38,6 +38,9 @@ const debugText = `<html> var debug = template.Must(template.New("RPC debug").Parse(debugText)) +// If set, print log statements for internal and I/O errors. +var debugLog = false + type debugMethod struct { Type *methodType Name string diff --git a/libgo/go/net/rpc/jsonrpc/server.go b/libgo/go/net/rpc/jsonrpc/server.go index 5bc05fd..16ec0fe 100644 --- a/libgo/go/net/rpc/jsonrpc/server.go +++ b/libgo/go/net/rpc/jsonrpc/server.go @@ -20,8 +20,7 @@ type serverCodec struct { c io.Closer // temporary work space - req serverRequest - resp serverResponse + req serverRequest // JSON-RPC clients can use arbitrary json values as request IDs. // Package rpc expects uint64 request IDs. diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go index e71b6fb..7eb2dcf 100644 --- a/libgo/go/net/rpc/server.go +++ b/libgo/go/net/rpc/server.go @@ -247,10 +247,12 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro sname = name } if sname == "" { - log.Fatal("rpc: no service name for type", s.typ.String()) + s := "rpc.Register: no service name for type " + s.typ.String() + log.Print(s) + return errors.New(s) } if !isExported(sname) && !useName { - s := "rpc Register: type " + sname + " is not exported" + s := "rpc.Register: type " + sname + " is not exported" log.Print(s) return errors.New(s) } @@ -258,13 +260,13 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro return errors.New("rpc: service already defined: " + sname) } s.name = sname - s.method = make(map[string]*methodType) // Install the methods s.method = suitableMethods(s.typ, true) if len(s.method) == 0 { str := "" + // To help the user, see if a pointer receiver would work. method := suitableMethods(reflect.PtrTo(s.typ), false) if len(method) != 0 { @@ -356,7 +358,7 @@ func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply inte resp.Seq = req.Seq sending.Lock() err := codec.WriteResponse(resp, reply) - if err != nil { + if debugLog && err != nil { log.Println("rpc: writing response:", err) } sending.Unlock() @@ -434,7 +436,7 @@ func (server *Server) ServeCodec(codec ServerCodec) { for { service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec) if err != nil { - if err != io.EOF { + if debugLog && err != io.EOF { log.Println("rpc:", err) } if !keepReading { @@ -560,20 +562,23 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt // we can still recover and move on to the next request. keepReading = true - serviceMethod := strings.Split(req.ServiceMethod, ".") - if len(serviceMethod) != 2 { + dot := strings.LastIndex(req.ServiceMethod, ".") + if dot < 0 { err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod) return } + serviceName := req.ServiceMethod[:dot] + methodName := req.ServiceMethod[dot+1:] + // Look up the request. server.mu.RLock() - service = server.serviceMap[serviceMethod[0]] + service = server.serviceMap[serviceName] server.mu.RUnlock() if service == nil { err = errors.New("rpc: can't find service " + req.ServiceMethod) return } - mtype = service.method[serviceMethod[1]] + mtype = service.method[methodName] if mtype == nil { err = errors.New("rpc: can't find method " + req.ServiceMethod) } @@ -612,6 +617,7 @@ func RegisterName(name string, rcvr interface{}) error { type ServerCodec interface { ReadRequestHeader(*Request) error ReadRequestBody(interface{}) error + // WriteResponse must be safe for concurrent use by multiple goroutines. WriteResponse(*Response, interface{}) error Close() error diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go index eb17210..3b9a883 100644 --- a/libgo/go/net/rpc/server_test.go +++ b/libgo/go/net/rpc/server_test.go @@ -84,6 +84,7 @@ func listenTCP() (net.Listener, string) { func startServer() { Register(new(Arith)) + RegisterName("net.rpc.Arith", new(Arith)) var l net.Listener l, serverAddr = listenTCP() @@ -97,11 +98,13 @@ func startServer() { func startNewServer() { newServer = NewServer() newServer.Register(new(Arith)) + newServer.RegisterName("net.rpc.Arith", new(Arith)) + newServer.RegisterName("newServer.Arith", new(Arith)) var l net.Listener l, newServerAddr = listenTCP() log.Println("NewServer test RPC server listening on", newServerAddr) - go Accept(l) + go newServer.Accept(l) newServer.HandleHTTP(newHttpPath, "/bar") httpOnce.Do(startHttpServer) @@ -118,6 +121,7 @@ func TestRPC(t *testing.T) { testRPC(t, serverAddr) newOnce.Do(startNewServer) testRPC(t, newServerAddr) + testNewServerRPC(t, newServerAddr) } func testRPC(t *testing.T, addr string) { @@ -125,6 +129,7 @@ func testRPC(t *testing.T, addr string) { if err != nil { t.Fatal("dialing", err) } + defer client.Close() // Synchronous calls args := &Args{7, 8} @@ -233,6 +238,36 @@ func testRPC(t *testing.T, addr string) { if reply.C != args.A*args.B { t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B) } + + // ServiceName contain "." character + args = &Args{7, 8} + reply = new(Reply) + err = client.Call("net.rpc.Arith.Add", args, reply) + if err != nil { + t.Errorf("Add: expected no error but got string %q", err.Error()) + } + if reply.C != args.A+args.B { + t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) + } +} + +func testNewServerRPC(t *testing.T, addr string) { + client, err := Dial("tcp", addr) + if err != nil { + t.Fatal("dialing", err) + } + defer client.Close() + + // Synchronous calls + args := &Args{7, 8} + reply := new(Reply) + err = client.Call("newServer.Arith.Add", args, reply) + if err != nil { + t.Errorf("Add: expected no error but got string %q", err.Error()) + } + if reply.C != args.A+args.B { + t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B) + } } func TestHTTP(t *testing.T) { @@ -253,6 +288,7 @@ func testHTTPRPC(t *testing.T, path string) { if err != nil { t.Fatal("dialing", err) } + defer client.Close() // Synchronous calls args := &Args{7, 8} @@ -329,6 +365,7 @@ func TestServeRequest(t *testing.T) { func testServeRequest(t *testing.T, server *Server) { client := CodecEmulator{server: server} + defer client.Close() args := &Args{7, 8} reply := new(Reply) @@ -411,6 +448,7 @@ func (WriteFailCodec) Close() error { func TestSendDeadlock(t *testing.T) { client := NewClientWithCodec(WriteFailCodec(0)) + defer client.Close() done := make(chan bool) go func() { @@ -449,6 +487,8 @@ func countMallocs(dial func() (*Client, error), t *testing.T) float64 { if err != nil { t.Fatal("error dialing", err) } + defer client.Close() + args := &Args{7, 8} reply := new(Reply) return testing.AllocsPerRun(100, func() { @@ -463,6 +503,9 @@ func countMallocs(dial func() (*Client, error), t *testing.T) float64 { } func TestCountMallocs(t *testing.T) { + if testing.Short() { + t.Skip("skipping malloc count in short mode") + } if runtime.GOMAXPROCS(0) > 1 { t.Skip("skipping; GOMAXPROCS>1") } @@ -470,6 +513,9 @@ func TestCountMallocs(t *testing.T) { } func TestCountMallocsOverHTTP(t *testing.T) { + if testing.Short() { + t.Skip("skipping malloc count in short mode") + } if runtime.GOMAXPROCS(0) > 1 { t.Skip("skipping; GOMAXPROCS>1") } @@ -496,6 +542,8 @@ func (writeCrasher) Write(p []byte) (int, error) { func TestClientWriteError(t *testing.T) { w := &writeCrasher{done: make(chan bool)} c := NewClient(w) + defer c.Close() + res := false err := c.Call("foo", 1, &res) if err == nil { @@ -552,6 +600,7 @@ func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) { if err != nil { b.Fatal("error dialing:", err) } + defer client.Close() // Synchronous calls args := &Args{7, 8} @@ -587,6 +636,7 @@ func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) { if err != nil { b.Fatal("error dialing:", err) } + defer client.Close() // Asynchronous calls args := &Args{7, 8} |