If the server sends a server shutdown error, it is safe for readwritesplit
to ignore it. When the TCP connection is closed, the router error handling
will discard the connection, optionally replacing it.
If a server responds when no response was expected, dump stored
statements. This should help deduce root causes of problems relating to
unexpected responses.
The resultset processing for MySQL requires some extra work as it lacks
the proper SERVER_MORE_RESULTS_EXIST flag in the last EOF packet. Instead,
the first EOF packet has the SERVER_PS_OUT_PARAMS flag which needs to be
interpreted as a SERVER_MORE_RESULTS_EXIST flag for the second EOF packet.
Also corrected the EOF packet handling to do the flag checks in the code
that deals with the EOF packets.
As the modutil_state parameter is now used for more than large packet
tracking, the correct solution is to store this state object in the
readwritesplit session instead of interpreting it to a boolean value.
The commands needs to be handled separately from the rest of the result
types.
Added a test case that reproduces the problem and verifies that the change
in code fixes it.
The COM_STMT_FETCH command will create a response. This was a
readwritesplit-specific interpretation of the command and it was wrong.
Also record the currently executed command event for session commands.
Readwritesplit would not handle multiple overlapping COM_STMT_EXECUTE
commands properly if they opened cursors. This was due to the fact that
the result would not be marked as complete and COM_STMT_FETCH commands
were executed as if they did not return results.
The correct implementation is to consider a COM_STMT_EXECUTE that opens a
cursor complete only when the first EOF packet is read (that is, when the
resultset header is read). This allows subsequent COM_STMT_FETCH commands
to be handled separately.
The separate COM_STMT_FETCH handling must count the number of packets that
are being fetched. This allows correct tracking of the state of a
COM_STMT_FETCH by checking that the number of packets is correct or the
second EOF/ERR packet is read.
When a LOAD DATA LOCAL INFILE is actively rejected by the server, the
server sends an error to the client. This error was not detected and the
router was stuck in the special mode that handles LOAD DATA LOCAL INFILE.
When a multi-statement query consisting completely of UPDATE statements is
received, the packets can be received in two separate buffers. To cope
with this situation, the state change into REPLY_STATE_RSET_COLDEF must
only be done if the buffer contains more than a single packet.
When readwritesplit receives a reply from a backend, an info level log
message is now logged. This allows easier debugging of situations where
replies aren't properly returned by the router.
Removed false error message about failed session commands. An error in
response to a session command is a perfectly valid result.
Also added the explicit commands that the master and slave return to the
warning that is logged when the results differ.
The default value for strict_multi_stmt prevents compound statements and
atomic multi-statement commands from being executed without completely
disabling load balancing. As the new default value will have no practical
effect on all correct uses of readwritesplit, this is a relatively safe
thing to change.
When binary data was processed, it was possible that the values were
misinterpreted as OK packets which caused debug assertions to trigger.
In addition to this, readwritesplit did not handle the case when all
packets were routed individually.
A multi-statements can return multiple resultsets in one response. To
accommodate for this, both the readwritesplit and modutil code must be
altered.
By ignoring complete resultsets in readwritesplit, the code can deduce
whether a result is complete or not.
Returning the results of a query as a set of packets is currently more
efficient. This is mainly due to the fact that each individual packet for
single packet routing is allocated from the heap which causes a
significant loss in performance.
Took the new capability into use in readwritesplit and modified the
reply_is_complete function to work with non-contiguous results.
The multi-statement detection did not check for the existence of
semicolons before doing the heavier processing.
Calculcate the packet length only once for the result state management.
Replace the original version of the function with the reference version
and use it everywhere. Added runtime assertions to check that an invalid
DCB is never processed.
As the DCB passed as the clientReply parameter is guaranteed to match one
of the DCBs in the RWBackends. By using a reference, the need to copy a
shared_ptr is removed (along with the atomic operation that it implies)
thus reducing the overhead in the clientReply and the functions it uses.
The result collection did not reset properly when a non-resultset was
returned for a request. As collected result need to be distinguishable
from single packet responses, a new buffer type was added.
The new buffer type is used by readwritesplit which uses result collection
for preparation of prepared statements.
Moved the current command tracking to the RWBackend class as the command
tracked by the protocol is can change before a response to the executed
command is received.
Removed a false debug assertion in the mxs_mysql_extract_ps_response
function that was triggered when a very large prepared statement response
was processed in multiple parts.
Inlined the getter/setter type functions that are often used. Profiling
shows that inlining the RWBackend get/set functions for the reply state
manipulation reduces the relative cost of the function to acceptable
levels. Inlining the Backend state function did not have as large an
effect but it appears contribute a slight performance boost.
The result processing code did unnecessary work to confirm that the result
buffers are contiguous. The code also assumed that multiple packets can be
routed at the same time when in fact only one contiguous result packet is
returned at a time.
By assuming that the buffers are contiguous and contain only one packet,
most of the copying and buffer manipulation can be avoided.
When readwritesplit is routing any queued queries, the currently executed
command of the protocol modules needs to be adjusted by
readwritesplit. This is not a true fix but more of a workaround to fix the
problems of queued query execution.
The correct solution would be to move the queued query handling into the
client protocol module so that all components see the same state.
The enums exposed by the connector are not intended to be used by the
users of the library. The fact that the protocol, and other, modules used
it was in violation of how the library is intended to be used.
Adding an internal mapping into MaxScale also removes some of the
dependencies that the core has on the connector.
Cleaned up the MaxScale version of the mysql.h header by removing all
unused includes. This revealed a large amount of dependencies on these
removed includes in other files which needed to be fixed.
Also sorted all includes in changed files by type and alphabetical
order. Removed explicit revision history from modified files.
The EOF packet calculation function in modutil.cc didn't handle the case
where the payload exceeded maximum packet size and could mistake binary
data for a ERR packet.
The state of a multi-packet payload is now exposed by the
modutil_count_signal_packets function. This allows proper handling of
large multi-packet payloads.
Added minor improvements to mxs1110_16mb to handle testing of this change.
The connections for a router session can now be done without a constructed
router session. This simplifies the creation of new router session by
removing the need to handle memory allocations.
Readwritesplit router sessions are now created in the static `create`
function which handles the actual creation of the connections and
allocation of the session itself.
Moved the initialization of the router session's member variables into the
constructor. Changed two functions that calculated server counts into the
router instance as they don't relate to a particular session.
When a read was successfully retried, the original expected response was
not decremented from the reponse counter. This caused one extra response
to be expected for successfully retried reads which caused a hang after a
retried read.
When a session command was executed and the last slave that was executing
dies, readwritesplit would route any pending queries before closing the
slave connection. This could cause a hang if the routing logic decided to
pick the failed server as the target of the stored query.
This fixes the MXS-1323 related regression in the develop branch.
The backend server can send a response even if the client hasn't sent a
request. One case where this occurs is when the server is shutting
down. The internal logic of readwritesplit can't handle unexpected states
gracefully so the safest thing to do is to just ignore them and send the
responses to the client.
Providing helper functions for the commonly used parts of the server makes
code easier to read. It also removes any possibility for formatting
problems by moving the URI and name string handling inside the Backend
class.
Added helper functions that check various server states. This makes the
readwritesplit code easier to read as the function names convey the
intention better than the macro invokations.
Renamed variables to better represent the types of variables they
represent. Reordered some of the functions so that the functions don't
need to be declared before they are used.
Return values instead of objects. This removes the need to handle cases
where a reference to a "debug value" is returned.
Return SRWBackend values instead of passing output references. This
doubles as a false boolan return value when an empty reference is
returned.