/* Parses the interactive commands */ #include #include #include #include #include #ifdef HAVE_READLINE_HISTORY_H #include #endif #include #include "vqsim.h" static void do_usage(void) { printf(" All node IDs in the cluster are unique and belong to a numbered 'partition' (default=0)\n"); printf("\n"); printf("up [:][[,] ...] [[:][...]] [...]\n"); printf(" bring node(s) online in the specified partition(s)\n"); printf("down ,[...]\n"); printf(" send nodes offline (shut them down)\n"); printf("move/split [:][[,] ...] [[:][...]] [...]\n"); printf(" Move nodes from one partition to another (netsplit)\n"); printf(" here is the partition to move the nodes to\n"); printf("join [] ... \n"); printf(" Join partitions together (reverse of a netsplit)\n"); printf("qdevice on|off [:][[,] ...] [[:][...]] [...]\n"); printf(" Enable quorum device in specified nodes\n"); printf("autofence on|off\n"); printf(" automatically 'down' nodes on inquorate side on netsplit\n"); printf("timeout (default 250)\n"); printf(" Wait a maximum of milli-seconds for the next command to complete.\n"); printf("sync on|off (default on)\n"); printf(" enable/disable synchronous execution of commands (wait for completion)\n"); printf("assert on|off (default off)\n"); printf(" Abort the simulation run if a timeout expires\n"); printf("show Show current nodes status\n"); printf("exit\n\n"); } /* Commands return 0 if they return immediately, >1 if we are waiting for replies from nodes */ typedef int (*cmd_routine_t)(int argc, char **argv); static int run_up_cmd(int argc, char **argv); static int run_down_cmd(int argc, char **argv); static int run_join_cmd(int argc, char **argv); static int run_move_cmd(int argc, char **argv); static int run_exit_cmd(int argc, char **argv); static int run_show_cmd(int argc, char **argv); static int run_timeout_cmd(int argc, char **argv); static int run_assert_cmd(int argc, char **argv); static int run_autofence_cmd(int argc, char **argv); static int run_qdevice_cmd(int argc, char **argv); static int run_sync_cmd(int argc, char **argv); static struct cmd_list_struct { const char *cmd; int min_args; cmd_routine_t cmd_runner; } cmd_list[] = { { "up", 1, run_up_cmd}, { "down", 1, run_down_cmd}, { "move", 2, run_move_cmd}, { "split", 2, run_move_cmd}, { "join", 2, run_join_cmd}, { "autofence", 1, run_autofence_cmd}, { "qdevice", 1, run_qdevice_cmd}, { "show", 0, run_show_cmd}, { "timeout", 1, run_timeout_cmd}, { "sync", 1, run_sync_cmd}, { "assert", 1, run_assert_cmd}, { "exit", 0, run_exit_cmd}, { "quit", 0, run_exit_cmd}, { "q", 0, run_exit_cmd}, }; static int num_cmds = (sizeof(cmd_list)) / sizeof(struct cmd_list_struct); #define MAX_ARGS 1024 /* Takes a :[[,]...] list and return it as a partition and a list of nodes. Returns 0 if successful, -1 if not */ static int parse_partition_nodelist(char *string, int *partition, int *num_nodes, int **retnodes) { int i; int nodecount; int len; int last_comma; char *nodeptr; int *nodes; char *colonptr = strchr(string, ':'); if (colonptr) { *colonptr = '\0'; nodeptr = colonptr+1; *partition = atoi(string); } else { /* Default to partition 0 */ *partition = 0; nodeptr = string; } /* Count the number of commas and allocate space for the nodes */ nodecount = 0; for (i=0; i MAX_NODES) { return -1; } nodes = malloc(sizeof(int) * nodecount); if (!nodes) { return -1; } nodecount = 0; last_comma = 0; len = strlen(nodeptr); for (i=0; i<=len; i++) { if (nodeptr[i] == ',' || nodeptr[i] == '\0') { nodeptr[i] = '\0'; nodes[nodecount++] = atoi(&nodeptr[last_comma]); last_comma = i+1; } } *num_nodes = nodecount; *retnodes = nodes; return 0; } void parse_input_command(char *rl_cmd) { int i; int argc = 0; int valid_cmd = 0; char *argv[MAX_ARGS]; int last_arg_start = 0; int last_was_space = 0; int len; int ret = 0; char *cmd; /* ^D quits */ if (rl_cmd == NULL) { (void)run_exit_cmd(0, NULL); } /* '#' starts a comment */ if (rl_cmd[0] == '#') { return; } cmd = strdup(rl_cmd); /* Split cmd up into args * destroying the original string mwahahahaha */ len = strlen(cmd); /* Span leading spaces */ for (i=0; cmd[i] == ' '; i++) ; last_arg_start = i; for (; i<=len; i++) { if (cmd[i] == ' ' || cmd[i] == '\0') { /* Allow multiple spaces */ if (last_was_space) { continue; } cmd[i] = '\0'; last_was_space = 1; argv[argc] = &cmd[last_arg_start]; argc++; } else { if (last_was_space) { last_arg_start = i; } last_was_space = 0; } } /* Ignore null commands */ if (argc < 1 || strlen(argv[0]) == 0) { free(cmd); resume_kb_input(0); return; } #ifdef HAVE_READLINE_HISTORY_H add_history(rl_cmd); #endif /* Dispatch command */ for (i=0; i