rpc_request_task::rpc_request_task(message_ptr& request, service_node* node) : task(task_code(request->header().local_rpc_code), request->header().client.hash, node), _request(request) { dbg_dassert (TASK_TYPE_RPC_REQUEST == spec().type, "task type must be RPC_REQUEST, please use DEFINE_TASK_CODE_RPC to define the task code"); }
void sim_client_session::send(message_ptr& msg) { sim_network_provider* rnet = nullptr; if (!s_switch[task_spec::get(msg->header().local_rpc_code)->rpc_call_channel].get(msg->header().to_address, rnet)) { dwarn("cannot find destination node %s:%d in simulator", msg->header().to_address.name.c_str(), static_cast<int>(msg->header().to_address.port) ); return; } auto server_session = rnet->get_server_session(_net.address()); if (nullptr == server_session) { rpc_client_session_ptr cptr = this; server_session.reset(new sim_server_session(*rnet, _net.address(), cptr)); rnet->on_server_session_accepted(server_session); } message_ptr recv_msg(new message(msg->writer().get_buffer())); recv_msg->header().from_address = msg->header().from_address; recv_msg->header().to_address = msg->header().to_address; server_session->on_recv_request(recv_msg, recv_msg->header().from_address == recv_msg->header().to_address ? 0 : rnet->net_delay_milliseconds() ); }
void rpc_server_session::on_recv_request(message_ptr& msg, int delay_ms) { msg->header().from_address = remote_address(); msg->header().from_address.port = msg->header().client.port; msg->header().to_address = _net.address(); msg->server_session().reset(this); return _net.on_recv_request(msg, delay_ms); }
void sim_server_session::send(message_ptr& reply_msg) { message_ptr recv_msg(new message(reply_msg->writer().get_buffer())); recv_msg->header().from_address = reply_msg->header().from_address; recv_msg->header().to_address = reply_msg->header().to_address; _client->on_recv_reply(recv_msg->header().id, recv_msg, recv_msg->header().from_address == recv_msg->header().to_address ? 0 : (static_cast<sim_network_provider*>(&_net))->net_delay_milliseconds() ); }
rpc_response_task::rpc_response_task(message_ptr& request, int hash) : task(task_spec::get(request->header().local_rpc_code)->rpc_paired_code, hash == 0 ? request->header().client.hash : hash) { set_error_code(ERR_IO_PENDING); dbg_dassert (TASK_TYPE_RPC_RESPONSE == spec().type, "task must be of RPC_RESPONSE type, please use DEFINE_TASK_CODE_RPC to define the request task code"); _request = request; _caller_pool = task::get_current_worker() ? task::get_current_worker()->pool() : nullptr; }
bool rpc_client_session::on_recv_reply(uint64_t key, message_ptr& reply, int delay_ms) { if (reply != nullptr) { reply->header().from_address = remote_address(); reply->header().to_address = _net.address(); } return _matcher->on_recv_reply(key, reply, delay_ms); }
void client_net_io::write(message_ptr& msg) { _sq.enqueue(msg, task_spec::get(msg->header().local_rpc_code)->priority); // not connected if (SS_CONNECTED != _state) { return; } do_write(); }
void replica::response_client_message(message_ptr& request, error_code error, decree d/* = invalid_decree*/) { if (nullptr == request) return; message_ptr resp = request->create_response(); resp->writer().write(error); dassert(error != ERR_OK, ""); dinfo("handle replication request with rpc_id = %016llx failed, err = %s", request->header().rpc_id, error.to_string()); rpc::reply(resp); }
void connection_oriented_network::call(message_ptr& request, rpc_response_task_ptr& call) { rpc_client_session_ptr client = nullptr; end_point& to = request->header().to_address; bool new_client = false; // TODO: thread-local client ptr cache { utils::auto_read_lock l(_clients_lock); auto it = _clients.find(to); if (it != _clients.end()) { client = it->second; } } if (nullptr == client.get()) { utils::auto_write_lock l(_clients_lock); auto it = _clients.find(to); if (it != _clients.end()) { client = it->second; } else { client = create_client_session(to); _clients.insert(client_sessions::value_type(to, client)); new_client = true; } } // init connection if necessary if (new_client) client->connect(); // rpc call client->call(request, call); }
void replication_app_client_base::query_partition_configuration_reply(error_code err, message_ptr& request, message_ptr& response, int pidx) { if (!err) { configuration_query_by_index_response resp; unmarshall(response->reader(), resp); if (resp.err == ERR_SUCCESS) { zauto_write_lock l(_config_lock); _last_contact_point = response->header().from_address; if (resp.partitions.size() > 0) { if (_app_id != -1 && _app_id != resp.partitions[0].gpid.app_id) { dassert(false, "app id is changed (mostly the app was removed and created with the same name), local Vs remote: %u vs %u ", _app_id, resp.partitions[0].gpid.app_id); } _app_id = resp.partitions[0].gpid.app_id; _app_partition_count = resp.partition_count; } for (auto it = resp.partitions.begin(); it != resp.partitions.end(); it++) { partition_configuration& new_config = *it; auto it2 = _config_cache.find(new_config.gpid.pidx); if (it2 == _config_cache.end()) { _config_cache[new_config.gpid.pidx] = new_config; } else if (it2->second.ballot < new_config.ballot) { it2->second = new_config; } } } } // send pending client msgs partition_context* pc = nullptr; { zauto_lock l(_requests_lock); auto it = _pending_requests.find(pidx); if (it != _pending_requests.end()) { pc = it->second; _pending_requests.erase(pidx); } } if (pc != nullptr) { for (auto& req : pc->requests) { call(req, false); } pc->requests.clear(); delete pc; } }
void net_io::write(message_ptr& msg) { _sq.enqueue(msg, task_spec::get(msg->header().local_rpc_code)->priority); do_write(); }
void replica::on_prepare_reply(std::pair<mutation_ptr, partition_status> pr, int err, message_ptr& request, message_ptr& reply) { check_hashed_access(); mutation_ptr& mu = pr.first; partition_status targetStatus = pr.second; // skip callback for old mutations if (mu->data.header.ballot < get_ballot() || PS_PRIMARY != status()) return; dassert (mu->data.header.ballot == get_ballot(), ""); end_point node = request->header().to_address; partition_status st = _primary_states.GetNodeStatus(node); // handle reply prepare_ack resp; // handle error if (err) { resp.err = err; } else { unmarshall(reply, resp); ddebug( "%s: mutation %s on_prepare_reply from %s:%d", name(), mu->name(), node.name.c_str(), static_cast<int>(node.port) ); } if (resp.err == ERR_SUCCESS) { dassert (resp.ballot == get_ballot(), ""); dassert (resp.decree == mu->data.header.decree, ""); switch (targetStatus) { case PS_SECONDARY: dassert (_primary_states.check_exist(node, PS_SECONDARY), ""); dassert (mu->left_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_secondary_ack_count()) { do_possible_commit_on_primary(mu); } break; case PS_POTENTIAL_SECONDARY: dassert (mu->left_potential_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_potential_secondary_ack_count()) { do_possible_commit_on_primary(mu); } break; default: ddebug( "%s: mutation %s prepare ack skipped coz the node is now inactive", name(), mu->name() ); break; } } // failure handling else { // note targetStatus and (curent) status may diff if (targetStatus == PS_POTENTIAL_SECONDARY) { dassert (mu->left_potential_secondary_ack_count() > 0, ""); if (0 == mu->decrease_left_potential_secondary_ack_count()) { do_possible_commit_on_primary(mu); } } handle_remote_failure(st, node, resp.err); } }