Merge branch '2.2' into develop

This commit is contained in:
Johan Wikman
2018-02-08 12:48:06 +02:00
41 changed files with 937 additions and 210 deletions

View File

@ -611,6 +611,39 @@ int config_cb(const char* fpath, const struct stat *sb, int typeflag, struct FTW
{
int rval = 0;
if (typeflag == FTW_SL) // A symbolic link; let's see what it points to.
{
struct stat sb;
if (stat(fpath, &sb) == 0)
{
int file_type = (sb.st_mode & S_IFMT);
switch (file_type)
{
case S_IFREG:
// Points to a file; we'll handle that regardless of where the file resides.
typeflag = FTW_F;
break;
case S_IFDIR:
// Points to a directory; we'll ignore that.
MXS_WARNING("Symbolic link %s in configuration directory points to a "
"directory; it will be ignored.", fpath);
break;
default:
// Points to something else; we'll silently ignore.
;
}
}
else
{
MXS_WARNING("Could not get information about the symbolic link %s; "
"it will be ignored.", fpath);
}
}
if (typeflag == FTW_F) // We are only interested in files,
{
const char* filename = fpath + ftwbuf->base;
@ -3651,6 +3684,7 @@ void fix_serverlist(char* value)
dest += sep;
dest += start;
sep = ",";
start = strtok_r(NULL, ",", &end);
}
/** The value will always be smaller than the original one or of equal size */

View File

@ -3204,9 +3204,24 @@ static uint32_t dcb_handler(DCB* dcb, uint32_t events)
static uint32_t dcb_poll_handler(MXS_POLL_DATA *data, int thread_id, uint32_t events)
{
uint32_t rval = 0;
DCB *dcb = (DCB*)data;
return dcb_handler(dcb, events);
/**
* Fake hangup events (e.g. from monitors) can cause a DCB to be closed
* before the real events are processed. This makes it look like a closed
* DCB is receiving events when in reality the events were received at the
* same time the DCB was closed. If a closed DCB receives events they should
* be ignored.
*
* @see FakeEventTask()
*/
if (dcb->n_close == 0)
{
rval = dcb_handler(dcb, events);
}
return rval;
}
static bool dcb_is_still_valid(DCB* target, int id)

View File

@ -43,6 +43,7 @@
#include <maxscale/housekeeper.h>
#include <maxscale/log_manager.h>
#include <maxscale/maxscale.h>
#include <maxscale/mysql_utils.h>
#include <maxscale/paths.h>
#include <maxscale/query_classifier.h>
#include <maxscale/server.h>
@ -188,6 +189,8 @@ static bool modules_process_init();
static void modules_process_finish();
static void disable_module_unloading(const char* arg);
static void enable_module_unloading(const char* arg);
static void enable_statement_logging(const char* arg);
static void disable_statement_logging(const char* arg);
static void redirect_output_to_file(const char* arg);
static bool user_is_acceptable(const char* specified_user);
static bool init_sqlite3();
@ -217,6 +220,14 @@ const DEBUG_ARGUMENT debug_arguments[] =
"redirect-output-to-file", redirect_output_to_file,
"redirect stdout and stderr to the file given as an argument"
},
{
"enable-statement-logging", enable_statement_logging,
"enable the logging of SQL statements sent by MaxScale to the servers"
},
{
"disable-statement-logging", disable_statement_logging,
"disable the logging of SQL statements sent by MaxScale to the servers"
},
{NULL, NULL, NULL}
};
@ -3185,6 +3196,16 @@ static void disable_module_unloading(const char* arg)
unload_modules_at_exit = false;
}
static void enable_statement_logging(const char* arg)
{
mxs_mysql_set_log_statements(true);
}
static void disable_statement_logging(const char* arg)
{
mxs_mysql_set_log_statements(false);
}
static void redirect_output_to_file(const char* arg)
{
if (arg)

View File

@ -32,6 +32,12 @@
#include <maxscale/alloc.h>
#include <maxscale/json_api.h>
#include <maxscale/modulecmd.h>
#include <maxscale/protocol.h>
#include <maxscale/router.h>
#include <maxscale/filter.h>
#include <maxscale/authenticator.h>
#include <maxscale/monitor.h>
#include <maxscale/query_classifier.h>
#include "internal/modules.h"
#include "internal/config.h"
@ -78,6 +84,56 @@ static LOADED_MODULE* register_module(const char *module,
MXS_MODULE *mod_info);
static void unregister_module(const char *module);
static bool api_version_mismatch(const MXS_MODULE *mod_info, const char* module)
{
bool rval = false;
MXS_MODULE_VERSION api = {};
switch (mod_info->modapi)
{
case MXS_MODULE_API_PROTOCOL:
api = MXS_PROTOCOL_VERSION;
break;
case MXS_MODULE_API_AUTHENTICATOR:
api = MXS_AUTHENTICATOR_VERSION;
break;
case MXS_MODULE_API_ROUTER:
api = MXS_ROUTER_VERSION;
break;
case MXS_MODULE_API_MONITOR:
api = MXS_MONITOR_VERSION;
break;
case MXS_MODULE_API_FILTER:
api = MXS_FILTER_VERSION;
break;
case MXS_MODULE_API_QUERY_CLASSIFIER:
api = MXS_QUERY_CLASSIFIER_VERSION;
break;
default:
MXS_ERROR("Unknown module type: 0x%02hhx", mod_info->modapi);
ss_dassert(!true);
break;
}
if (api.major != mod_info->api_version.major ||
api.minor != mod_info->api_version.minor ||
api.patch != mod_info->api_version.patch)
{
MXS_ERROR("API version mismatch for '%s': Need version %d.%d.%d, have %d.%d.%d",
module, api.major, api.minor, api.patch, mod_info->api_version.major,
mod_info->api_version.minor, mod_info->api_version.patch);
rval = true;
}
return rval;
}
static bool check_module(const MXS_MODULE *mod_info, const char *type, const char *module)
{
bool success = true;
@ -118,6 +174,12 @@ static bool check_module(const MXS_MODULE *mod_info, const char *type, const cha
MXS_ERROR("Module '%s' does not implement the query classifier API.", module);
success = false;
}
if (api_version_mismatch(mod_info, module))
{
success = false;
}
if (mod_info->version == NULL)
{
MXS_ERROR("Module '%s' does not define a version string", module);

View File

@ -2428,7 +2428,7 @@ static bool journal_is_stale(MXS_MONITOR *monitor, time_t max_age)
return is_stale;
}
MXS_MONITORED_SERVER* mon_get_monitored_server(MXS_MONITOR* mon, SERVER* search_server)
MXS_MONITORED_SERVER* mon_get_monitored_server(const MXS_MONITOR* mon, SERVER* search_server)
{
ss_dassert(mon && search_server);
for (MXS_MONITORED_SERVER* iter = mon->monitored_servers; iter != NULL; iter = iter->next)
@ -2439,4 +2439,46 @@ MXS_MONITORED_SERVER* mon_get_monitored_server(MXS_MONITOR* mon, SERVER* search_
}
}
return NULL;
}
int mon_config_get_servers(const MXS_CONFIG_PARAMETER* params, const char* key, const MXS_MONITOR* mon,
MXS_MONITORED_SERVER*** monitored_servers_out)
{
ss_dassert(*monitored_servers_out == NULL);
SERVER** servers = NULL;
int servers_size = config_get_server_list(params, key, &servers);
int rval = 0;
// All servers in the array must be monitored by the given monitor.
if (servers_size > 0)
{
MXS_MONITORED_SERVER** monitored_array =
(MXS_MONITORED_SERVER**)MXS_CALLOC(servers_size, sizeof(MXS_MONITORED_SERVER*));
bool error = false;
for (int i = 0; i < servers_size && !error; i++)
{
MXS_MONITORED_SERVER* mon_serv = mon_get_monitored_server(mon, servers[i]);
if (mon_serv != NULL)
{
monitored_array[i] = mon_serv;
}
else
{
MXS_ERROR("Server '%s' is not monitored by monitor '%s'.", servers[i]->unique_name, mon->name);
error = true;
}
}
MXS_FREE(servers);
if (error)
{
MXS_FREE(monitored_array);
rval = -1;
}
else
{
*monitored_servers_out = monitored_array;
rval = servers_size;
}
}
return rval;
}

View File

@ -32,6 +32,21 @@
#include <maxscale/debug.h>
#include <maxscale/log_manager.h>
namespace
{
struct THIS_UNIT
{
bool log_statements; // Should all statements sent to server be logged?
};
static THIS_UNIT this_unit =
{
false
};
}
/**
* @brief Calculate the length of a length-encoded integer in bytes
*
@ -221,6 +236,19 @@ int mxs_mysql_query(MYSQL* conn, const char* query)
rc = mysql_query(conn, query);
}
if (this_unit.log_statements)
{
const char* host;
if (mariadb_get_info(conn, MARIADB_CONNECTION_HOST, &host) != 0)
{
// No idea about the host, but let's use something that looks like
// an IP-address as a placeholder.
host = "0.0.0.0";
}
MXS_NOTICE("SQL(%s): %d, \"%s\"", host, rc, query);
}
return rc;
}
@ -377,3 +405,13 @@ void mxs_mysql_set_server_version(MYSQL* mysql, SERVER* server)
}
}
}
void mxs_mysql_set_log_statements(bool enable)
{
this_unit.log_statements = enable;
}
bool mxs_mysql_get_log_statements()
{
return this_unit.log_statements;
}