示例#1
0
// ServiceRPC.Forward is the entry point for RPC calls. It wraps actual RPC calls
// and provides a slot for the RequestInfo. The parameters to the actual RPC
// calls are transmitted in a []byte, and are then marshalled/unmarshalled on
// either end.
func (srpc *ServiceRPC) Forward(in ServiceRPCIn, out *ServiceRPCOut) (err error) {
	m, ok := srpc.methods[in.Method]
	if !ok {
		err = errors.New(fmt.Sprintf("No such method %q", in.Method))
		return
	}

	inValuePtr := reflect.New(m.Type().In(2))

	err = bson.Unmarshal(in.In, inValuePtr.Interface())
	if err != nil {
		return
	}

	// Allocate the out parameter of the RPC call.
	outType := m.Type().In(3)
	var outValue reflect.Value

	switch outType.Kind() {
	case reflect.Ptr:
		outValue = reflect.New(m.Type().In(3).Elem())
	case reflect.Map:
		outValue = reflect.MakeMap(outType)
	default:
		panic("illegal out param type")
	}

	startTime := time.Now().UnixNano()

	params := []reflect.Value{
		reflect.ValueOf(srpc.delegate),
		reflect.ValueOf(in.RequestInfo),
		inValuePtr.Elem(),
		outValue,
	}

	returns := m.Call(params)

	duration := time.Now().UnixNano() - startTime

	mc := MethodCall{
		MethodName:  in.Method,
		RequestInfo: in.RequestInfo,
		Duration:    duration,
	}

	if srpc.log != nil {
		srpc.log.Item(mc)
	}

	out.Out, err = bson.Marshal(outValue.Interface())
	if err != nil {
		return
	}

	erri := returns[0].Interface()
	out.Err, _ = erri.(error)

	return
}
示例#2
0
func (d *Decoder) Decode(pv interface{}) (err error) {
	var lbuf [4]byte
	n, err := d.r.Read(lbuf[:])
	if n == 0 {
		err = io.EOF
		return
	}
	if n != 4 {
		err = errors.New(fmt.Sprintf("Corrupted BSON stream: could only read %d", n))
		return
	}
	if err != nil {
		return
	}

	length := (int(lbuf[0]) << 0) |
		(int(lbuf[1]) << 8) |
		(int(lbuf[2]) << 16) |
		(int(lbuf[3]) << 24)

	buf := make([]byte, length)
	copy(buf[0:4], lbuf[:])
	_, err = d.r.Read(buf[4:])
	if err != nil {
		return
	}

	err = bson.Unmarshal(buf, pv)

	return
}
示例#3
0
func (c *ServiceClient) Send(requestInfo *skynet.RequestInfo, funcName string, in interface{}, outPointer interface{}) (err error) {
	// TODO: timeout logic
	s, err := c.getConnection(0)
	if err != nil {
		c.Log.Item(err)
		return
	}

	if requestInfo == nil {
		requestInfo = &skynet.RequestInfo{
			RequestID: skynet.UUID(),
		}
	}

	sin := service.ServiceRPCIn{
		RequestInfo: requestInfo,
		Method:      funcName,
	}

	sin.In, err = bson.Marshal(in)
	if err != nil {
		return
	}

	sout := service.ServiceRPCOut{}

	// TODO: Check for connectivity issue so that we can try to get another resource out of the pool
	err = s.rpcClient.Call(s.service.Config.Name+".Forward", sin, &sout)
	if err != nil {
		c.Log.Item(err)
	}

	err = bson.Unmarshal(sout.Out, outPointer)
	if err != nil {
		return
	}

	c.connectionPool.Put(s)

	return
}