~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/net/rpc/server.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 
25
25
        where T, T1 and T2 can be marshaled by encoding/gob.
26
26
        These requirements apply even if a different codec is used.
27
 
        (In future, these requirements may soften for custom codecs.)
 
27
        (In the future, these requirements may soften for custom codecs.)
28
28
 
29
29
        The method's first argument represents the arguments provided by the caller; the
30
30
        second argument represents the result parameters to be returned to the caller.
31
31
        The method's return value, if non-nil, is passed back as a string that the client
32
 
        sees as if created by errors.New.
 
32
        sees as if created by errors.New.  If an error is returned, the reply parameter
 
33
        will not be sent back to the client.
33
34
 
34
35
        The server may handle requests on a single connection by calling ServeConn.  More
35
36
        typically it will create a network listener and call Accept or, for an HTTP
111
112
 
112
113
                // Asynchronous call
113
114
                quotient := new(Quotient)
114
 
                divCall := client.Go("Arith.Divide", args, &quotient, nil)
 
115
                divCall := client.Go("Arith.Divide", args, quotient, nil)
115
116
                replyCall := <-divCall.Done     // will be equal to divCall
116
117
                // check errors, print, etc.
117
118
 
181
182
 
182
183
// Server represents an RPC Server.
183
184
type Server struct {
184
 
        mu         sync.Mutex // protects the serviceMap
 
185
        mu         sync.RWMutex // protects the serviceMap
185
186
        serviceMap map[string]*service
186
187
        reqLock    sync.Mutex // protects freeReq
187
188
        freeReq    *Request
218
219
//      - exported method
219
220
//      - two arguments, both pointers to exported structs
220
221
//      - one return value, of type error
221
 
// It returns an error if the receiver is not an exported type or has no
222
 
// suitable methods.
 
222
// It returns an error if the receiver is not an exported type or has
 
223
// no methods or unsuitable methods. It also logs the error using package log.
223
224
// The client accesses each method using a string of the form "Type.Method",
224
225
// where Type is the receiver's concrete type.
225
226
func (server *Server) Register(rcvr interface{}) error {
226
227
        return server.register(rcvr, "", false)
227
228
}
228
229
 
229
 
// RegisterName is like Register but uses the provided name for the type 
 
230
// RegisterName is like Register but uses the provided name for the type
230
231
// instead of the receiver's concrete type.
231
232
func (server *Server) RegisterName(name string, rcvr interface{}) error {
232
233
        return server.register(rcvr, name, true)
260
261
        s.method = make(map[string]*methodType)
261
262
 
262
263
        // Install the methods
263
 
        for m := 0; m < s.typ.NumMethod(); m++ {
264
 
                method := s.typ.Method(m)
 
264
        s.method = suitableMethods(s.typ, true)
 
265
 
 
266
        if len(s.method) == 0 {
 
267
                str := ""
 
268
                // To help the user, see if a pointer receiver would work.
 
269
                method := suitableMethods(reflect.PtrTo(s.typ), false)
 
270
                if len(method) != 0 {
 
271
                        str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
 
272
                } else {
 
273
                        str = "rpc.Register: type " + sname + " has no exported methods of suitable type"
 
274
                }
 
275
                log.Print(str)
 
276
                return errors.New(str)
 
277
        }
 
278
        server.serviceMap[s.name] = s
 
279
        return nil
 
280
}
 
281
 
 
282
// suitableMethods returns suitable Rpc methods of typ, it will report
 
283
// error using log if reportErr is true.
 
284
func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
 
285
        methods := make(map[string]*methodType)
 
286
        for m := 0; m < typ.NumMethod(); m++ {
 
287
                method := typ.Method(m)
265
288
                mtype := method.Type
266
289
                mname := method.Name
267
290
                // Method must be exported.
270
293
                }
271
294
                // Method needs three ins: receiver, *args, *reply.
272
295
                if mtype.NumIn() != 3 {
273
 
                        log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
 
296
                        if reportErr {
 
297
                                log.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
 
298
                        }
274
299
                        continue
275
300
                }
276
301
                // First arg need not be a pointer.
277
302
                argType := mtype.In(1)
278
303
                if !isExportedOrBuiltinType(argType) {
279
 
                        log.Println(mname, "argument type not exported:", argType)
 
304
                        if reportErr {
 
305
                                log.Println(mname, "argument type not exported:", argType)
 
306
                        }
280
307
                        continue
281
308
                }
282
309
                // Second arg must be a pointer.
283
310
                replyType := mtype.In(2)
284
311
                if replyType.Kind() != reflect.Ptr {
285
 
                        log.Println("method", mname, "reply type not a pointer:", replyType)
 
312
                        if reportErr {
 
313
                                log.Println("method", mname, "reply type not a pointer:", replyType)
 
314
                        }
286
315
                        continue
287
316
                }
288
317
                // Reply type must be exported.
289
318
                if !isExportedOrBuiltinType(replyType) {
290
 
                        log.Println("method", mname, "reply type not exported:", replyType)
 
319
                        if reportErr {
 
320
                                log.Println("method", mname, "reply type not exported:", replyType)
 
321
                        }
291
322
                        continue
292
323
                }
293
324
                // Method needs one out.
294
325
                if mtype.NumOut() != 1 {
295
 
                        log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
 
326
                        if reportErr {
 
327
                                log.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
 
328
                        }
296
329
                        continue
297
330
                }
298
331
                // The return type of the method must be error.
299
332
                if returnType := mtype.Out(0); returnType != typeOfError {
300
 
                        log.Println("method", mname, "returns", returnType.String(), "not error")
 
333
                        if reportErr {
 
334
                                log.Println("method", mname, "returns", returnType.String(), "not error")
 
335
                        }
301
336
                        continue
302
337
                }
303
 
                s.method[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
304
 
        }
305
 
 
306
 
        if len(s.method) == 0 {
307
 
                s := "rpc Register: type " + sname + " has no exported methods of suitable type"
308
 
                log.Print(s)
309
 
                return errors.New(s)
310
 
        }
311
 
        server.serviceMap[s.name] = s
312
 
        return nil
 
338
                methods[mname] = &methodType{method: method, ArgType: argType, ReplyType: replyType}
 
339
        }
 
340
        return methods
313
341
}
314
342
 
315
343
// A value sent as a placeholder for the server's response value when the server
538
566
                return
539
567
        }
540
568
        // Look up the request.
541
 
        server.mu.Lock()
 
569
        server.mu.RLock()
542
570
        service = server.serviceMap[serviceMethod[0]]
543
 
        server.mu.Unlock()
 
571
        server.mu.RUnlock()
544
572
        if service == nil {
545
573
                err = errors.New("rpc: can't find service " + req.ServiceMethod)
546
574
                return
568
596
// Register publishes the receiver's methods in the DefaultServer.
569
597
func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }
570
598
 
571
 
// RegisterName is like Register but uses the provided name for the type 
 
599
// RegisterName is like Register but uses the provided name for the type
572
600
// instead of the receiver's concrete type.
573
601
func RegisterName(name string, rcvr interface{}) error {
574
602
        return DefaultServer.RegisterName(name, rcvr)
611
639
}
612
640
 
613
641
// Accept accepts connections on the listener and serves requests
614
 
// to DefaultServer for each incoming connection.  
 
642
// to DefaultServer for each incoming connection.
615
643
// Accept blocks; the caller typically invokes it in a go statement.
616
644
func Accept(lis net.Listener) { DefaultServer.Accept(lis) }
617
645