Merge branch 'develop' into binlog_server_waitdata_encryption
This commit is contained in:
@ -50,6 +50,7 @@
|
||||
#include <binlog_common.h>
|
||||
#include <avro/errors.h>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/modulecmd.h>
|
||||
|
||||
#ifndef BINLOG_NAMEFMT
|
||||
#define BINLOG_NAMEFMT "%s.%06d"
|
||||
@ -93,6 +94,7 @@ bool avro_save_conversion_state(AVRO_INSTANCE *router);
|
||||
static void stats_func(void *);
|
||||
void avro_index_file(AVRO_INSTANCE *router, const char* path);
|
||||
void avro_update_index(AVRO_INSTANCE* router);
|
||||
static bool conversion_task_ctl(AVRO_INSTANCE *inst, bool start);
|
||||
|
||||
/** The module object definition */
|
||||
static ROUTER_OBJECT MyObject =
|
||||
@ -123,6 +125,26 @@ version()
|
||||
return version_str;
|
||||
}
|
||||
|
||||
bool avro_handle_convert(const MODULECMD_ARG *args)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (strcmp(args->argv[1].value.string, "start") == 0 &&
|
||||
conversion_task_ctl(args->argv[0].value.service->router_instance, true))
|
||||
{
|
||||
MXS_NOTICE("Started conversion for service '%s'.", args->argv[0].value.service->name);
|
||||
rval = true;
|
||||
}
|
||||
else if (strcmp(args->argv[1].value.string, "stop") == 0 &&
|
||||
conversion_task_ctl(args->argv[0].value.service->router_instance, false))
|
||||
{
|
||||
MXS_NOTICE("Stopped conversion for service '%s'.", args->argv[0].value.service->name);
|
||||
rval = true;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The module initialisation routine, called when the module
|
||||
* is first loaded.
|
||||
@ -133,6 +155,13 @@ ModuleInit()
|
||||
MXS_NOTICE("Initialized avrorouter module %s.\n", version_str);
|
||||
spinlock_init(&instlock);
|
||||
instances = NULL;
|
||||
|
||||
modulecmd_arg_type_t args[] =
|
||||
{
|
||||
{ MODULECMD_ARG_SERVICE, "The avrorouter service" },
|
||||
{ MODULECMD_ARG_STRING, "Action, whether to 'start' or 'stop' the conversion process" }
|
||||
};
|
||||
modulecmd_register_command("avrorouter", "convert", avro_handle_convert, 2, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,22 +253,29 @@ bool create_tables(sqlite3* handle)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool add_conversion_task(AVRO_INSTANCE *inst)
|
||||
static bool conversion_task_ctl(AVRO_INSTANCE *inst, bool start)
|
||||
{
|
||||
char tasknm[strlen(avro_task_name) + strlen(inst->service->name) + 2];
|
||||
snprintf(tasknm, sizeof(tasknm), "%s-%s", inst->service->name, avro_task_name);
|
||||
if (inst->service->svc_do_shutdown)
|
||||
bool rval = false;
|
||||
|
||||
if (!inst->service->svc_do_shutdown)
|
||||
{
|
||||
MXS_INFO("AVRO converter task is not added due to MaxScale shutdown");
|
||||
return false;
|
||||
char tasknm[strlen(avro_task_name) + strlen(inst->service->name) + 2];
|
||||
snprintf(tasknm, sizeof(tasknm), "%s-%s", inst->service->name, avro_task_name);
|
||||
|
||||
/** Remove old task and create a new one */
|
||||
hktask_remove(tasknm);
|
||||
|
||||
if (!start || hktask_add(tasknm, converter_func, inst, inst->task_delay))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Failed to add binlog to Avro conversion task to housekeeper.");
|
||||
}
|
||||
}
|
||||
MXS_INFO("Setting task for converter_func");
|
||||
if (hktask_oneshot(tasknm, converter_func, inst, inst->task_delay) == 0)
|
||||
{
|
||||
MXS_ERROR("Failed to add binlog to Avro conversion task to housekeeper.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -566,7 +602,7 @@ createInstance(SERVICE *service, char **options)
|
||||
*/
|
||||
|
||||
/* Start the scan, read, convert AVRO task */
|
||||
add_conversion_task(inst);
|
||||
conversion_task_ctl(inst, true);
|
||||
|
||||
MXS_INFO("AVRO: current MySQL binlog file is %s, pos is %lu\n",
|
||||
inst->binlog_name, inst->current_pos);
|
||||
@ -1047,7 +1083,7 @@ void converter_func(void* data)
|
||||
if (binlog_end == AVRO_LAST_FILE)
|
||||
{
|
||||
router->task_delay = MXS_MIN(router->task_delay + 1, AVRO_TASK_DELAY_MAX);
|
||||
if (add_conversion_task(router))
|
||||
if (conversion_task_ctl(router, true))
|
||||
{
|
||||
MXS_INFO("Stopped processing file %s at position %lu. Waiting until"
|
||||
" more data is written before continuing. Next check in %d seconds.",
|
||||
|
@ -423,6 +423,19 @@ static void shutdown_server()
|
||||
static void shutdown_service(DCB *dcb, SERVICE *service);
|
||||
static void shutdown_monitor(DCB *dcb, MONITOR *monitor);
|
||||
|
||||
static void
|
||||
shutdown_listener(DCB *dcb, SERVICE *service, const char *name)
|
||||
{
|
||||
if (serviceStopListener(service, name))
|
||||
{
|
||||
dcb_printf(dcb, "Stopped listener '%s'\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb_printf(dcb, "Failed to stop listener '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The subcommands of the shutdown command
|
||||
*/
|
||||
@ -452,6 +465,14 @@ struct subcommand shutdownoptions[] =
|
||||
"E.g. shutdown service \"Sales Database\"",
|
||||
{ARG_TYPE_SERVICE, 0, 0}
|
||||
},
|
||||
{
|
||||
"listener",
|
||||
2, 2,
|
||||
shutdown_listener,
|
||||
"Stop a listener",
|
||||
"E.g. shutdown listener \"RW Service\" \"RW Listener\"",
|
||||
{ARG_TYPE_SERVICE, ARG_TYPE_STRING}
|
||||
},
|
||||
{
|
||||
EMPTY_OPTION
|
||||
}
|
||||
@ -487,6 +508,20 @@ struct subcommand syncoptions[] =
|
||||
|
||||
static void restart_service(DCB *dcb, SERVICE *service);
|
||||
static void restart_monitor(DCB *dcb, MONITOR *monitor);
|
||||
|
||||
static void
|
||||
restart_listener(DCB *dcb, SERVICE *service, const char *name)
|
||||
{
|
||||
if (serviceStartListener(service, name))
|
||||
{
|
||||
dcb_printf(dcb, "Restarted listener '%s'\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb_printf(dcb, "Failed to restart listener '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The subcommands of the restart command
|
||||
*/
|
||||
@ -504,6 +539,12 @@ struct subcommand restartoptions[] =
|
||||
"E.g. restart service \"Sales Database\"",
|
||||
{ARG_TYPE_SERVICE, 0, 0}
|
||||
},
|
||||
{
|
||||
"listener", 2, 2, restart_listener,
|
||||
"Restart a listener",
|
||||
"E.g. restart listener \"RW Service\" \"RW Listener\"",
|
||||
{ARG_TYPE_SERVICE, ARG_TYPE_STRING}
|
||||
},
|
||||
{ EMPTY_OPTION }
|
||||
};
|
||||
|
||||
|
@ -359,29 +359,35 @@ execute(ROUTER *rinstance, void *router_session, GWBUF *queue)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// We have a complete request in a signle buffer
|
||||
int rc = 1;
|
||||
// We have a complete request in a single buffer
|
||||
if (modutil_MySQL_Query(queue, &sql, &len, &residual))
|
||||
{
|
||||
sql = strndup(sql, len);
|
||||
int rc = maxinfo_execute_query(instance, session, sql);
|
||||
rc = maxinfo_execute_query(instance, session, sql);
|
||||
MXS_FREE(sql);
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (MYSQL_COMMAND(queue))
|
||||
{
|
||||
case COM_PING:
|
||||
return maxinfo_ping(instance, session, queue);
|
||||
rc = maxinfo_ping(instance, session, queue);
|
||||
break;
|
||||
case COM_STATISTICS:
|
||||
return maxinfo_statistics(instance, session, queue);
|
||||
rc = maxinfo_statistics(instance, session, queue);
|
||||
break;
|
||||
case COM_QUIT:
|
||||
break;
|
||||
default:
|
||||
MXS_ERROR("maxinfo: Unexpected MySQL command 0x%x",
|
||||
MYSQL_COMMAND(queue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
// MaxInfo doesn't route the data forward so it should be freed.
|
||||
gwbuf_free(queue);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -652,6 +658,7 @@ maxinfo_execute_query(INFO_INSTANCE *instance, INFO_SESSION *session, char *sql)
|
||||
else
|
||||
{
|
||||
maxinfo_execute(session->dcb, tree);
|
||||
maxinfo_free_tree(tree);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ typedef enum
|
||||
|
||||
|
||||
extern MAXINFO_TREE *maxinfo_parse(char *, PARSE_ERROR *);
|
||||
extern void maxinfo_free_tree(MAXINFO_TREE *);
|
||||
extern void maxinfo_execute(DCB *, MAXINFO_TREE *);
|
||||
extern void maxinfo_send_error(DCB *, int, char *);
|
||||
extern void maxinfo_send_parse_error(DCB *, char *, PARSE_ERROR);
|
||||
|
@ -880,21 +880,27 @@ static void
|
||||
exec_show_variables(DCB *dcb, MAXINFO_TREE *filter)
|
||||
{
|
||||
RESULTSET *result;
|
||||
VARCONTEXT context;
|
||||
VARCONTEXT *context;
|
||||
|
||||
if ((context = MXS_MALLOC(sizeof(VARCONTEXT))) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter)
|
||||
{
|
||||
context.like = filter->value;
|
||||
context->like = filter->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.like = NULL;
|
||||
context->like = NULL;
|
||||
}
|
||||
context.index = 0;
|
||||
context->index = 0;
|
||||
|
||||
if ((result = resultset_create(variable_row, &context)) == NULL)
|
||||
if ((result = resultset_create(variable_row, context)) == NULL)
|
||||
{
|
||||
maxinfo_send_error(dcb, 0, "No resources available");
|
||||
MXS_FREE(context);
|
||||
return;
|
||||
}
|
||||
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
|
||||
@ -1166,21 +1172,27 @@ static void
|
||||
exec_show_status(DCB *dcb, MAXINFO_TREE *filter)
|
||||
{
|
||||
RESULTSET *result;
|
||||
VARCONTEXT context;
|
||||
VARCONTEXT *context;
|
||||
|
||||
if ((context = MXS_MALLOC(sizeof(VARCONTEXT))) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter)
|
||||
{
|
||||
context.like = filter->value;
|
||||
context->like = filter->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.like = NULL;
|
||||
context->like = NULL;
|
||||
}
|
||||
context.index = 0;
|
||||
context->index = 0;
|
||||
|
||||
if ((result = resultset_create(status_row, &context)) == NULL)
|
||||
if ((result = resultset_create(status_row, context)) == NULL)
|
||||
{
|
||||
maxinfo_send_error(dcb, 0, "No resources available");
|
||||
MXS_FREE(context);
|
||||
return;
|
||||
}
|
||||
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <maxscale/log_manager.h>
|
||||
|
||||
static MAXINFO_TREE *make_tree_node(MAXINFO_OPERATOR, char *, MAXINFO_TREE *, MAXINFO_TREE *);
|
||||
static void free_tree(MAXINFO_TREE *);
|
||||
void maxinfo_free_tree(MAXINFO_TREE *); // This function is needed by maxinfo.c
|
||||
static char *fetch_token(char *, int *, char **);
|
||||
static MAXINFO_TREE *parse_column_list(char **sql);
|
||||
static MAXINFO_TREE *parse_table_name(char **sql);
|
||||
@ -95,13 +95,13 @@ maxinfo_parse(char *sql, PARSE_ERROR *parse_error)
|
||||
{
|
||||
// Expected expression
|
||||
*parse_error = PARSE_EXPECTED_LIKE;
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Malformed show
|
||||
MXS_FREE(text);
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
*parse_error = PARSE_MALFORMED_SHOW;
|
||||
return NULL;
|
||||
#if 0
|
||||
@ -132,7 +132,7 @@ maxinfo_parse(char *sql, PARSE_ERROR *parse_error)
|
||||
{
|
||||
/** Unknown token after SHUTDOWN MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
return tree;
|
||||
@ -146,7 +146,7 @@ maxinfo_parse(char *sql, PARSE_ERROR *parse_error)
|
||||
{
|
||||
/** Missing token for RESTART MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL);
|
||||
@ -156,7 +156,7 @@ maxinfo_parse(char *sql, PARSE_ERROR *parse_error)
|
||||
/** Unknown token after RESTART MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
MXS_FREE(text);
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
return tree;
|
||||
@ -278,20 +278,20 @@ make_tree_node(MAXINFO_OPERATOR op, char *value, MAXINFO_TREE *left, MAXINFO_TRE
|
||||
}
|
||||
|
||||
/**
|
||||
* Recusrsively free the storage associated with a parse tree
|
||||
* Recursively free the storage associated with a parse tree
|
||||
*
|
||||
* @param tree The parse tree to free
|
||||
*/
|
||||
static void
|
||||
free_tree(MAXINFO_TREE *tree)
|
||||
void
|
||||
maxinfo_free_tree(MAXINFO_TREE *tree)
|
||||
{
|
||||
if (tree->left)
|
||||
{
|
||||
free_tree(tree->left);
|
||||
maxinfo_free_tree(tree->left);
|
||||
}
|
||||
if (tree->right)
|
||||
{
|
||||
free_tree(tree->right);
|
||||
maxinfo_free_tree(tree->right);
|
||||
}
|
||||
if (tree->value)
|
||||
{
|
||||
@ -431,7 +431,7 @@ MAXINFO_TREE* maxinfo_parse_literals(MAXINFO_TREE *tree, int min_args, char *ptr
|
||||
(node->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL)) == NULL)
|
||||
{
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
maxinfo_free_tree(tree);
|
||||
if (ptr)
|
||||
{
|
||||
MXS_FREE(text);
|
||||
|
Reference in New Issue
Block a user