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.
When a backend is waiting for a response but no statement is stored for
the session, the buffer where the stored statement is copied is not
modified. This means that it needs to be initialized to a NULL value.
Added a test that checks that the behavior works as expected even with
persistent connections. A second test reproduces the crash by executing
parallel SET commands while slaves are blocked.
There is still a behavioral problem in readwritesplit. If a session
command is being executed and it fails on a slave, an error is sent to the
client. In this case it would not be necessary to close the session if the
master is still alive.
When a statement is being prepared, the type and name of the statement is
stored in the router session. If the name of a statement to be executed is
found in the map, the query type that stored in the map is used.
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.
As the session commands are always appended to the end of the list, the
name should reflect that action. For this reason, the function was renamed
to append_session_command.
Readwritesplit supports replacement of slave servers by storing all
executed session commands in a list. To make the copying of this list a
bit cleaner, an overload for a list of session commands was added. This
will allow relatively smooth addition of server replacement to all router
modules that use the Backend class.
Making the function allows higher level checking to be done by the derived
class.
The readwritesplit does some of the reply bookkeeping for session commands
in the function. This makes their execution less prone for errors as the
states are always updated correctly whenever a session command is
executed.
Readwritesplit now uses the SessionCommand class as a "master list" of
executed session commands. This allows the session commands to be easily
copied over to slaves that are taken into use after session commands have
already been executed.
Currently, the code doesn't execute the session command history when a
mid-session reconnection occurs. A method to cleanly copy the session
commands needs to be exposed by the Backend class.
Removed old router property code as it is no longer needed when
SessionCommand class used by the Backend class is taken into use.
Removed unnecessary code that is implemented as a part of the Backend
class.
Changed functions to return references to Backends instead of handling raw
DCBs. This introduces a few cases where the code returns a reference when
no reference is actually available. These cases are solved by having an
empty static shared_ptr that is returned in these cases. This is done to
silence any compiler warnings that returning references to local variables
would bring as these should never happen if the code is functioning
properly.
This is the first step to taking the Backend class into use. It is now
used in rwsplit_select_backends.cc and readwritesplit.hh. The module is
not yet functional and doesn't even compile.
Added some helper functions to the Backend class to get easier access to
the server referenced by the SERVER_REF and to check the state of the
backend.
Creating duplicate connections using the Backend class allows the
connections and their handling to be tested at the same time that the old
system is in place. This should make it somewhat easier to grasp what
changes and where when the new implementation is taken into use.
The session commands are now duplicated as SessionCommand objects This
allows for an easier migration from the old session command implementation
to the new one.
The default database can now be manipulated with a set of functions
exposed by the maxscale/protocol/mysql.h header. This removes the need to
handle the structures themselves in the modules and is a step towards
moving the dcb->data contents inside the session.
Reorganized the main source file of readwritesplit. The internal functions
are first followed by the API entry points. The actual module definition
is the last declared object in the file.
The temporary table detection and handling now uses C++ containers to
store the set of temporary tables. The detection also uses the new query
classifier field info API to detect which tables and databases are
targeted.
Cleaned up the readwritesplit main header. The structs were named to their
typedef names so that no code changes are required. The structs should be
renamed if/when they are converted to proper C++ classes.
The `user`, `password`, `version_string` and `weightby` values should be
allocated as a part of the service structure. This allows them to be
modified at runtime without having to worry about memory allocation
problems.
Although this removes the problem of reallocation, it still does not make
the updating of the strings thread-safe. This can cause invalid values to
be read from the service strings.
All routers except the binlogrouter now fully implement the JSON
diagnostic entry point. The binlogrouter needs to be handled in a separate
commit as it produces a large amount of diagnostic output.
When a prepared statement preparation is being routed to the master, the
response is now collected into one buffer before being sent back. This
allows proper processing of pipelined prepared statements.
When responses are being tracked, the execution of a LOAD DATA LOCAL
INFILE requires special handling. The readwritesplit now has a simple
state machine for the handling of the LOAD DATA LOCAL INFILE command. This
should also make the code a bit more readable.
The readwritesplit didn't correctly process the response packets that
contained more than one part of a multi-result response. By processing the
packets in a loop, this problem is avoided.
Removed some of the more "unique" ways of sending error messages in favor
of simply writing the error to the client DCB. This removes the need for
extra logic in the clientReply response handling.