Merge branch 'develop' into MXS-329-develop-20151111
This commit is contained in:
@ -2213,7 +2213,7 @@ int main(int argc, char** argv)
|
||||
NULL
|
||||
};
|
||||
|
||||
skygw_logmanager_init(argc_,argv_);
|
||||
mxs_log_init(argc_,argv_);
|
||||
|
||||
|
||||
init_test_env(home);
|
||||
@ -2231,7 +2231,7 @@ int main(int argc, char** argv)
|
||||
printf("Failed to parse rule. Read the error log for the reason of the failure.\n");
|
||||
}
|
||||
|
||||
skygw_log_sync_all();
|
||||
mxs_log_flush_sync();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -15,10 +15,9 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
||||
DCB* dcb;
|
||||
char cwd[1024];
|
||||
char tmp[2048];
|
||||
char** optstr;
|
||||
|
||||
if(!(argc == 2 && strcmp(argv[1],"-h") == 0)){
|
||||
skygw_logmanager_init(NULL,0,NULL);
|
||||
mxs_log_init(NULL,NULL,LOG_TARGET_DEFAULT);
|
||||
}
|
||||
|
||||
if(!(instance.head = calloc(1,sizeof(FILTERCHAIN))))
|
||||
@ -52,11 +51,7 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
||||
getcwd(cwd,sizeof(cwd));
|
||||
sprintf(tmp,"%s",cwd);
|
||||
|
||||
optstr = (char**)malloc(sizeof(char*)*2);
|
||||
optstr[0] = strdup("log_manager");
|
||||
optstr[1] = NULL;
|
||||
skygw_logmanager_init(tmp, 1, optstr);
|
||||
free(optstr);
|
||||
mxs_log_init(NULL, tmp, LOG_TARGET_DEFAULT);
|
||||
|
||||
rval = process_opts(argc,argv);
|
||||
|
||||
|
||||
@ -11,8 +11,7 @@ int main(int argc, char** argv){
|
||||
if(harness_init(argc,argv,&hinstance)){
|
||||
printf("Error: Initialization failed.\n");
|
||||
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
||||
skygw_logmanager_done();
|
||||
skygw_logmanager_exit();
|
||||
mxs_log_finish();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -230,8 +229,7 @@ int main(int argc, char** argv){
|
||||
|
||||
free_buffers();
|
||||
free_filters();
|
||||
skygw_logmanager_done();
|
||||
skygw_logmanager_exit();
|
||||
mxs_log_finish();
|
||||
free(instance.head);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -35,8 +35,7 @@ int main(int argc,char** argv)
|
||||
if(harness_init(argc,argv,&inst) || inst->error){
|
||||
printf("Error: Initialization failed.\n");
|
||||
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
||||
skygw_logmanager_done();
|
||||
skygw_logmanager_exit();
|
||||
mxs_log_finish();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -73,7 +73,12 @@ typedef enum
|
||||
MAXOP_LITERAL,
|
||||
MAXOP_PREDICATE,
|
||||
MAXOP_LIKE,
|
||||
MAXOP_EQUAL
|
||||
MAXOP_EQUAL,
|
||||
MAXOP_FLUSH,
|
||||
MAXOP_SET,
|
||||
MAXOP_CLEAR,
|
||||
MAXOP_SHUTDOWN,
|
||||
MAXOP_RESTART
|
||||
} MAXINFO_OPERATOR;
|
||||
|
||||
/**
|
||||
@ -109,6 +114,11 @@ typedef struct maxinfo_tree {
|
||||
#define LT_FROM 7
|
||||
#define LT_STAR 8
|
||||
#define LT_VARIABLE 9
|
||||
#define LT_FLUSH 10
|
||||
#define LT_SET 11
|
||||
#define LT_CLEAR 12
|
||||
#define LT_SHUTDOWN 13
|
||||
#define LT_RESTART 14
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -154,32 +154,15 @@ startMonitor(void *arg,void* opt)
|
||||
handle->use_priority = config_truth_value(params->value);
|
||||
else if(!strcmp(params->name,"script"))
|
||||
{
|
||||
if(handle->script)
|
||||
{
|
||||
free(handle->script);
|
||||
handle->script = NULL;
|
||||
}
|
||||
|
||||
if(access(params->value,X_OK) == 0)
|
||||
{
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
if(access(params->value,F_OK) == 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be executed: %s",
|
||||
params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be found: %s",
|
||||
params->value);
|
||||
}
|
||||
}
|
||||
if (externcmd_can_execute(params->value))
|
||||
{
|
||||
free(handle->script);
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(params->name,"events"))
|
||||
{
|
||||
@ -327,11 +310,10 @@ char *server_string;
|
||||
|
||||
/* get server version string */
|
||||
server_string = (char *)mysql_get_server_info(database->con);
|
||||
if (server_string) {
|
||||
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
|
||||
if (database->server->server_string)
|
||||
strcpy(database->server->server_string, server_string);
|
||||
}
|
||||
if (server_string)
|
||||
{
|
||||
server_set_version_string(database->server, server_string);
|
||||
}
|
||||
|
||||
/* Check if the the Galera FSM shows this node is joined to the cluster */
|
||||
if (mysql_query(database->con, "SHOW STATUS LIKE 'wsrep_local_state'") == 0
|
||||
|
||||
@ -136,31 +136,15 @@ startMonitor(void *arg,void* opt)
|
||||
}
|
||||
else if(!strcmp(params->name,"script"))
|
||||
{
|
||||
if(handle->script)
|
||||
{
|
||||
free(handle->script);
|
||||
}
|
||||
if(access(params->value,X_OK) == 0)
|
||||
{
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
if(access(params->value,F_OK) == 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be executed: %s",
|
||||
params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be found: %s",
|
||||
params->value);
|
||||
}
|
||||
handle->script = NULL;
|
||||
}
|
||||
if (externcmd_can_execute(params->value))
|
||||
{
|
||||
free(handle->script);
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(params->name,"events"))
|
||||
{
|
||||
@ -312,11 +296,10 @@ char *server_string;
|
||||
|
||||
/* get server version string */
|
||||
server_string = (char *)mysql_get_server_info(database->con);
|
||||
if (server_string) {
|
||||
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
|
||||
if (database->server->server_string)
|
||||
strcpy(database->server->server_string, server_string);
|
||||
}
|
||||
if (server_string)
|
||||
{
|
||||
server_set_version_string(database->server, server_string);
|
||||
}
|
||||
|
||||
/* get server_id form current node */
|
||||
if (mysql_query(database->con, "SELECT @@server_id") == 0
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <monitor_common.h>
|
||||
#include <maxscale_pcre2.h>
|
||||
|
||||
monitor_event_t mon_name_to_event(char* tok);
|
||||
|
||||
@ -225,23 +226,32 @@ case NEW_DONOR_EVENT:
|
||||
|
||||
}
|
||||
|
||||
void mon_append_node_names(MONITOR_SERVERS* start,char* str, int len)
|
||||
/**
|
||||
* Create a list of running servers
|
||||
* @param start Monitored servers
|
||||
* @param dest Destination where the string is formed
|
||||
* @param len Length of @c dest
|
||||
*/
|
||||
void mon_append_node_names(MONITOR_SERVERS* start, char* dest, int len)
|
||||
{
|
||||
MONITOR_SERVERS* ptr = start;
|
||||
bool first = true;
|
||||
int slen = strlen(str);
|
||||
char arr[256];
|
||||
while(ptr && slen < len)
|
||||
int slen = strlen(dest);
|
||||
char arr[MAX_SERVER_NAME_LEN + 32]; // Some extra space for port
|
||||
while (ptr && slen < len)
|
||||
{
|
||||
if(!first)
|
||||
{
|
||||
strncat(str,",",len);
|
||||
}
|
||||
first = false;
|
||||
sprintf(arr,"%s:%d",ptr->server->name,ptr->server->port);
|
||||
strncat(str,arr,len);
|
||||
ptr = ptr->next;
|
||||
slen = strlen(str);
|
||||
if(SERVER_IS_RUNNING(ptr->server))
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
strncat(dest, ",", len);
|
||||
}
|
||||
first = false;
|
||||
snprintf(arr, sizeof(arr), "%s:%d", ptr->server->name, ptr->server->port);
|
||||
strncat(dest, arr, len);
|
||||
slen = strlen(dest);
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,23 +312,26 @@ bool mon_print_fail_status(
|
||||
*/
|
||||
void monitor_launch_script(MONITOR* mon, MONITOR_SERVERS* ptr, char* script)
|
||||
{
|
||||
char argstr[PATH_MAX + MON_ARG_MAX + 1];
|
||||
EXTERNCMD* cmd;
|
||||
char nodelist[PATH_MAX + MON_ARG_MAX + 1] = {'\0'};
|
||||
char event[strlen(mon_get_event_name(ptr))];
|
||||
char initiator[strlen(ptr->server->name) + 24]; // Extra space for port
|
||||
|
||||
snprintf(argstr, PATH_MAX + MON_ARG_MAX,
|
||||
"%s --event=%s --initiator=%s:%d --nodelist=",
|
||||
script,
|
||||
mon_get_event_name(ptr),
|
||||
ptr->server->name,
|
||||
ptr->server->port);
|
||||
snprintf(initiator, sizeof(initiator), "%s:%d", ptr->server->name, ptr->server->port);
|
||||
snprintf(event, sizeof(event), "%s", mon_get_event_name(ptr));
|
||||
mon_append_node_names(mon->databases, nodelist, PATH_MAX + MON_ARG_MAX);
|
||||
|
||||
mon_append_node_names(mon->databases, argstr, PATH_MAX + MON_ARG_MAX);
|
||||
if ((cmd = externcmd_allocate(argstr)) == NULL)
|
||||
EXTERNCMD* cmd = externcmd_allocate(script);
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
skygw_log_write(LE, "Failed to initialize script: %s", script);
|
||||
return;
|
||||
}
|
||||
|
||||
externcmd_substitute_arg(cmd, "[$]INITIATOR", initiator);
|
||||
externcmd_substitute_arg(cmd, "[$]EVENT", event);
|
||||
externcmd_substitute_arg(cmd, "[$]NODELIST", nodelist);
|
||||
|
||||
if (externcmd_execute(cmd))
|
||||
{
|
||||
skygw_log_write(LOGFILE_ERROR,
|
||||
|
||||
@ -168,32 +168,18 @@ startMonitor(void *arg, void* opt)
|
||||
handle->detectStaleMaster = config_truth_value(params->value);
|
||||
else if(!strcmp(params->name,"detect_replication_lag"))
|
||||
handle->replicationHeartbeat = config_truth_value(params->value);
|
||||
else if(!strcmp(params->name,"script"))
|
||||
{
|
||||
if(handle->script)
|
||||
free(handle->script);
|
||||
if(access(params->value,X_OK) == 0)
|
||||
{
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
if(access(params->value,F_OK) == 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be executed: %s",
|
||||
params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be found: %s",
|
||||
params->value);
|
||||
}
|
||||
handle->script = NULL;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(params->name, "script"))
|
||||
{
|
||||
if (externcmd_can_execute(params->value))
|
||||
{
|
||||
free(handle->script);
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(params->name,"events"))
|
||||
{
|
||||
if(mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value) != 0)
|
||||
@ -659,10 +645,9 @@ monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
|
||||
|
||||
/* get server version string */
|
||||
server_string = (char *)mysql_get_server_info(database->con);
|
||||
if (server_string) {
|
||||
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
|
||||
if (database->server->server_string)
|
||||
strcpy(database->server->server_string, server_string);
|
||||
if (server_string)
|
||||
{
|
||||
server_set_version_string(database->server, server_string);
|
||||
}
|
||||
|
||||
/* get server_id form current node */
|
||||
|
||||
@ -127,29 +127,15 @@ startMonitor(void *arg,void* opt)
|
||||
{
|
||||
if(!strcmp(params->name,"script"))
|
||||
{
|
||||
if(handle->script)
|
||||
free(handle->script);
|
||||
if(access(params->value,X_OK) == 0)
|
||||
{
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
if(access(params->value,F_OK) == 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be executed: %s",
|
||||
params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: The file cannot be found: %s",
|
||||
params->value);
|
||||
}
|
||||
handle->script = NULL;
|
||||
}
|
||||
if (externcmd_can_execute(params->value))
|
||||
{
|
||||
free(handle->script);
|
||||
handle->script = strdup(params->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_error = true;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(params->name,"events"))
|
||||
{
|
||||
@ -277,11 +263,10 @@ char *server_string;
|
||||
|
||||
/* get server version string */
|
||||
server_string = (char *)mysql_get_server_info(database->con);
|
||||
if (server_string) {
|
||||
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
|
||||
if (database->server->server_string)
|
||||
strcpy(database->server->server_string, server_string);
|
||||
}
|
||||
if (server_string)
|
||||
{
|
||||
server_set_version_string(database->server, server_string);
|
||||
}
|
||||
|
||||
/* Check if the the SQL node is able to contact one or more data nodes */
|
||||
if (mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_number_of_ready_data_nodes'") == 0
|
||||
|
||||
@ -580,6 +580,7 @@ char task_name[BLRM_TASK_NAME_LEN+1] = "";
|
||||
inst->service->name)));
|
||||
if (service->users) {
|
||||
users_free(service->users);
|
||||
service->users = NULL;
|
||||
}
|
||||
|
||||
free(inst);
|
||||
@ -658,6 +659,7 @@ char task_name[BLRM_TASK_NAME_LEN+1] = "";
|
||||
|
||||
if (service->users) {
|
||||
users_free(service->users);
|
||||
service->users = NULL;
|
||||
}
|
||||
|
||||
if (service->dbref && service->dbref->server) {
|
||||
|
||||
@ -86,8 +86,6 @@ return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char** arg_vector;
|
||||
int arg_count = 1;
|
||||
ROUTER_INSTANCE *inst;
|
||||
int fd;
|
||||
int ret;
|
||||
@ -126,21 +124,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
num_args = optind;
|
||||
|
||||
arg_vector = malloc(sizeof(char*)*(arg_count + 1));
|
||||
mxs_log_init(NULL, NULL, LOG_TARGET_DEFAULT);
|
||||
|
||||
if(arg_vector == NULL)
|
||||
{
|
||||
fprintf(stderr,"Error: Memory allocation failed for log manager arg_vector.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
arg_vector[0] = "logmanager";
|
||||
arg_vector[1] = NULL;
|
||||
skygw_logmanager_init(NULL, arg_count, arg_vector);
|
||||
|
||||
skygw_log_set_augmentation(0);
|
||||
|
||||
free(arg_vector);
|
||||
mxs_log_set_augmentation(0);
|
||||
|
||||
if (!debug_out)
|
||||
skygw_log_disable(LOGFILE_DEBUG);
|
||||
@ -151,8 +137,8 @@ int main(int argc, char **argv) {
|
||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||
"Error: Memory allocation failed for ROUTER_INSTANCE")));
|
||||
|
||||
skygw_log_sync_all();
|
||||
skygw_logmanager_done();
|
||||
mxs_log_flush_sync();
|
||||
mxs_log_finish();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -175,8 +161,8 @@ int main(int argc, char **argv) {
|
||||
"Failed to open binlog file %s: %s",
|
||||
path, strerror(errno))));
|
||||
|
||||
skygw_log_sync_all();
|
||||
skygw_logmanager_done();
|
||||
mxs_log_flush_sync();
|
||||
mxs_log_finish();
|
||||
|
||||
free(inst);
|
||||
|
||||
@ -208,13 +194,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
close(inst->binlog_fd);
|
||||
|
||||
skygw_log_sync_all();
|
||||
mxs_log_flush_sync();
|
||||
|
||||
LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE,
|
||||
"Check retcode: %i, Binlog Pos = %llu", ret, inst->binlog_position)));
|
||||
|
||||
skygw_log_sync_all();
|
||||
skygw_logmanager_done();
|
||||
mxs_log_flush_sync();
|
||||
mxs_log_finish();
|
||||
|
||||
free(inst);
|
||||
|
||||
|
||||
@ -73,11 +73,9 @@ static struct option long_options[] = {
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char** arg_vector;
|
||||
ROUTER_INSTANCE *inst;
|
||||
int ret;
|
||||
int rc;
|
||||
int arg_count = 1;
|
||||
char error_string[BINLOG_ERROR_MSG_LEN + 1] = "";
|
||||
CHANGE_MASTER_OPTIONS change_master;
|
||||
char query[255+1]="";
|
||||
@ -91,18 +89,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
roptions = strdup("server-id=3,heartbeat=200,binlogdir=/not_exists/my_dir,transaction_safety=1,master_version=5.6.99-common,master_hostname=common_server,master_uuid=xxx-fff-cccc-fff,master-id=999");
|
||||
|
||||
arg_vector = malloc(sizeof(char*)*(arg_count + 1));
|
||||
|
||||
if(arg_vector == NULL)
|
||||
{
|
||||
fprintf(stderr,"Error: Memory allocation FAILED for log manager arg_vector.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
arg_vector[0] = "logmanager";
|
||||
arg_vector[1] = NULL;
|
||||
skygw_logmanager_init(NULL, arg_count,arg_vector);
|
||||
free(arg_vector);
|
||||
mxs_log_init(NULL, NULL, LOG_TARGET_DEFAULT);
|
||||
|
||||
skygw_log_disable(LOGFILE_DEBUG);
|
||||
skygw_log_disable(LOGFILE_TRACE);
|
||||
@ -140,8 +127,8 @@ int main(int argc, char **argv) {
|
||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||
"Error: Memory allocation FAILED for ROUTER_INSTANCE")));
|
||||
|
||||
skygw_log_sync_all();
|
||||
skygw_logmanager_done();
|
||||
mxs_log_flush_sync();
|
||||
mxs_log_finish();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -591,8 +578,8 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
skygw_log_sync_all();
|
||||
skygw_logmanager_done();
|
||||
mxs_log_flush_sync();
|
||||
mxs_log_finish();
|
||||
|
||||
free(inst);
|
||||
|
||||
|
||||
@ -621,29 +621,48 @@ struct subcommand removeoptions[] = {
|
||||
static void
|
||||
flushlog(DCB *pdcb, char *logname)
|
||||
{
|
||||
if (logname == NULL)
|
||||
bool unrecognized = false;
|
||||
bool deprecated = false;
|
||||
|
||||
if (!strcasecmp(logname, "error"))
|
||||
{
|
||||
}
|
||||
else if (!strcasecmp(logname, "error"))
|
||||
{
|
||||
skygw_log_rotate(LOGFILE_ERROR);
|
||||
deprecated = true;
|
||||
}
|
||||
else if (!strcasecmp(logname, "message"))
|
||||
{
|
||||
skygw_log_rotate(LOGFILE_MESSAGE);
|
||||
deprecated = true;
|
||||
}
|
||||
else if (!strcasecmp(logname, "trace"))
|
||||
{
|
||||
skygw_log_rotate(LOGFILE_TRACE);
|
||||
deprecated = true;
|
||||
}
|
||||
else if (!strcasecmp(logname, "debug"))
|
||||
{
|
||||
skygw_log_rotate(LOGFILE_DEBUG);
|
||||
deprecated = true;
|
||||
}
|
||||
else if (!strcasecmp(logname, "maxscale"))
|
||||
{
|
||||
; // nop
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb_printf(pdcb, "Unexpected logfile name, expected "
|
||||
"error, message, trace or debug.\n");
|
||||
unrecognized = true;
|
||||
}
|
||||
|
||||
if (unrecognized)
|
||||
{
|
||||
dcb_printf(pdcb, "Unexpected logfile name '%s', expected: 'maxscale'.\n", logname);
|
||||
}
|
||||
else
|
||||
{
|
||||
mxs_log_rotate();
|
||||
|
||||
if (deprecated)
|
||||
{
|
||||
dcb_printf(pdcb,
|
||||
"'%s' is deprecated, currently there is only one log 'maxscale', "
|
||||
"which was rotated.\n", logname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,10 +674,7 @@ flushlog(DCB *pdcb, char *logname)
|
||||
static void
|
||||
flushlogs(DCB *pdcb)
|
||||
{
|
||||
skygw_log_rotate(LOGFILE_ERROR);
|
||||
skygw_log_rotate(LOGFILE_MESSAGE);
|
||||
skygw_log_rotate(LOGFILE_TRACE);
|
||||
skygw_log_rotate(LOGFILE_DEBUG);
|
||||
mxs_log_rotate();
|
||||
}
|
||||
|
||||
|
||||
@ -678,8 +694,8 @@ struct subcommand flushoptions[] = {
|
||||
"logs",
|
||||
0,
|
||||
flushlogs,
|
||||
"Flush the content of all log files, close that logs, rename them and open a new log files",
|
||||
"Flush the content of all log files, close that logs, rename them and open a new log files",
|
||||
"Flush the content of all log files, close those logs, rename them and open a new log files",
|
||||
"Flush the content of all log files, close those logs, rename them and open a new log files",
|
||||
{0, 0, 0}
|
||||
},
|
||||
{
|
||||
@ -1100,40 +1116,6 @@ restart_service(DCB *dcb, SERVICE *service)
|
||||
serviceRestart(service);
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *str;
|
||||
unsigned int bit;
|
||||
} ServerBits[] = {
|
||||
{ "running", SERVER_RUNNING },
|
||||
{ "master", SERVER_MASTER },
|
||||
{ "slave", SERVER_SLAVE },
|
||||
{ "synced", SERVER_JOINED },
|
||||
{ "ndb", SERVER_NDB },
|
||||
{ "maintenance", SERVER_MAINT },
|
||||
{ "maint", SERVER_MAINT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
/**
|
||||
* Map the server status bit
|
||||
*
|
||||
* @param str String representation
|
||||
* @return bit value or 0 on error
|
||||
*/
|
||||
static unsigned int
|
||||
server_map_status(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ServerBits[i].str; i++)
|
||||
{
|
||||
if (!strcasecmp(str, ServerBits[i].str))
|
||||
{
|
||||
return ServerBits[i].bit;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the status bit of a server
|
||||
*
|
||||
@ -1603,7 +1585,7 @@ static void enable_log_priority(DCB *dcb, char *arg1)
|
||||
|
||||
if (priority != -1)
|
||||
{
|
||||
mxs_log_enable_priority(priority);
|
||||
mxs_log_set_priority_enabled(priority, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1621,7 +1603,7 @@ static void disable_log_priority(DCB *dcb, char *arg1)
|
||||
|
||||
if (priority != -1)
|
||||
{
|
||||
mxs_log_enable_priority(priority);
|
||||
mxs_log_set_priority_enabled(priority, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -780,7 +780,7 @@ maxinfo_add_mysql_user(SERVICE *service) {
|
||||
"maxinfo: create hex_sha1_sha1_password failed for service user %s",
|
||||
service_user)));
|
||||
users_free(service->users);
|
||||
|
||||
service->users = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -54,7 +54,12 @@ static void exec_select(DCB *dcb, MAXINFO_TREE *tree);
|
||||
static void exec_show_variables(DCB *dcb, MAXINFO_TREE *filter);
|
||||
static void exec_show_status(DCB *dcb, MAXINFO_TREE *filter);
|
||||
static int maxinfo_pattern_match(char *pattern, char *str);
|
||||
|
||||
static void exec_flush(DCB *dcb, MAXINFO_TREE *tree);
|
||||
static void exec_set(DCB *dcb, MAXINFO_TREE *tree);
|
||||
static void exec_clear(DCB *dcb, MAXINFO_TREE *tree);
|
||||
static void exec_shutdown(DCB *dcb, MAXINFO_TREE *tree);
|
||||
static void exec_restart(DCB *dcb, MAXINFO_TREE *tree);
|
||||
void maxinfo_send_ok(DCB *dcb);
|
||||
/**
|
||||
* Execute a parse tree and return the result set or runtime error
|
||||
*
|
||||
@ -72,6 +77,23 @@ maxinfo_execute(DCB *dcb, MAXINFO_TREE *tree)
|
||||
case MAXOP_SELECT:
|
||||
exec_select(dcb, tree);
|
||||
break;
|
||||
|
||||
case MAXOP_FLUSH:
|
||||
exec_flush(dcb, tree);
|
||||
break;
|
||||
case MAXOP_SET:
|
||||
exec_set(dcb, tree);
|
||||
break;
|
||||
case MAXOP_CLEAR:
|
||||
exec_clear(dcb, tree);
|
||||
break;
|
||||
case MAXOP_SHUTDOWN:
|
||||
exec_shutdown(dcb, tree);
|
||||
break;
|
||||
case MAXOP_RESTART:
|
||||
exec_restart(dcb, tree);
|
||||
break;
|
||||
|
||||
case MAXOP_TABLE:
|
||||
case MAXOP_COLUMNS:
|
||||
case MAXOP_LITERAL:
|
||||
@ -274,6 +296,448 @@ char errmsg[120];
|
||||
LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, errmsg)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush all logs to disk and rotate them.
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
void exec_flush_logs(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
mxs_log_rotate();
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* The table of flush commands that are supported
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void (*func)(DCB *, MAXINFO_TREE *);
|
||||
} flush_commands[] = {
|
||||
{ "logs", exec_flush_logs},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a flush command parse tree and return the result set or runtime error
|
||||
*
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
static void
|
||||
exec_flush(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
char errmsg[120];
|
||||
|
||||
for (i = 0; flush_commands[i].name; i++)
|
||||
{
|
||||
if (strcasecmp(flush_commands[i].name, tree->value) == 0)
|
||||
{
|
||||
(*flush_commands[i].func)(dcb, tree->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Unsupported flush command '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
skygw_log_write(LE, errmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the server status.
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_set_server(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
SERVER* server = server_find_by_unique_name(tree->value);
|
||||
char errmsg[120];
|
||||
|
||||
if (server)
|
||||
{
|
||||
int status = server_map_status(tree->right->value);
|
||||
if (status != 0)
|
||||
{
|
||||
server_set_status(server, status);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->right->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->right->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->right->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The table of set commands that are supported
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void (*func)(DCB *, MAXINFO_TREE *);
|
||||
} set_commands[] = {
|
||||
{ "server", exec_set_server},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a set command parse tree and return the result set or runtime error
|
||||
*
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
static void
|
||||
exec_set(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
char errmsg[120];
|
||||
|
||||
for (i = 0; set_commands[i].name; i++)
|
||||
{
|
||||
if (strcasecmp(set_commands[i].name, tree->value) == 0)
|
||||
{
|
||||
(*set_commands[i].func)(dcb, tree->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Unsupported set command '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
skygw_log_write(LE, errmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the server status.
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_clear_server(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
SERVER* server = server_find_by_unique_name(tree->value);
|
||||
char errmsg[120];
|
||||
|
||||
if (server)
|
||||
{
|
||||
int status = server_map_status(tree->right->value);
|
||||
if (status != 0)
|
||||
{
|
||||
server_clear_status(server, status);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->right->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->right->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->right->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The table of clear commands that are supported
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void (*func)(DCB *, MAXINFO_TREE *);
|
||||
} clear_commands[] = {
|
||||
{ "server", exec_clear_server},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a clear command parse tree and return the result set or runtime error
|
||||
*
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
static void
|
||||
exec_clear(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
char errmsg[120];
|
||||
|
||||
for (i = 0; clear_commands[i].name; i++)
|
||||
{
|
||||
if (strcasecmp(clear_commands[i].name, tree->value) == 0)
|
||||
{
|
||||
(*clear_commands[i].func)(dcb, tree->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Unsupported clear command '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
skygw_log_write(LE, errmsg);
|
||||
}
|
||||
|
||||
extern void shutdown_server();
|
||||
|
||||
/**
|
||||
* MaxScale shutdown
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_shutdown_maxscale(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
shutdown_server();
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a monitor
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_shutdown_monitor(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
char errmsg[120];
|
||||
if (tree && tree->value)
|
||||
{
|
||||
MONITOR* monitor = monitor_find(tree->value);
|
||||
if (monitor)
|
||||
{
|
||||
monitorStop(monitor);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errmsg, "Missing argument for 'SHUTDOWN MONITOR'");
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a service
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_shutdown_service(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
char errmsg[120];
|
||||
if (tree && tree->value)
|
||||
{
|
||||
SERVICE* service = service_find(tree->value);
|
||||
if (service)
|
||||
{
|
||||
serviceStop(service);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errmsg, "Missing argument for 'SHUTDOWN SERVICE'");
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The table of shutdown commands that are supported
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void (*func)(DCB *, MAXINFO_TREE *);
|
||||
} shutdown_commands[] = {
|
||||
{ "maxscale", exec_shutdown_maxscale},
|
||||
{ "monitor", exec_shutdown_monitor},
|
||||
{ "service", exec_shutdown_service},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a shutdown command parse tree and return OK or runtime error
|
||||
*
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
static void
|
||||
exec_shutdown(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
char errmsg[120];
|
||||
|
||||
for (i = 0; shutdown_commands[i].name; i++)
|
||||
{
|
||||
if (strcasecmp(shutdown_commands[i].name, tree->value) == 0)
|
||||
{
|
||||
(*shutdown_commands[i].func)(dcb, tree->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Unsupported shutdown command '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
skygw_log_write(LE, errmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart a monitor
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_restart_monitor(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
char errmsg[120];
|
||||
if (tree && tree->value)
|
||||
{
|
||||
MONITOR* monitor = monitor_find(tree->value);
|
||||
if (monitor)
|
||||
{
|
||||
monitorStart(monitor, NULL);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errmsg, "Missing argument for 'RESTART MONITOR'");
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart a service
|
||||
* @param dcb Client DCB
|
||||
* @param tree Parse tree
|
||||
*/
|
||||
void exec_restart_service(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
char errmsg[120];
|
||||
if (tree && tree->value)
|
||||
{
|
||||
SERVICE* service = service_find(tree->value);
|
||||
if (service)
|
||||
{
|
||||
serviceRestart(service);
|
||||
maxinfo_send_ok(dcb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Invalid argument '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errmsg, "Missing argument for 'RESTART SERVICE'");
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The table of restart commands that are supported
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void (*func)(DCB *, MAXINFO_TREE *);
|
||||
} restart_commands[] = {
|
||||
{ "monitor", exec_restart_monitor},
|
||||
{ "service", exec_restart_service},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a restart command parse tree and return OK or runtime error
|
||||
*
|
||||
* @param dcb The DCB that connects to the client
|
||||
* @param tree The parse tree for the query
|
||||
*/
|
||||
static void
|
||||
exec_restart(DCB *dcb, MAXINFO_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
char errmsg[120];
|
||||
|
||||
for (i = 0; restart_commands[i].name; i++)
|
||||
{
|
||||
if (strcasecmp(restart_commands[i].name, tree->value) == 0)
|
||||
{
|
||||
(*restart_commands[i].func)(dcb, tree->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strlen(tree->value) > 80) // Prevent buffer overrun
|
||||
{
|
||||
tree->value[80] = 0;
|
||||
}
|
||||
sprintf(errmsg, "Unsupported restart command '%s'", tree->value);
|
||||
maxinfo_send_error(dcb, 0, errmsg);
|
||||
skygw_log_write(LE, errmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current MaxScale version
|
||||
*
|
||||
@ -764,3 +1228,25 @@ extern char *strcasestr();
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an OK packet to the client.
|
||||
* @param dcb The DCB that connects to the client
|
||||
*/
|
||||
void maxinfo_send_ok(DCB *dcb)
|
||||
{
|
||||
static const char ok_packet[] ={
|
||||
0x07, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
GWBUF* buffer = gwbuf_alloc(sizeof(ok_packet));
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
memcpy(buffer->start, ok_packet, sizeof(ok_packet));
|
||||
dcb->func.write(dcb, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,8 @@ static void free_tree(MAXINFO_TREE *);
|
||||
static char *fetch_token(char *, int *, char **);
|
||||
static MAXINFO_TREE *parse_column_list(char **sql);
|
||||
static MAXINFO_TREE *parse_table_name(char **sql);
|
||||
|
||||
MAXINFO_TREE* maxinfo_parse_literals(MAXINFO_TREE *tree, int min_args, char *ptr,
|
||||
PARSE_ERROR *parse_error);
|
||||
|
||||
/**
|
||||
* Parse a SQL subset for the maxinfo plugin and return a parse tree
|
||||
@ -111,6 +112,67 @@ MAXINFO_TREE *col, *table;
|
||||
table = parse_table_name(&ptr);
|
||||
return make_tree_node(MAXOP_SELECT, NULL, col, table);
|
||||
#endif
|
||||
case LT_FLUSH:
|
||||
free(text); // not needed
|
||||
ptr = fetch_token(ptr, &token, &text);
|
||||
return make_tree_node(MAXOP_FLUSH, text, NULL, NULL);
|
||||
|
||||
case LT_SHUTDOWN:
|
||||
free(text);
|
||||
ptr = fetch_token(ptr, &token, &text);
|
||||
tree = make_tree_node(MAXOP_SHUTDOWN, text, NULL, NULL);
|
||||
|
||||
if ((ptr = fetch_token(ptr, &token, &text)) == NULL)
|
||||
{
|
||||
/** Possibly SHUTDOWN MAXSCALE */
|
||||
return tree;
|
||||
}
|
||||
tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL);
|
||||
|
||||
if ((ptr = fetch_token(ptr, &token, &text)) != NULL)
|
||||
{
|
||||
/** Unknown token after SHUTDOWN MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
return tree;
|
||||
|
||||
case LT_RESTART:
|
||||
free(text);
|
||||
ptr = fetch_token(ptr, &token, &text);
|
||||
tree = make_tree_node(MAXOP_RESTART, text, NULL, NULL);
|
||||
|
||||
if ((ptr = fetch_token(ptr, &token, &text)) == NULL)
|
||||
{
|
||||
/** Missing token for RESTART MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL);
|
||||
|
||||
if ((ptr = fetch_token(ptr, &token, &text)) != NULL)
|
||||
{
|
||||
/** Unknown token after RESTART MONITOR|SERVICE */
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
return NULL;
|
||||
}
|
||||
return tree;
|
||||
|
||||
case LT_SET:
|
||||
free(text); // not needed
|
||||
ptr = fetch_token(ptr, &token, &text);
|
||||
tree = make_tree_node(MAXOP_SET, text, NULL, NULL);
|
||||
return maxinfo_parse_literals(tree, 2, ptr, parse_error);
|
||||
|
||||
case LT_CLEAR:
|
||||
free(text); // not needed
|
||||
ptr = fetch_token(ptr, &token, &text);
|
||||
tree = make_tree_node(MAXOP_CLEAR, text, NULL, NULL);
|
||||
return maxinfo_parse_literals(tree, 2, ptr, parse_error);
|
||||
break;
|
||||
default:
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
return NULL;
|
||||
@ -231,18 +293,24 @@ free_tree(MAXINFO_TREE *tree)
|
||||
/**
|
||||
* The set of keywords known to the tokeniser
|
||||
*/
|
||||
static struct {
|
||||
char *text;
|
||||
int token;
|
||||
static struct
|
||||
{
|
||||
char *text;
|
||||
int token;
|
||||
} keywords[] = {
|
||||
{ "show", LT_SHOW },
|
||||
{ "select", LT_SELECT },
|
||||
{ "from", LT_FROM },
|
||||
{ "like", LT_LIKE },
|
||||
{ "=", LT_EQUAL },
|
||||
{ ",", LT_COMMA },
|
||||
{ "*", LT_STAR },
|
||||
{ NULL, 0 }
|
||||
{ "show", LT_SHOW},
|
||||
{ "select", LT_SELECT},
|
||||
{ "from", LT_FROM},
|
||||
{ "like", LT_LIKE},
|
||||
{ "=", LT_EQUAL},
|
||||
{ ",", LT_COMMA},
|
||||
{ "*", LT_STAR},
|
||||
{ "flush", LT_FLUSH},
|
||||
{ "set", LT_SET},
|
||||
{ "clear", LT_CLEAR},
|
||||
{ "shutdown", LT_SHUTDOWN},
|
||||
{ "restart", LT_RESTART},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -322,3 +390,36 @@ int i;
|
||||
*token = LT_STRING;
|
||||
return s2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the remaining arguments as literals.
|
||||
* @param tree Previous head of the parse tree
|
||||
* @param min_args Minimum required number of arguments
|
||||
* @param ptr Pointer to client command
|
||||
* @param parse_error Pointer to parsing error to fill
|
||||
* @return Parsed tree or NULL if parsing failed
|
||||
*/
|
||||
MAXINFO_TREE* maxinfo_parse_literals(MAXINFO_TREE *tree, int min_args, char *ptr,
|
||||
PARSE_ERROR *parse_error)
|
||||
{
|
||||
int token;
|
||||
MAXINFO_TREE* node = tree;
|
||||
char *text;
|
||||
for(int i = 0; i < min_args; i++)
|
||||
{
|
||||
if((ptr = fetch_token(ptr, &token, &text)) == NULL ||
|
||||
(node->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL)) == NULL)
|
||||
{
|
||||
*parse_error = PARSE_SYNTAX_ERROR;
|
||||
free_tree(tree);
|
||||
if(ptr)
|
||||
{
|
||||
free(text);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
node = node->right;
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user