The server monuser and monpw members were used with the assumption that
they could be NULL. This is no longer true since they were converted to
arrays.
The name member of the server was freed leading to a crash when the server
unit test was run.
The persisted configuration directory is created and/or read when MaxScale
starts. This allows the servers created at runtime to be recreated when
MaxScale is restarted.
The persisted configuration subdirectory will be used to store changes to
the configuration. The gwdirs.h header now supports setting and getting
the value for this directory.
The address, port, monuser and monpw parameters of an existing server can
be changed at runtime. The support for enabling SSL will come in a later
commit.
Allowing servers to be modified could also be done by destroying and
recreating them. Since the servers are never actually destroyed, it is
better to allow the alteration of the existing ones.
MaxScale can now start without any defined monitors. This allows the core
services to be configured beforehand. With the changes to dynamic
modifications to servers, automatic scaling of slaves is possible.
The `add server` command accepts a server name and either a service name
or a monitor name. It will add servers to services and monitors. Since all
monitors use the MONITOR_SERVER structures directly, the monitors need
to be stopped before new servers are added to them
The function serializes a server to a file. This is intended to be used
with dynamically created servers. The output of the server serialization
will eventually be stored in the configuration file directory (default is
/etc/maxscale.cnf.d/) so that created servers persist even after a
restart.
Servers can now be added and removed from services which allows routers to
use them with new sessions. The routers don't fully use the new
functionality in the server references which prevents new servers from
being taken into use.
If shutdown has been initiated (via maxadmin or by sending a
SIGINT or SIGTERM) and a SIGTERM is received, the process
is terminated.
If shutdown has been initiated (via maxadmin or by sending a
SIGINT or SIGTERM) and a SIGINT (Ctrl-C) is received, a warning
is printed that shutdown is in progess. Then, if an additional
SIGINT is received, the process is terminated.
So, in practice:
- If MaxScale is running as a daemon, the first SIGTERM initiates
shutdown and a second one unconditionally terminates the process.
- If MaxScale is running in the console, the first Ctrl-C initiates
shutdown, the second prints a warning and the third terminates
the process.
This is to ensure that MaxScale can be forced to exit, in
case some thread is hung for whatever reason, and is thus preventing
the controlled shutdown.
If the user running MaxScale could open the .secrets-file and the
file permissions were anything other than owner:read, the
secrets_readkeys() would fail with error message
"Ignoring secrets file <path>, invalid permissions." Now the
message is more accurate in stating the expected permissions.
The hangup code was refactored into a common function which should only be
used after the server states have been updated. This will remove erroneus
connections to already failed servers.
The monitors and services didn't use TLS when they connected to the
backend servers. Since there has been no proof of instability, TLS should
be enabled.
When persistent connections were used, it was possible that the injection
of COM_CHANGE_USER statements caused a crash when a DCB in the wrong state
was accessed.
For MySQL protocol modules, the `data` member of the client DCB points to
the shared session data, a MYSQL_session struct, but for sessions in the
persistent pool, it points to NULL. The boolean, `was_persistent`, tells
whether a DCB was just taken from the pool or it has been in use.
The `was_persistent` status wasn't properly reset for connections that
were put into the pool which caused a COM_CHANGE_USER statement to be
injected for stale connections in the pool which caused a crash when the
NULL `data` member was accessed.
Previously the session_id incrementation was done after creating
filters, giving the filters a constant zero value for session_id.
Now the incrementation happens before filter creation.
This allows safer lock-free reads to be done on lists that never shrink in
size. The main use-case for this is to allow servers to be added to a
service without locking the service each time a new session is created.
Synchronizing the memory before adding new components into a list
guarantees that if a session reads from the list and sees the new list
item, the memory pointed by the item is valid.
Function is no longer used and it was quite unoptimal, so now
removed.
qc_get_prepare_name, qc_get_prepare_operation and qc_get_field_info
that were missing from qc_dummy added at the same time.
If an illegal DCB close is done with a backend DCB, it will log the server
where it was connected. This allows us to know whether the DCB was
connected to a master or a slave.
Added more debug assertions to readwritesplit code. The DCBs should never
enter the DCB_STATE_DISCONNECTED.
Removed useless debug log messages. The messages usually just flood the
logs with no use to the developers.
The check for the success of the configuration file always resulted in a
successful return value even if the loading failed.
In addition to this, a log message referred to the active configuration
when the active configuration was set only after the processing was
complete. Since configuration failures are always fatal, there's no harm
in preemptively setting the active configuration to the one currently
being processed.
This function returns more detailed information about the fields
of a statement. Supersedes qc_get_affected_fields() that will
be deprecated and removed.
Note that this function now introduced new kind of behaviour; the
returned data belongs to the GWBUF and remains valid for as long as
the GWBUF is alive. That means that unnecessary copying need not
be done.
When a persistent connection is taken from the pool, the state is reset
with a COM_CHANGE_USER on the next write. This allows reuse of persistent
connections without having to worry about the state of the MySQL session.
Given a config file "config.cnf", we look for the directory
"config.cnf.d" and recursively in that hierarhcy load all files
whose suffix is ".cnf"; other files are ignored.
Currently duplicate sections are checked on a file by file basis.
That will be changed so that duplicate sections are not allowed
across all the files.
- First <maxscale/cdefs.h>
- Then all system, c-runtime, OS include files in alphabetical order.
- Then include files for "3rd-party" software in a loose order of
importance.
- Then maxscale headers ordered alphabetically.
The transaction state only reflects explicitly started transactions.
Thus, by looking at the autocommit mode and the transaction state a
component can figure out whether the current statement will be committed
or not.
With this change, whether something should be logged or, that is,
whether the used log priority is enabled or not, is checked before
the logging function is called. That should save a few cycles.
Now mxs_log_message() always logs a message, without consideration
for whether the priority is enabled or not. The inline function
mxs_log_is_priority_enabled() returns true if a particular priority
is enabled and the MXS_LOG_MESSAGE() macro (that MXS_ERROR etc. are
expanded into) call that before calling the actual logging function.
Some of the tests depended on a working installation where modules are all
located at the default paths. These tests now explicitly set the module
directory which fixes the immediate problem.
Disabled the starting of services in the service test as this will fail
with real modules. The dummy internal modules aren't build and should be
removed in a later commit. In general, it might be better to do service
level testing outside the internal test suite.
The HTTPD protocol mistakenly assumed that the `authenticator` parameter
of a listener would be NULL if the default authenticator is used.
Recent changes modified it so that the value is never NULL and
`NullAuthDeny` would be used for protocols which did not implement the
auth_default entry point.