// sendRPC sends one or more RPCs to replicas from the supplied // storage.Replica slice. First, replicas which have gossipped // addresses are corraled and then sent via rpc.Send, with requirement // that one RPC to a server must succeed. func (db *DistDB) sendRPC(replicas []storage.Replica, method string, args, replyChanI interface{}) error { if len(replicas) == 0 { return util.Errorf("%s: replicas set is empty", method) } // Build a map from replica address (if gossipped) to args struct // with replica set in header. argsMap := map[net.Addr]interface{}{} for _, replica := range replicas { addr, err := db.nodeIDToAddr(replica.NodeID) if err != nil { glog.V(1).Infof("node %d address is not gossipped", replica.NodeID) continue } // Copy the args value and set the replica in the header. argsVal := reflect.New(reflect.TypeOf(args).Elem()) reflect.Indirect(argsVal).Set(reflect.Indirect(reflect.ValueOf(args))) reflect.Indirect(argsVal).FieldByName("Replica").Set(reflect.ValueOf(replica)) argsMap[addr] = argsVal.Interface() } if len(argsMap) == 0 { return noNodeAddrsAvailErr{util.Errorf("%s: no replica node addresses available via gossip", method)} } rpcOpts := rpc.Options{ N: 1, SendNextTimeout: defaultSendNextTimeout, Timeout: defaultRPCTimeout, } return rpc.Send(argsMap, method, replyChanI, rpcOpts) }
// sendRPC sends one or more RPCs to replicas from the supplied // proto.Replica slice. First, replicas which have gossipped // addresses are corraled and then sent via rpc.Send, with requirement // that one RPC to a server must succeed. func (kv *DistKV) sendRPC(desc *proto.RangeDescriptor, method string, args proto.Request, replyChan interface{}) error { if len(desc.Replicas) == 0 { return util.Errorf("%s: replicas set is empty", method) } // Build a map from replica address (if gossipped) to args struct // with replica set in header. argsMap := map[net.Addr]interface{}{} for _, replica := range desc.Replicas { addr, err := kv.nodeIDToAddr(replica.NodeID) if err != nil { log.V(1).Infof("node %d address is not gossipped", replica.NodeID) continue } // Copy the args value and set the replica in the header. argsVal := reflect.New(reflect.TypeOf(args).Elem()) reflect.Indirect(argsVal).Set(reflect.Indirect(reflect.ValueOf(args))) reflect.Indirect(argsVal).FieldByName("Replica").Set(reflect.ValueOf(replica)) argsMap[addr] = argsVal.Interface() } if len(argsMap) == 0 { return noNodeAddrsAvailError{} } rpcOpts := rpc.Options{ N: 1, SendNextTimeout: defaultSendNextTimeout, Timeout: defaultRPCTimeout, } return rpc.Send(argsMap, method, replyChan, rpcOpts, kv.gossip.TLSConfig()) }