Index: src/pkg/rpc/server.go |
=================================================================== |
--- a/src/pkg/rpc/server.go |
+++ b/src/pkg/rpc/server.go |
@@ -394,7 +394,7 @@ |
func (server *Server) ServeCodec(codec ServerCodec) { |
sending := new(sync.Mutex) |
for { |
- req, service, mtype, err := server.readRequest(codec) |
+ service, mtype, req, argv, replyv, err := server.readRequest(codec) |
if err != nil { |
if err != os.EOF { |
log.Println("rpc:", err) |
@@ -402,9 +402,6 @@ |
if err == os.EOF || err == io.ErrUnexpectedEOF { |
break |
} |
- // discard body |
- codec.ReadRequestBody(nil) |
- |
// send a response if we actually managed to read a header. |
if req != nil { |
server.sendResponse(sending, req, invalidRequest, codec, err.String()) |
@@ -412,37 +409,31 @@ |
} |
continue |
} |
- |
- // Decode the argument value. |
- var argv reflect.Value |
- argIsValue := false // if true, need to indirect before calling. |
- if mtype.ArgType.Kind() == reflect.Ptr { |
- argv = reflect.New(mtype.ArgType.Elem()) |
- } else { |
- argv = reflect.New(mtype.ArgType) |
- argIsValue = true |
- } |
- // argv guaranteed to be a pointer now. |
- replyv := reflect.New(mtype.ReplyType.Elem()) |
- err = codec.ReadRequestBody(argv.Interface()) |
- if err != nil { |
- if err == os.EOF || err == io.ErrUnexpectedEOF { |
- if err == io.ErrUnexpectedEOF { |
- log.Println("rpc:", err) |
- } |
- break |
- } |
- server.sendResponse(sending, req, replyv.Interface(), codec, err.String()) |
- continue |
- } |
- if argIsValue { |
- argv = argv.Elem() |
- } |
go service.call(server, sending, mtype, req, argv, replyv, codec) |
} |
codec.Close() |
} |
+// ServeSingle is like ServeCodec but synchronously serves a single request |
rsc
2011/08/15 16:11:09
suggest ServeRequest instead of ServeSingle.
// S
sougou
2011/08/15 20:17:18
Done.
|
+// without launching a goroutine. It does not close the codec upon completion. |
+func (server *Server) ServeSingle(codec ServerCodec) os.Error { |
+ sending := new(sync.Mutex) |
+ service, mtype, req, argv, replyv, err := server.readRequest(codec) |
+ if err != nil { |
+ if err == os.EOF || err == io.ErrUnexpectedEOF { |
+ return err |
+ } |
+ // send a response if we actually managed to read a header. |
+ if req != nil { |
+ server.sendResponse(sending, req, invalidRequest, codec, err.String()) |
+ server.freeRequest(req) |
+ } |
+ return err |
+ } |
+ service.call(server, sending, mtype, req, argv, replyv, codec) |
+ return nil |
+} |
+ |
func (server *Server) getRequest() *Request { |
server.reqLock.Lock() |
req := server.freeReq |
@@ -483,7 +474,38 @@ |
server.respLock.Unlock() |
} |
-func (server *Server) readRequest(codec ServerCodec) (req *Request, service *service, mtype *methodType, err os.Error) { |
+func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *methodType, req *Request, argv, replyv reflect.Value, err os.Error) { |
+ service, mtype, req, err = server.readRequestHeader(codec) |
+ if err != nil { |
+ if err == os.EOF || err == io.ErrUnexpectedEOF { |
+ return |
+ } |
+ // discard body |
+ codec.ReadRequestBody(nil) |
+ return |
+ } |
+ |
+ // Decode the argument value. |
+ argIsValue := false // if true, need to indirect before calling. |
+ if mtype.ArgType.Kind() == reflect.Ptr { |
+ argv = reflect.New(mtype.ArgType.Elem()) |
+ } else { |
+ argv = reflect.New(mtype.ArgType) |
+ argIsValue = true |
+ } |
+ // argv guaranteed to be a pointer now. |
+ if err = codec.ReadRequestBody(argv.Interface()); err != nil { |
+ return |
+ } |
+ if argIsValue { |
+ argv = argv.Elem() |
+ } |
+ |
+ replyv = reflect.New(mtype.ReplyType.Elem()) |
+ return |
+} |
+ |
+func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, err os.Error) { |
// Grab the request header. |
req = server.getRequest() |
err = codec.ReadRequestHeader(req) |
@@ -568,6 +590,12 @@ |
DefaultServer.ServeCodec(codec) |
} |
+// ServeSingle is like ServeCodec but synchronously serves a single request |
rsc
2011/08/15 16:11:09
same
sougou
2011/08/15 20:17:18
Done.
|
+// without launching a goroutine. It does not close the codec upon completion. |
+func ServeSingle(codec ServerCodec) os.Error { |
+ return DefaultServer.ServeSingle(codec) |
+} |
+ |
// Accept accepts connections on the listener and serves requests |
// to DefaultServer for each incoming connection. |
// Accept blocks; the caller typically invokes it in a go statement. |