-
Notifications
You must be signed in to change notification settings - Fork 6
client: fix result
argument of wait
#131
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?
Conversation
d7df387
to
abbe0c2
Compare
result
argumentresult
argument of wait
3c7f774
to
2d9d6cc
Compare
Connector uses a special helper for decoding ready responses and then it erases them from `m_ReadyToDecode` set by himself. That's not a good design and it can lead to various bugs (there is already a bug, actually) because it's easy to forgot to earse the decoded future. So let's move the erasure right to the `connectionDecodeResponses` helper. Note that the helper must be turned into a method of `Connector` then since it needs to use its fields. The above-mentioned bug happens because we decode responses in `Connector::wait` right before the main loop but we forgot to remove the connection from `m_ReadyToDecode` set there. Closes tarantool#124
Method `wait` of `Connector` allows to obtain result directly with `result` argument - it can be useful when the user cares about performance and don't want to perform an unneeded insertion to a map of ready futures. However, we check that the future is ready by looking to the map of ready futures, and the future is not inserted there when the argument is used. The commit fixes the problem by checking the argument as well. Also, the commit handles a situation when user waits for already decoded future using `result` argument. Before the commit, `wait` would return zero return code (success) but the `result` wouldn't be set - user still had to check if it's not in the map of futures. After the commit, already decoded future is moved to `result` as well, so if the function returns successfully, `result` is guaranteed to be set. Part of tarantool#112
Somewhy we cast `nullptr` to the needed class sometimes and it looks ugly. Anyway, `nullptr` is designed to be casted to any pointer automatically, so let's just stop doing it.
Currently, the argument returns any decoded future - that is inconvenient and completely unusable. Let's return only the requested future, or nothing, if it's not ready. Along the way, reformat argument list of modified functions to make them conform clang-format. Closes tarantool#112
2d9d6cc
to
995d5ec
Compare
Ignoring clang-format suggestions in order not to mess with the diff. Suggestionsdiff --git a/src/Client/Connection.hpp b/src/Client/Connection.hpp
index d9626f0..30547e1 100644
--- a/src/Client/Connection.hpp
+++ b/src/Client/Connection.hpp
@@ -228,9 +228,8 @@ public:
friend
bool hasDataToDecode(Connection<B, N> &conn);
- template<class B, class N>
- friend
- enum DecodeStatus processResponse(Connection<B, N> &conn, int req_sync, Response<B> *result);
+ template <class B, class N>
+ friend enum DecodeStatus processResponse(Connection<B, N> &conn, int req_sync, Response<B> *result);
template<class B, class N>
friend
@@ -527,7 +526,7 @@ inputBufGC(Connection<BUFFER, NetProvider> &conn)
}
}
-template<class BUFFER, class NetProvider>
+template <class BUFFER, class NetProvider>
DecodeStatus
processResponse(Connection<BUFFER, NetProvider> &conn, int req_sync, Response<BUFFER> *result)
{
diff --git a/src/Client/Connector.hpp b/src/Client/Connector.hpp
index 863bd28..c0db86e 100644
--- a/src/Client/Connector.hpp
+++ b/src/Client/Connector.hpp
@@ -171,7 +171,7 @@ Connector<BUFFER, NetProvider>::close(ConnectionImpl<BUFFER, NetProvider> &conn)
m_NetProvider.close(conn.strm);
}
-template<class BUFFER, class NetProvider>
+template <class BUFFER, class NetProvider>
int
Connector<BUFFER, NetProvider>::connectionDecodeResponses(Connection<BUFFER, NetProvider> &conn, int req_sync,
Response<BUFFER> *result)
|
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.
Typo in commit comment: "the helper must be turned into a method of `Connector` then since it".
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.
Nit: please reread your commit message. In this patch you are erasing decoded connections, not futures or responses.
src/Client/Connector.hpp
Outdated
DecodeStatus rc = processResponse(conn, result); | ||
if (rc == DECODE_ERR) | ||
return -1; | ||
DecodeStatus status = processResponse(conn, result); |
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.
Nit: excess whitespace after processResponse(conn,
.
if (connectionDecodeResponses(conn, result) != 0) | ||
return -1; | ||
if (result != NULL && result->header.sync != INVALID_SYNC) { | ||
LOG_DEBUG("Future ", future, " is ready and decoded"); |
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.
Can we assert that result->header.sync == future
here and below? I think we should refactor this branch into a separate helper since it repeats more than once.
fail_unless(conn.futureIsReady(f)); | ||
fail_unless(client.wait(conn, f, WAIT_TIMEOUT, &result) == 0); | ||
/* The result was consumed, so the future is not ready. */ | ||
fail_unless(!conn.futureIsReady(f)); |
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.
I think the future semantics are kind of weird right now. If a user tries to wait on this future, he will never get it, right?
Could we track the current sync in the connection and return an error in wait
methods for this? And add something like a valid
method or return 3 possible values from futureIsReady
(false, true, invalid)? Just open a ticket if you agree.
@@ -213,9 +214,10 @@ Connector<BUFFER, NetProvider>::wait(Connection<BUFFER, NetProvider> &conn, | |||
Timer timer{timeout}; | |||
timer.start(); | |||
static constexpr int INVALID_SYNC = -1; | |||
int req_sync = static_cast<int>(future); |
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.
Why don't you just use the rid_t
type everywhere? Would be nice to use integer types consistently across the code base. If you think it's more convenient to pass around an int
right now, but you agree that this looks inconsistent to maintain, please open a ticket.
@@ -266,7 +268,7 @@ Connector<BUFFER, NetProvider>::waitAll(Connection<BUFFER, NetProvider> &conn, | |||
strerror(errno), errno); | |||
return -1; | |||
} | |||
if (connectionDecodeResponses(conn, nullptr) != 0) | |||
if (connectionDecodeResponses(conn, 0, nullptr) != 0) |
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.
Nit: isn't it better to pass the INVALID_SYNC
constant you introduced previously to be consistent?
I would also introduce an overload for connectionDecodeResponses
that accepts only a connection
, since we are in C++ world. But feel free to ignore/defer.
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.
Nit: please reread your commit message. In this patch you are erasing decoded connections, not futures or responses.
The argument was completely broken - the commit fixes it.
Along the way, fixed a crash when a decoded future appeared in
m_ReadyToDecode
. See the commits for details.Closes #112
Closes #124