hpx::naming::id_type const& interpolator::get_id(double ye, double temp, double rho) const { std::size_t x = get_partition_index(dimension::ye, ye); std::size_t y = get_partition_index(dimension::temp, std::log10(temp)); std::size_t z = get_partition_index(dimension::rho, std::log10(rho)); std::size_t index = x + (y + z * num_partitions_per_dim_) * num_partitions_per_dim_; HPX_ASSERT(index < partitions_.size()); return partitions_[index]; }
void partition_resolver_simple::query_config_reply(error_code err, dsn_message_t request, dsn_message_t response, int partition_index) { auto client_err = ERR_OK; if (err == ERR_OK) { configuration_query_by_index_response resp; unmarshall(response, resp); if (resp.err == ERR_OK) { zauto_write_lock l(_config_lock); if (_app_id != -1 && _app_id != resp.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.app_id); } if (_app_partition_count != -1 && _app_partition_count != resp.partition_count) { dassert(false, "partition count is changed (mostly the app was removed and created with the same name), local Vs remote: %u vs %u ", _app_partition_count, resp.partition_count); } _app_id = resp.app_id; _app_partition_count = resp.partition_count; _app_is_stateful = resp.is_stateful; for (auto it = resp.partitions.begin(); it != resp.partitions.end(); ++it) { auto& new_config = *it; dinfo("%s.client: query config reply, gpid = %d.%d, ballot = %" PRId64 ", primary = %s", _app_path.c_str(), new_config.pid.get_app_id(), new_config.pid.get_partition_index(), new_config.ballot, new_config.primary.to_string() ); auto it2 = _config_cache.find(new_config.pid.get_partition_index()); if (it2 == _config_cache.end()) { std::unique_ptr<partition_info> pi(new partition_info); pi->timeout_count = 0; pi->config = new_config; _config_cache.emplace(new_config.pid.get_partition_index(), std::move(pi)); } else if (_app_is_stateful && it2->second->config.ballot < new_config.ballot) { it2->second->timeout_count = 0; it2->second->config = new_config; } else if (!_app_is_stateful) { it2->second->timeout_count = 0; it2->second->config = new_config; } else { // nothing to do } } } else if (resp.err == ERR_OBJECT_NOT_FOUND) { derror("%s.client: query config reply, gpid = %d.%d, err = %s", _app_path.c_str(), _app_id, partition_index, resp.err.to_string() ); client_err = ERR_APP_NOT_EXIST; } else { derror("%s.client: query config reply, gpid = %d.%d, err = %s", _app_path.c_str(), _app_id, partition_index, resp.err.to_string() ); client_err = resp.err; } } else { derror("%s.client: query config reply, gpid = %d.%d, err = %s", _app_path.c_str(), _app_id, partition_index, err.to_string() ); } // get specific or all partition update if (partition_index != -1) { partition_context* pc = nullptr; { zauto_lock l(_requests_lock); auto it = _pending_requests.find(partition_index); if (it != _pending_requests.end()) { pc = it->second; _pending_requests.erase(partition_index); } } if (pc) { handle_pending_requests(pc->requests, client_err); delete pc; } } // get all partition update else { pending_replica_requests reqs; std::deque<request_context_ptr> reqs2; { zauto_lock l(_requests_lock); reqs.swap(_pending_requests); reqs2.swap(_pending_requests_before_partition_count_unknown); } if (!reqs2.empty()) { if (_app_partition_count != -1) { for (auto& req : reqs2) { dassert(req->partition_index == -1, ""); req->partition_index = get_partition_index(_app_partition_count, req->partition_hash); } } handle_pending_requests(reqs2, client_err); } for (auto& r : reqs) { if (r.second) { handle_pending_requests(r.second->requests, client_err); delete r.second; } } } }
void replication_app_client_base::call(request_context_ptr request, bool from_meta_ack) { if (from_meta_ack) { zauto_lock l(request->lock); if (request->completed) return; } auto nts = ::dsn_now_us(); // timeout will happen very soon, no way to get the rpc call done if (nts + 100 >= request->timeout_ts_us) // within 100 us { dsn_message_t nil(nullptr); end_request(request, ERR_TIMEOUT, nil); return; } // calculate timeout int timeout_ms; if (nts + 1000 > request->timeout_ts_us) timeout_ms = 1; else timeout_ms = static_cast<int>(request->timeout_ts_us - nts) / 1000; // fill partition index if (_app_partition_count == -1) { zauto_lock l(_requests_lock); query_partition_config(request); return; } else { request->partition_index = get_partition_index(_app_partition_count, request->key_hash); } // fill target address ::dsn::rpc_address addr; error_code err = get_address(request->partition_index, !request->is_read, addr, request->read_header.semantic); // target address known if (err == ERR_OK) { call_with_address(addr, request); } // target node not known else { if (from_meta_ack) { // delay 1 second for further config query, call again tasking::enqueue(LPC_REPLICATION_DELAY_QUERY_CONFIG, this, std::bind(&replication_app_client_base::call, this, request, false), 0, 1000 ); } else { // init timeout timer only when necessary // DO NOT START THE TIMER FOR EACH REQUEST { zauto_lock l(request->lock); if (request->timeout_timer == nullptr) { request->timeout_timer = tasking::enqueue( LPC_REPLICATION_CLIENT_REQUEST_TIMEOUT, this, std::bind(&replication_app_client_base::on_replica_request_timeout, this, request), 0, timeout_ms ); } } zauto_lock l(_requests_lock); // put into pending queue of querying target partition auto it = _pending_replica_requests.find(request->partition_index); if (it == _pending_replica_requests.end()) { auto pc = new partition_context; pc->query_config_task = nullptr; it = _pending_replica_requests.insert(pending_replica_requests::value_type(request->partition_index, pc)).first; } it->second->requests.push_back(request); // init configuration query task if necessary if (it->second->query_config_task == nullptr) { it->second->query_config_task = query_partition_config(request); } } } }