By storing a link to the backend DCBs in the session object itself, we can
reach all related objects from the session. This removes the need to
iterate over all DCBs to find the set of related DCBs.
Now that the readwritesplit uses the same mechanism for both
retry_failed_reads and delayed query retries, the re-routing function
should accept a delay of 0 seconds. This makes the mechanism more suitable
for other uses e.g. delaying of queries in filters.
The `error` variable was never used. Also added a more convenient typedef
for both the downstream and upstream functions and updated filter API
version.
This is a proof-of-concept that validates the query retrying method. The
actual implementation of the query retrying mechanism needs more thought
as using the housekeeper is not very efficient.
With the configuration entry
dump_last_statements=[never|on_close|on_error]
you can now specify when and if to dump the last statements
of of a session.
With the configuration entry
retain_last_statements=<unsigned>
or the debug flag '--debug=retain-last-statements=<unsigned>',
MaxScale will store the specified number of last statements
for each session. By calling
session_dump_statements(session);
MaxScale will dump the last statements as NOTICE messages.
For debugging purposes.
- session_set_response() made const correct
- set_response() function added to mxs::FilterSession; calls
session_set_response().
- Cache uses set_response() for delivering the cache result
to the client.
Filter that terminate the response processing now have a mechanism
using which a response can be provided in such a way that previous
filters will see the response.
The macros MXS_SESSION_ROUTE_QUERY and MXS_SESSION_ROUTE_REPLY
are now defined in terms of functions that do the actual stuff.
Incidentally, the function session_route_reply() existed already
but was not used. Now slightly rewritten so that it does not simply
ignore misuse.
The earlier @maxscale.cache.enabled has now been replaced with
@maxscale.cache.populate and @maxscale.cache.use that provide
for more flexibility.
With the former it is possible to control in what circumstances
the cache is populated and with the latter one when it is used.
Together they can be used for having a completely client driven
caching.
With the changes in this commit it is possible to add and remove
MaxScale specific user variables. A MaxScale specific user variable
is a user variable that is interpreted by MaxScale and that
potentially changes the behaviour of MaxScale.
MaxScale specific user variables are of the format "@maxscale.x.y"
where "@maxscale" is a mandatory prefix, x a scope identifying the
component that handles the variable and y the component specific
variable. So, a variable might be called e.g. "@maxscale.cache.enabled".
The scope "core" is reserved (although not enforced yet) to MaxScale
itself.
The idea is that although MaxScale catches these, they are passed
through to the server. The benefit of this is that we do not need to
detect e.g. "SELECT @maxscale.cache.enabled", but can let the result
be returned from the server.
The interpretation of a provided value is handled by the component that
adds the variable. In a subsequent commit, it will be possible for a
component to reject a value, which will then cause an error to be
returned to the client.
There are 3 new functions:
- session_add_variable() using which a variable is added,
- session_remove_variable() using which a variable is removed, and
- session_set_variable_value().
The two former ones are to be called by components, the last one by
the protocol that catches the "set @maxscale..." statements.
The backend protocol command tracking didn't check whether the session was
the dummy session. The DCB's session is always set to this value when it
is put into the persistent pool.
KILL commands are now sent to the backends in an asynchronous manner. As
the LocalClient class is used to connect to the servers, this will cause
an extra connection to be created on top of the original connections
created by the session.
If the user does not have the permissions to execute the KILL, the error
message is currently lost. This could be solved by adding a "result
handler" into the LocalClient class which is called with the result.
When a session is being closed in a controlled manner, i.e. a COM_QUIT is
received from the client, it is possible to deduce from this fact that the
backend connections are very likely to be idle. This can be used as an
additional qualification that must be met by all connections before they
can be candidates for connection pooling.
This assumption will not hold with batched and asynchronous queries. In
this case it is possible that the COM_QUIT is received from the client
before even the first result from the backend is read. For this to work,
the protocol module would need to track the number and state of expected
responses.
The server internal session id may be larger than 4 bytes (MariaDB uses 8)
but only 4 are sent in the handshake. The full value can be queried
from the server, but this query is not supported by MaxScale yet. In any
case, both the protocol and MXS_SESSION now have 64 bit counters. Only the
low 32 bits are sent in the handshake, similar to server.
Various small changes to part2, as suggested by comments and otherwise.
Mostly renaming, working logic should not change.
Exception: session id changed to 64bit in the container and associated
functions. Another commit will change it to 64bit in the session itself.
MySQL sessions are added to a hasmap when created, removed when closed.
MYSQL_COM_PROCESS_KILL is now detected, the thread_id is read and the kill
command sent to all worker threads to find the correct session. If found, a
fake hangup even is created for the client dcb.
As is, this function is of little use since the client could just disconnect
itself instead. Later on, additional commands of this nature will be added.
The /sessions/ resource was not implemented due to changes in the core
polling mechanics. With the new worker thread messaging system, sessions
can be listed in a safe manner.
When a resource has a relation to another resource, it should be expressed
as a working link to the resource. By passing the hostname of the server
to the functions, we are able to generate working relation links.
Preparation for adding KILL syntax support.
Session id changed to uint32 everywhere. Added atomic op.
Session id can be acquired before session_alloc().
Added session_alloc_with_id(), which is given a session id number.
Worker object has a session_id->SESSION* mapping, not used yet.
The contents of the existing filter.cc was copied into filter.c that
subsequently was renamed to filter.cc.
The way the session is called as the last filter in the filter chain
is really dubious and ought to be rearranged so that the blind casting
of a session to a filter and back is not needed.
The core now provides a simple function to close a session. This removes
the need for the modules to directly call the API entry points when the
session should be closed. It is also in line with the style that other
objects, namely the DCBs, use. This makes the new session_close very
similar to dcb_close.
Removed unused spinlocks from DCBs, sessions and the MySQL protocol
structs. They were used in a context where only one thread has access to
the structure.
Removed unused member variables from DCBs.
The transaction tracking now flags the transaction as open even when a
COMMIT/ROLLBACK is received. The next statement after the transaction is
closed resets the transaction state to inactive. This means that the end
of the transaction belongs in the transaction.
This allows all statements that belong to a transaction to be detected
with the transaction tracking functions provided by the core. With this,
the routing modules should have an easier time handling transactions.
When the transaction ends, it's good to know what type of a transaction
just ended. Currently, this will be used by readwritesplit to detect when
a read-only transaction ends.