aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/rpc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2013-11-06 19:49:01 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2013-11-06 19:49:01 +0000
commitf038dae646bac2b31be98ab592c0e5206d2d96f5 (patch)
tree39530b071991b2326f881b2a30a2d82d6c133fd6 /libgo/go/net/rpc
parentf20f261304993444741e0f0a14d3147e591bc660 (diff)
downloadgcc-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.go7
-rw-r--r--libgo/go/net/rpc/debug.go3
-rw-r--r--libgo/go/net/rpc/jsonrpc/server.go3
-rw-r--r--libgo/go/net/rpc/server.go24
-rw-r--r--libgo/go/net/rpc/server_test.go52
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}