Merge branch '2.2' into develop
This commit is contained in:
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user