-
Notifications
You must be signed in to change notification settings - Fork 455
CDRIVER-4617 Refactor libmongoc to use mcd-rpc #1307
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
Conversation
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.
LGTM, and the new form is often significantly more readable than the prior version.
My only concern is about validation of received messages. I'm unsure how much of a concern it is, or if there are unseen checks that guard against firing assertions.
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.
Nicely done. LGTM with minor comments addressed.
break; | ||
|
||
case MONGOC_OP_CODE_KILL_CURSORS: | ||
BSON_UNREACHABLE ("unexpected MONGOC_OP_CODE_CURSORS ingress"); |
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.
BSON_UNREACHABLE ("unexpected MONGOC_OP_CODE_CURSORS ingress"); | |
BSON_UNREACHABLE ("unexpected MONGOC_OP_KILL_CURSORS ingress"); |
|
||
static void | ||
request_from_insert (request_t *request, const mongoc_rpc_t *rpc); | ||
request_from_insert (request_t *request); |
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.
Consider removing unused mock server functions for receiving the legacy wire protocol:
mock_server_receives_insert
and associated functionsmock_server_receives_bulk_insert
and associated functionsmock_server_receives_update
and associated functionsmock_server_receives_delete
and associated functions
-C driver still uses legacy get more for exhaust cursors inmock_server_receives_getmore
and associated functions_mongoc_cursor_op_getmore_send
.
With the minimum server version of 3.6, I expect the C driver can no longer send any of those protocols. I expect the changes to the mock server for these legacy protocols are not tested.
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.
Even though C Driver still uses legacy OP_GET_MORE, it seems like the mock server receives function is nevertheless not being used anywhere, so will proceed with removing it anyways. Can easily be reverted if we end up needing a test that uses this assertion (hopefully unlikely).
mcd_rpc_op_compressed_get_compressed_message (rpc), | ||
mcd_rpc_op_compressed_get_compressed_message_length (rpc), | ||
ptr + message_header_length, | ||
&actual_uncompressed_size)) { |
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.
&actual_uncompressed_size)) { | |
&actual_uncompressed_size)) { | |
bson_free (ptr); |
RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL, | ||
MONGOC_ERROR_PROTOCOL_INVALID_REPLY, | ||
"message length %" PRId32 | ||
" is not within valid range of 16-%" PRId32 " bytes", | ||
message_length, | ||
server_stream->sd->max_msg_size); |
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.
RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL, | |
MONGOC_ERROR_PROTOCOL_INVALID_REPLY, | |
"message length %" PRId32 | |
" is not within valid range of 16-%" PRId32 " bytes", | |
message_length, | |
server_stream->sd->max_msg_size); | |
RUN_CMD_ERR (MONGOC_ERROR_PROTOCOL, | |
MONGOC_ERROR_PROTOCOL_INVALID_REPLY, | |
"message length %" PRId32 | |
" is not within valid range of %" PRId32 "-%" PRId32 | |
" bytes", | |
message_header_length, | |
message_length, | |
server_stream->sd->max_msg_size); |
Use message_header_length
constant.
"message length %" PRId32 | ||
" is not within valid range of 16-%" PRId32 " bytes", | ||
message_length, | ||
server_stream->sd->max_msg_size); |
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.
Use message_header_length
:
bson_set_error (error,
MONGOC_ERROR_PROTOCOL,
MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
"message length %" PRId32
" is not within valid range of %" PRId32 " -%" PRId32
" bytes",
message_header_length,
message_length,
server_stream->sd->max_msg_size);
message_length += | ||
mcd_rpc_header_set_request_id (rpc, ++cluster->request_id); | ||
message_length += mcd_rpc_header_set_response_to (rpc, 0); | ||
message_length += mcd_rpc_header_set_op_code (rpc, MONGOC_OPCODE_MSG); |
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.
message_length += mcd_rpc_header_set_op_code (rpc, MONGOC_OPCODE_MSG); | |
message_length += mcd_rpc_header_set_op_code (rpc, MONGOC_OP_CODE_MSG); |
It looks correct to me. For some background on A network error may free the
Adding |
Latest changes verified by |
Description
Followup to #1296. This PR replaces
mongoc_rpc_t
withmcd_rpc_message
in libmongoc. This PR deliberately leaves the (now unused)mongoc_rpc_t
utilities to facilitate comparison of equivalent utilities and avoid messy diffs. Themongoc_rpc_t
utilities will be removed in a followup commit.Verified by
this patchthis patch (includes the commit addressing distinct pointer type warnings on Windows).RPC Utility Functions
There are four RPC message utility functions in libmongoc that require new equivalents:
_mongoc_rpc_op_(egress|ingress)_inc
->mcd_rpc_message_(egress|ingress)
_mongoc_rpc_(compress|decompress)
->mcd_rpc_message_(compress|decompress)
_mongoc_rpc_decompress_if_necessary
->mcd_rpc_message_decompress_if_necessary
_mongoc_rpc_reply_get_first_msg
->mcd_rpc_message_get_body
_mongoc_rpc_check_ok
->mcd_rpc_message_check_ok
The new ingress and egress functions are fairly straightforward. Compared to the old
mongoc_rpc_t
equivalents which conflated the counters with conversion from data / to iovecs (partially addressed for the egress case by #1256), themcd_rpc_message
functions completely separate conversion (withfrom_data
andto_iovecs
) from counter increment (withegress
andingress
).The new compression functions (
compress
,decompress
, anddecompress_if_necessary
) remove the dependency onmongoc_cluster_t
by requesting the compressor level (derived from the cluster's URI) explicitly as a parameter instead. They also do not handle ingress/egress counter increments (as currently being done by the_mongoc_rpc_scatter
function) to improve separation of concerns.The
get_first_document
function was renamed toget_body
to better reflect it's intended use (obtaining the Kind 0 section BSON document of an OP_MSG or the first document in an OP_REPLY). The function now properly handles the possibility of the Kind 0 section not being the first section in the OP_MSG, although this freedom does not appear to have been exercised yet by the server.The
check_ok
function is a simple translation and does not require further elaboration.mongoc_cluster_t::request_id
A drive-by fix to make the type of the request ID consistent with its specification and use.
Mock Server
The new
mcd_rpc_message
utilities already exposed inconsistent opcode handling of RPC messages that were addressed in #1280 (caught bymcd_rpc_op_query_get_flags
inassert_request_matches_flags
). This PR contains the changes that led to their discovery. Most of the changes involve improvements to type consistency, greater detail on message parsing failure, and refactors to simplify code (notably, removal of the redundantrpc
parameter for therequest_from_*
functions).Server Monitor Thread
A fairly straightforward one-to-one translation from
mongoc_rpc_t
tomcd_rpc_message
equivalents. Nearby code was updated to improve readability.mongoc-async-cmd
Also fairly straightforward one-to-one translation, but removed the redundant
mongoc_async_cmd::array
data member in favor of local variables to store the iovec structures used for async send operations. The existingmongoc_async_cmd::iovecs
data member is used directly instead (now made an owning pointer).mongoc_cluster_run_command_opquery
Refactored into
_mongoc_cluster_run_command_opquery_send
and_mongoc_cluster_run_command_opquery_recv
. The old implementation used a truly bizarre algorithm when receiving the reply that assumes the message is an OP_REPLY, receiving the incoming bytes as if it is an OP_REPLY, then later realizing it may actually be an OP_COMPRESSED message instead, then reading the remaining bytes of the OP_COMPRESSED message. The implementation was changed to use the more consistent pattern of readingmessageLength
only first, before consuming all the remaining bytes of the incoming message in one go, then validating the opcode of the entire message, also aided by the much nicer-to-use_mongoc_buffer_append_from_stream
interface.mongoc_cluster_run_opmsg
Also refactored into separate
_mongoc_cluster_run_opmsg_send
and_mongoc_cluster_run_opmsg_recv
functions. It's mostly straightforward translation with the exception of more thorough error-handling checks.I remain fairly confused by the inconsistent use of
RUN_CMD_ERR_DECORATE
,_handle_network_error
,server_stream->stream = NULL
, andnetwork_error_reply (reply, cmd)
(including their ordering) in the original code. I would appreciate a closer look into their use to confirm they are being used correctly in the new functions.Cursor Functions
The only major change of note that isn't straightforward one-to-one translation is the use of local
iovecs
instead of themongoc_cluster_t::iov
array object, a small refactor of some blocks of code into_mongoc_cursor_op_*_send
functions, and improved type consistency.