-
Notifications
You must be signed in to change notification settings - Fork 110
[k2] fix TlRpcError::try_fetch #1518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,68 +4,27 @@ | |
|
|
||
| #include "runtime-light/stdlib/rpc/rpc-tl-error.h" | ||
|
|
||
| #include <tuple> | ||
| #include <variant> | ||
|
|
||
| #include "common/tl/constants/common.h" | ||
| #include "runtime-light/stdlib/diagnostics/exception-functions.h" | ||
| #include "runtime-light/stdlib/rpc/rpc-api.h" | ||
| #include "runtime-light/stdlib/rpc/rpc-tl-builtins.h" | ||
| #include "runtime-light/server/rpc/rpc-server-state.h" | ||
| #include "runtime-light/tl/tl-core.h" | ||
| #include "runtime-light/tl/tl-types.h" | ||
|
|
||
| bool TlRpcError::try_fetch() noexcept { | ||
| const auto backup_pos{tl_parse_save_pos()}; | ||
| auto op{TRY_CALL(decltype(f$fetch_int()), bool, f$fetch_int())}; | ||
| if (op == TL_REQ_RESULT_HEADER) { | ||
| fetch_and_skip_header(); | ||
| op = TRY_CALL(decltype(f$fetch_int()), bool, f$fetch_int()); | ||
| } | ||
| if (op != TL_RPC_REQ_ERROR) { | ||
| tl_parse_restore_pos(backup_pos); | ||
| auto fetcher{RpcServerInstanceState::get().tl_fetcher}; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like copying the fetcher here is an error |
||
| const auto backup_pos{fetcher.pos()}; | ||
| tl::ReqResult req_result; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here about init nit: it's better to hide variables in scope unless they are used at the function level
|
||
| if (req_result.fetch(fetcher) && std::holds_alternative<tl::reqResultHeader>(req_result.value)) { | ||
| fetcher = tl::fetcher{std::get<tl::reqResultHeader>(req_result.value).result}; | ||
| } else { | ||
| fetcher.reset(backup_pos); | ||
| } | ||
| tl::RpcReqResult rpc_req_result; | ||
| if (!rpc_req_result.fetch(fetcher) || !std::holds_alternative<tl::rpcReqError>(rpc_req_result.value)) { | ||
| return false; | ||
| } | ||
|
|
||
| std::ignore = TRY_CALL(decltype(f$fetch_long()), bool, f$fetch_long()); | ||
| error_code = static_cast<int32_t>(TRY_CALL(decltype(f$fetch_int()), bool, f$fetch_int())); | ||
| error_msg = TRY_CALL(decltype(f$fetch_string()), bool, f$fetch_string()); | ||
| auto& rpc_req_error{std::get<tl::rpcReqError>(rpc_req_result.value)}; | ||
| error_code = rpc_req_error.error_code.value; | ||
| error_msg = {rpc_req_error.error.value.data(), static_cast<string::size_type>(rpc_req_error.error.value.size())}; | ||
| return true; | ||
| } | ||
|
|
||
| void TlRpcError::fetch_and_skip_header() const noexcept { | ||
| const auto flags{static_cast<int32_t>(TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()))}; | ||
|
|
||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::binlog_pos) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_long()), void, f$fetch_long()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::binlog_time) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_long()), void, f$fetch_long()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::engine_pid) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::request_size) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::response_size) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::failed_subqueries) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::compression_version) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::stats) { | ||
| const auto size{TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int())}; | ||
| for (auto i = 0; i < size; ++i) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| std::ignore = TRY_CALL(decltype(f$fetch_int()), void, f$fetch_int()); | ||
| } | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::epoch_number) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_long()), void, f$fetch_long()); | ||
| } | ||
| if (flags & vk::tl::common::rpc_req_result_extra_flags::view_number) { | ||
| std::ignore = TRY_CALL(decltype(f$fetch_long()), void, f$fetch_long()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -218,6 +218,58 @@ tl::mask rpcInvokeReqExtra::get_flags() const noexcept { | |
| return flags; | ||
| } | ||
|
|
||
| bool rpcReqResultExtra::fetch(tl::fetcher& tlf, const tl::mask& flags) noexcept { | ||
| if (static_cast<bool>(flags.value & BINLOG_POS_FLAG)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about following implementation? P.S. we need to change types of |
||
| if (!binlog_pos.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & BINLOG_TIME_FLAG)) { | ||
| if (!binlog_time.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value) & ENGINE_PID_FLAG) { | ||
| if (!engine_pid.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & REQUEST_SIZE_FLAG)) { | ||
| kphp::log::assertion(static_cast<bool>(flags.value & RESPONSE_SIZE_FLAG)); | ||
| if (!request_size.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| if (!response_size.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & FAILED_SUBQUERIES_FLAG)) { | ||
| if (!failed_subqueries.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & COMPRESSION_VERSION_FLAG)) { | ||
| if (!compression_version.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & STATS_FLAG)) { | ||
| if (!stats.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| if (static_cast<bool>(flags.value & EPOCH_NUMBER_FLAG)) { | ||
| kphp::log::assertion(static_cast<bool>(flags.value & VIEW_NUMBER_FLAG)); | ||
| if (!epoch_number.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| if (!view_number.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| void rpcReqResultExtra::store(tl::storer& tls, const tl::mask& flags) const noexcept { | ||
| if (static_cast<bool>(flags.value & BINLOG_POS_FLAG)) { | ||
| binlog_pos.store(tls); | ||
|
|
@@ -278,6 +330,36 @@ size_t rpcReqResultExtra::footprint(const tl::mask& flags) const noexcept { | |
| return footprint; | ||
| } | ||
|
|
||
| bool ReqResult::fetch(tl::fetcher& tlf) noexcept { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here about different implementation approach |
||
| const auto backup_pos{tlf.pos()}; | ||
| tl::magic magic; | ||
| if (!magic.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| switch (magic.value) { | ||
| case TL_REQ_ERROR: { | ||
| tl::reqError req_error; | ||
| if (!req_error.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| value = req_error; | ||
| break; | ||
| } | ||
| case TL_REQ_RESULT_HEADER: { | ||
| tl::reqResultHeader req_result_header; | ||
| if (!req_result_header.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| value = req_result_header; | ||
| break; | ||
| } | ||
| default: | ||
| tlf.reset(backup_pos); | ||
| value = *tlf.fetch_bytes(tlf.remaining()); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| } // namespace tl | ||
|
|
||
| namespace tl2 { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1153,6 +1153,7 @@ class rpcReqResultExtra final { | |
| tl::i64 epoch_number{}; | ||
| tl::i64 view_number{}; | ||
|
|
||
| bool fetch(tl::fetcher& tlf, const tl::mask& flags) noexcept; | ||
| void store(tl::storer& tls, const tl::mask& flags) const noexcept; | ||
|
|
||
| size_t footprint(const tl::mask& flags) const noexcept; | ||
|
|
@@ -1166,6 +1167,84 @@ struct RpcReqResultExtra final { | |
| } | ||
| }; | ||
|
|
||
| struct reqError final { | ||
| tl::i32 error_code{}; | ||
| tl::string error{}; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept { | ||
| return error_code.fetch(tlf) && error.fetch(tlf); | ||
| } | ||
| }; | ||
|
|
||
| struct reqResultHeader final { | ||
| tl::mask flags{}; | ||
| tl::rpcReqResultExtra extra{}; | ||
| std::span<const std::byte> result; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept { | ||
| if (!flags.fetch(tlf) || !extra.fetch(tlf, flags)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| result = *tlf.fetch_bytes(tlf.remaining()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not skip check for the result of |
||
| return true; | ||
| } | ||
| }; | ||
|
|
||
| struct ReqResult final { | ||
| std::variant<tl::reqError, tl::reqResultHeader, std::span<const std::byte>> value; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept; | ||
| }; | ||
|
|
||
| struct rpcReqResult final { | ||
| tl::ReqResult result{}; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept { | ||
| return tl::i64{}.fetch(tlf) && result.fetch(tlf); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you skip |
||
| } | ||
| }; | ||
|
|
||
| struct rpcReqError final { | ||
| tl::i32 error_code{}; | ||
| tl::string error{}; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept { | ||
| return tl::i64{}.fetch(tlf) && error_code.fetch(tlf) && error.fetch(tlf); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for |
||
| } | ||
| }; | ||
|
|
||
| struct RpcReqResult final { | ||
| std::variant<tl::rpcReqResult, tl::rpcReqError> value; | ||
|
|
||
| bool fetch(tl::fetcher& tlf) noexcept { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about following implementation? |
||
| tl::magic magic; | ||
| if (!magic.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| switch (magic.value) { | ||
| case TL_RPC_REQ_RESULT: { | ||
| tl::rpcReqResult rpc_req_result; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, don't leave local variables of types |
||
| if (!rpc_req_result.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| value = rpc_req_result; | ||
| break; | ||
| } | ||
| case TL_RPC_REQ_ERROR: { | ||
| tl::rpcReqError rpc_req_error; | ||
| if (!rpc_req_error.fetch(tlf)) [[unlikely]] { | ||
| return false; | ||
| } | ||
| value = rpc_req_error; | ||
| break; | ||
| } | ||
| default: | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }; | ||
|
|
||
| struct k2RpcResponseError final { | ||
| tl::i32 error_code{}; | ||
| tl::string error{}; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not include these changes as they are not mandatory