mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
rpc: make more tolerant of errors.
Add Error type to enable clients to distinguish between local and remote errors. Also return "connection shut down error" after the first error return rather than returning the same error each time. R=r CC=golang-dev https://golang.org/cl/4080058
This commit is contained in:
parent
d916cca327
commit
d40ae94993
3 changed files with 131 additions and 120 deletions
|
|
@ -299,7 +299,7 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) os.E
|
|||
|
||||
// A value sent as a placeholder for the response when the server receives an invalid request.
|
||||
type InvalidRequest struct {
|
||||
marker int
|
||||
Marker int
|
||||
}
|
||||
|
||||
var invalidRequest = InvalidRequest{1}
|
||||
|
|
@ -316,6 +316,7 @@ func sendResponse(sending *sync.Mutex, req *Request, reply interface{}, codec Se
|
|||
resp.ServiceMethod = req.ServiceMethod
|
||||
if errmsg != "" {
|
||||
resp.Error = errmsg
|
||||
reply = invalidRequest
|
||||
}
|
||||
resp.Seq = req.Seq
|
||||
sending.Lock()
|
||||
|
|
@ -389,9 +390,28 @@ func (server *Server) ServeConn(conn io.ReadWriteCloser) {
|
|||
func (server *Server) ServeCodec(codec ServerCodec) {
|
||||
sending := new(sync.Mutex)
|
||||
for {
|
||||
// Grab the request header.
|
||||
req := new(Request)
|
||||
err := codec.ReadRequestHeader(req)
|
||||
req, service, mtype, err := server.readRequest(codec)
|
||||
if err != nil {
|
||||
if err != os.EOF {
|
||||
log.Println("rpc:", err)
|
||||
}
|
||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
||||
break
|
||||
}
|
||||
// discard body
|
||||
codec.ReadRequestBody(new(interface{}))
|
||||
|
||||
// send a response if we actually managed to read a header.
|
||||
if req != nil {
|
||||
sendResponse(sending, req, invalidRequest, codec, err.String())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the argument value.
|
||||
argv := _new(mtype.ArgType)
|
||||
replyv := _new(mtype.ReplyType)
|
||||
err = codec.ReadRequestBody(argv.Interface())
|
||||
if err != nil {
|
||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
|
|
@ -399,44 +419,45 @@ func (server *Server) ServeCodec(codec ServerCodec) {
|
|||
}
|
||||
break
|
||||
}
|
||||
s := "rpc: server cannot decode request: " + err.String()
|
||||
sendResponse(sending, req, invalidRequest, codec, s)
|
||||
break
|
||||
}
|
||||
serviceMethod := strings.Split(req.ServiceMethod, ".", -1)
|
||||
if len(serviceMethod) != 2 {
|
||||
s := "rpc: service/method request ill-formed: " + req.ServiceMethod
|
||||
sendResponse(sending, req, invalidRequest, codec, s)
|
||||
continue
|
||||
}
|
||||
// Look up the request.
|
||||
server.Lock()
|
||||
service, ok := server.serviceMap[serviceMethod[0]]
|
||||
server.Unlock()
|
||||
if !ok {
|
||||
s := "rpc: can't find service " + req.ServiceMethod
|
||||
sendResponse(sending, req, invalidRequest, codec, s)
|
||||
continue
|
||||
}
|
||||
mtype, ok := service.method[serviceMethod[1]]
|
||||
if !ok {
|
||||
s := "rpc: can't find method " + req.ServiceMethod
|
||||
sendResponse(sending, req, invalidRequest, codec, s)
|
||||
continue
|
||||
}
|
||||
// Decode the argument value.
|
||||
argv := _new(mtype.ArgType)
|
||||
replyv := _new(mtype.ReplyType)
|
||||
err = codec.ReadRequestBody(argv.Interface())
|
||||
if err != nil {
|
||||
log.Println("rpc: tearing down", serviceMethod[0], "connection:", err)
|
||||
sendResponse(sending, req, replyv.Interface(), codec, err.String())
|
||||
break
|
||||
continue
|
||||
}
|
||||
go service.call(sending, mtype, req, argv, replyv, codec)
|
||||
}
|
||||
codec.Close()
|
||||
}
|
||||
func (server *Server) readRequest(codec ServerCodec) (req *Request, service *service, mtype *methodType, err os.Error) {
|
||||
// Grab the request header.
|
||||
req = new(Request)
|
||||
err = codec.ReadRequestHeader(req)
|
||||
if err != nil {
|
||||
req = nil
|
||||
if err == os.EOF || err == io.ErrUnexpectedEOF {
|
||||
return
|
||||
}
|
||||
err = os.ErrorString("rpc: server cannot decode request: " + err.String())
|
||||
return
|
||||
}
|
||||
|
||||
serviceMethod := strings.Split(req.ServiceMethod, ".", -1)
|
||||
if len(serviceMethod) != 2 {
|
||||
err = os.ErrorString("rpc: service/method request ill-formed: " + req.ServiceMethod)
|
||||
return
|
||||
}
|
||||
// Look up the request.
|
||||
server.Lock()
|
||||
service = server.serviceMap[serviceMethod[0]]
|
||||
server.Unlock()
|
||||
if service == nil {
|
||||
err = os.ErrorString("rpc: can't find service " + req.ServiceMethod)
|
||||
return
|
||||
}
|
||||
mtype = service.method[serviceMethod[1]]
|
||||
if mtype == nil {
|
||||
err = os.ErrorString("rpc: can't find method " + req.ServiceMethod)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Accept accepts connections on the listener and serves requests
|
||||
// for each incoming connection. Accept blocks; the caller typically
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue