Exemplo n.º 1
0
/*
 * @brief service is implemented by programer, suach as from peloton service
 * interface
 * Therefore, a service has several methods. These methods can be registered
 * using
 * this function
 */
bool RpcServer::RegisterService(google::protobuf::Service *service) {
  // Get the service descriptor
  const google::protobuf::ServiceDescriptor *descriptor =
      service->GetDescriptor();
  std::hash<std::string> string_hash_fn;

  /*
   * Put all of the method names (descriptors), msg types into rpc_method_map_
   * For example, peloton service has HeartBeat method, its
   * request msg type is HeartbeatRequest
   * response msg type is HeartbeatResponse
   */
  for (int i = 0; i < descriptor->method_count(); ++i) {
    // Get the method descriptor
    const google::protobuf::MethodDescriptor *method = descriptor->method(i);

    // Get request and response type through method descriptor
    const google::protobuf::Message *request =
        &service->GetRequestPrototype(method);
    const google::protobuf::Message *response =
        &service->GetResponsePrototype(method);

    // Create the corresponding method structure
    RpcMethod *rpc_method = new RpcMethod(service, request, response, method);

    // Put the method into rpc_method_map_: hashcode-->method
    std::string methodname = std::string(method->full_name());
    // TODO:
    // uint64_t hash = CityHash64(methodname.c_str(), methodname.length());

    // although the return type is size_t, again we should specify the size of
    // the type
    uint64_t hash = string_hash_fn(methodname);
    RpcMethodMap::const_iterator iter = rpc_method_map_.find(hash);
    if (iter == rpc_method_map_.end()) {
      auto pair = std::make_pair(hash, rpc_method);
      rpc_method_map_.insert(pair);
    }
  }

  return true;
}
Exemplo n.º 2
0
/*
 * Channel is only invoked by protobuf rpc client. So this method is sending
 * request msg
 */
void RpcChannel::CallMethod(
    const google::protobuf::MethodDescriptor* method,
    google::protobuf::RpcController* controller,
    const google::protobuf::Message* request,
    UNUSED_ATTRIBUTE google::protobuf::Message* response,
    google::protobuf::Closure* done) {
  PL_ASSERT(request != nullptr);
  /*  run call back function */
  if (done != NULL) {
    done->Run();
  }

  /* Get the rpc function name */
  std::string methodname = std::string(method->full_name());
  std::hash<std::string> string_hash_fn;

  /*  Set the type */
  uint16_t type = MSG_TYPE_REQ;

  /*  Get the hashcode for the rpc function name */
  /*  we use unit64_t because we should specify the exact length */
  uint64_t opcode = string_hash_fn(methodname);

  /* prepare the sending buf */
  uint32_t msg_len = request->ByteSize() + OPCODELEN + TYPELEN;

  /* total length of the message: header length (4bytes) + message length
   * (8bytes + ...) */
  PL_ASSERT(HEADERLEN == sizeof(msg_len));
  char buf[HEADERLEN + msg_len];

  /* copy the header into the buf */
  PL_MEMCPY(buf, &msg_len, sizeof(msg_len));

  /* copy the type into the buf, following the header */
  PL_ASSERT(TYPELEN == sizeof(type));
  PL_MEMCPY(buf + HEADERLEN, &type, TYPELEN);

  /*  copy the hashcode into the buf, following the type */
  PL_ASSERT(OPCODELEN == sizeof(opcode));
  PL_MEMCPY(buf + HEADERLEN + TYPELEN, &opcode, OPCODELEN);

  /*  call protobuf to serialize the request message into sending buf */
  request->SerializeToArray(buf + HEADERLEN + TYPELEN + OPCODELEN,
                            request->ByteSize());

  /*
   * GET a connection to process the rpc send and recv. If there is a associated
   * connection
   * it will be returned. If not, a new connection will be created and connect
   * to server
   */
  Connection* conn = ConnectionManager::GetInstance().CreateConn(
      addr_);  // CreateConn is used for self connect
  // Connection* conn = ConnectionManager::GetInstance().GetConn(addr_);

  /* Connect to server with given address */
  if (conn == NULL) {
    LOG_TRACE("Can't get connection");

    // rpc client use this info to decide whether re-send the message
    controller->SetFailed("Connect Error");

    return;
  }

  /* write data into sending buffer, when using libevent we don't need loop send
   */
  if (conn->AddToWriteBuffer(buf, HEADERLEN + msg_len) == false) {
    LOG_TRACE("Write data Error");
    return;
  }
}