From: Yunkai Zhang <qiushu.zyk at taobao.com> Rename 'collie recover' to 'collie recover force' so that we can introduce other two recover subcommands: {stop|start} in the next patch. In order to keep consistent naming, I also renamed some related functions and flags. As we need to express subcommand's subcommand(such as 'recover' is a subcommand of 'collie' and 'force' is a subcommand of 'recover'), I have modified subcommand's data structure and refactored some helper funcions a bit. Signed-off-by: Yunkai Zhang <qiushu.zyk at taobao.com> --- collie/cluster.c | 40 +++++++++++++++------ collie/collie.c | 92 ++++++++++++++++++++++++++++++++++++++++-------- collie/collie.h | 2 ++ collie/node.c | 10 +++--- collie/vdi.c | 30 ++++++++-------- include/internal_proto.h | 2 +- include/sheep.h | 2 +- include/sheepdog_proto.h | 2 +- sheep/ops.c | 10 +++--- 9 files changed, 138 insertions(+), 52 deletions(-) diff --git a/collie/cluster.c b/collie/cluster.c index bfa06ea..9ddd726 100644 --- a/collie/cluster.c +++ b/collie/cluster.c @@ -343,12 +343,12 @@ static int cluster_cleanup(int argc, char **argv) #define RECOVER_PRINT \ "Caution! Please try starting all the cluster nodes normally before\n\ running this command.\n\n\ -The cluster may need to be recovered manually if:\n\ +The cluster may need to be force recovered if:\n\ - the master node fails to start because of epoch mismatch; or\n\ - some nodes fail to start after a cluster shutdown.\n\n\ Are you sure you want to continue? [yes/no]: " -static int cluster_recover(int argc, char **argv) +static int cluster_force_recover(int argc, char **argv) { int ret; struct sd_req hdr; @@ -367,7 +367,7 @@ static int cluster_recover(int argc, char **argv) return EXIT_SUCCESS; } - sd_init_req(&hdr, SD_OP_RECOVER); + sd_init_req(&hdr, SD_OP_FORCE_RECOVER); hdr.epoch = sd_epoch; ret = send_light_req(&hdr, sdhost, sdport); @@ -379,19 +379,39 @@ static int cluster_recover(int argc, char **argv) return EXIT_SUCCESS; } +/* Subcommand list of recover */ +static struct subcommand cluster_recover_cmd[] = { + {"force", NULL, NULL, "force recover cluster immediately", + NULL, 0, cluster_force_recover}, + {NULL}, +}; + +static int cluster_recover(int argc, char **argv) +{ + int i; + + for (i = 0; cluster_recover_cmd[i].name; i++) { + if (!strcmp(cluster_recover_cmd[i].name, argv[3])) + return cluster_recover_cmd[i].fn(argc, argv); + } + + subcommand_usage(argv[1], argv[2], EXIT_FAILURE); + return EXIT_FAILURE; +} + static struct subcommand cluster_cmd[] = { {"info", NULL, "aprh", "show cluster information", - SUBCMD_FLAG_NEED_NODELIST, cluster_info}, + NULL, SUBCMD_FLAG_NEED_NODELIST, cluster_info}, {"format", NULL, "bcmaph", "create a Sheepdog store", - 0, cluster_format}, + NULL, 0, cluster_format}, {"shutdown", NULL, "aph", "stop Sheepdog", - SUBCMD_FLAG_NEED_NODELIST, cluster_shutdown}, - {"recover", NULL, "afph", "manually recover the cluster", - 0, cluster_recover}, + NULL, SUBCMD_FLAG_NEED_NODELIST, cluster_shutdown}, {"snapshot", NULL, "aRlph", "snapshot/restore the cluster", - 0, cluster_snapshot}, + NULL, 0, cluster_snapshot}, {"cleanup", NULL, "aph", "cleanup the useless snapshot data from recovery", - 0, cluster_cleanup}, + NULL, 0, cluster_cleanup}, + {"recover", NULL, "afph", "See 'collie cluster recover' for more information\n", + cluster_recover_cmd, SUBCMD_FLAG_NEED_THIRD_ARG, cluster_recover}, {NULL,}, }; diff --git a/collie/collie.c b/collie/collie.c index fda9a59..423b4e4 100644 --- a/collie/collie.c +++ b/collie/collie.c @@ -50,7 +50,7 @@ static const struct sd_option collie_options[] = { { 0, NULL, 0, NULL }, }; -static void usage(struct command *commands, int status); +static void usage(const struct command *commands, int status); uint32_t sd_epoch; @@ -142,6 +142,47 @@ static const struct sd_option *find_opt(int ch) exit(EXIT_SYSFAIL); } +static void init_commands(const struct command **commands) +{ + static struct command *cmds; + struct command command_list[] = { + vdi_command, + node_command, + cluster_command, + debug_command, + {NULL,} + }; + + if (!cmds) { + cmds = (struct command *)malloc(sizeof(command_list)); + memcpy(cmds, command_list, sizeof(command_list)); + } + + *commands = cmds; + return; +} + +static const struct subcommand *find_subcmd(const char *cmd, const char *subcmd) +{ + int i, j; + const struct command *commands; + const struct subcommand *sub; + + init_commands(&commands); + + for (i = 0; commands[i].name; i++) { + if (!strcmp(commands[i].name, cmd)) { + sub = commands[i].sub; + for (j = 0; sub[j].name; j++) { + if (!strcmp(sub[j].name, subcmd)) + return &sub[j]; + } + } + } + + return NULL; +} + static char *build_short_options(const char *opts) { static char sopts[256], *p; @@ -180,7 +221,8 @@ static struct option *build_long_options(const char *opts) return lopts; } -static unsigned long setup_command(struct command *commands, char *cmd, char *subcmd) +static unsigned long setup_commands(const struct command *commands, + char *cmd, char *subcmd) { int i, found = 0; struct subcommand *s; @@ -223,7 +265,7 @@ static unsigned long setup_command(struct command *commands, char *cmd, char *su return flags; } -static void usage(struct command *commands, int status) +static void usage(const struct command *commands, int status) { int i; struct subcommand *s; @@ -248,13 +290,30 @@ static void usage(struct command *commands, int status) exit(status); } -static void subcommand_usage(char *cmd, char *subcmd, int status) +void subcommand_usage(char *cmd, char *subcmd, int status) { - int i, len = strlen(command_options); + int i, n, len = strlen(command_options); const struct sd_option *sd_opt; + const struct subcommand *sub, *subsub; char name[64]; printf("Usage: %s %s %s", program_name, cmd, subcmd); + + /* Show subcmd's subcommands if necessary */ + sub = find_subcmd(cmd, subcmd); + subsub = sub->sub; + if (subsub) { + for (n = 0; subsub[n].name; n++); + if (n == 1) + printf(" %s", subsub[0].name); + else if (n > 1) { + printf(" {%s", subsub[0].name); + for (i = 1; i < n; i++) + printf("|%s", subsub[i].name); + printf("}"); + } + } + for (i = 0; i < len; i++) { sd_opt = find_opt(command_options[i]); if (sd_opt->has_arg) @@ -264,7 +323,17 @@ static void subcommand_usage(char *cmd, char *subcmd, int status) } if (command_arg) printf(" %s", command_arg); - printf("\nOptions:\n"); + + printf("\n"); + if (subsub) { + printf("Available subcommands:\n"); + for (i = 0; subsub[i].name; i++) { + printf(" %-24s%s\n", subsub[i].name, subsub[i].desc); + } + + } + + printf("Options:\n"); for (i = 0; i < len; i++) { sd_opt = find_opt(command_options[i]); sprintf(name, "-%c, --%s", sd_opt->val, sd_opt->name); @@ -279,21 +348,16 @@ int main(int argc, char **argv) int ch, longindex, ret; unsigned long flags; struct option *long_options; + const struct command *commands; const char *short_options; char *p; - struct command commands[] = { - vdi_command, - node_command, - cluster_command, - debug_command, - {NULL,} - }; + init_commands(&commands); if (argc < 3) usage(commands, 0); - flags = setup_command(commands, argv[1], argv[2]); + flags = setup_commands(commands, argv[1], argv[2]); optind = 3; diff --git a/collie/collie.h b/collie/collie.h index 75a675c..e6874c0 100644 --- a/collie/collie.h +++ b/collie/collie.h @@ -46,9 +46,11 @@ struct subcommand { const char *arg; const char *opts; const char *desc; + struct subcommand *sub; unsigned long flags; int (*fn)(int, char **); }; +void subcommand_usage(char *cmd, char *subcmd, int status); extern const char *sdhost; extern int sdport; diff --git a/collie/node.c b/collie/node.c index 0192dba..ef1626c 100644 --- a/collie/node.c +++ b/collie/node.c @@ -210,15 +210,15 @@ static int node_kill(int argc, char **argv) static struct subcommand node_cmd[] = { {"kill", "<node id>", "aprh", "kill node", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, node_kill}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, node_kill}, {"list", NULL, "aprh", "list nodes", - SUBCMD_FLAG_NEED_NODELIST, node_list}, + NULL, SUBCMD_FLAG_NEED_NODELIST, node_list}, {"info", NULL, "aprh", "show information about each node", - SUBCMD_FLAG_NEED_NODELIST, node_info}, + NULL, SUBCMD_FLAG_NEED_NODELIST, node_info}, {"recovery", NULL, "aprh", "show nodes in recovery", - SUBCMD_FLAG_NEED_NODELIST, node_recovery}, + NULL, SUBCMD_FLAG_NEED_NODELIST, node_recovery}, {"cache", "<cache size>", "aprh", "specify max cache size", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, node_cache}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, node_cache}, {NULL,}, }; diff --git a/collie/vdi.c b/collie/vdi.c index 1506d24..ad3583f 100644 --- a/collie/vdi.c +++ b/collie/vdi.c @@ -1494,35 +1494,35 @@ out: static struct subcommand vdi_cmd[] = { {"check", "<vdiname>", "saph", "check and repair image's consistency", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_check}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_check}, {"create", "<vdiname> <size>", "Paph", "create an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_create}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_create}, {"snapshot", "<vdiname>", "saph", "create a snapshot", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_snapshot}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_snapshot}, {"clone", "<src vdi> <dst vdi>", "sPaph", "clone an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_clone}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_clone}, {"delete", "<vdiname>", "saph", "delete an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_delete}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_delete}, {"list", "[vdiname]", "aprh", "list images", - SUBCMD_FLAG_NEED_NODELIST, vdi_list}, + NULL, SUBCMD_FLAG_NEED_NODELIST, vdi_list}, {"tree", NULL, "aph", "show images in tree view format", - SUBCMD_FLAG_NEED_NODELIST, vdi_tree}, + NULL, SUBCMD_FLAG_NEED_NODELIST, vdi_tree}, {"graph", NULL, "aph", "show images in Graphviz dot format", - SUBCMD_FLAG_NEED_NODELIST, vdi_graph}, + NULL, SUBCMD_FLAG_NEED_NODELIST, vdi_graph}, {"object", "<vdiname>", "isaph", "show object information in the image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_object}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_object}, {"track", "<vdiname>", "isaph", "show the object epoch trace in the image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_track}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_track}, {"setattr", "<vdiname> <key> [value]", "dxaph", "set a VDI attribute", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_setattr}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_setattr}, {"getattr", "<vdiname> <key>", "aph", "get a VDI attribute", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_getattr}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_getattr}, {"resize", "<vdiname> <new size>", "aph", "resize an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_resize}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_resize}, {"read", "<vdiname> [<offset> [<len>]]", "saph", "read data from an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_read}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_read}, {"write", "<vdiname> [<offset> [<len>]]", "aph", "write data to an image", - SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_write}, + NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_write}, {NULL,}, }; diff --git a/include/internal_proto.h b/include/internal_proto.h index 3e22124..a6e54b8 100644 --- a/include/internal_proto.h +++ b/include/internal_proto.h @@ -42,7 +42,7 @@ #define SD_OP_STAT_SHEEP 0x86 #define SD_OP_STAT_CLUSTER 0x87 #define SD_OP_GET_VDI_ATTR 0x89 -#define SD_OP_RECOVER 0x8a +#define SD_OP_FORCE_RECOVER 0x8a #define SD_OP_GET_STORE_LIST 0x90 #define SD_OP_SNAPSHOT 0x91 #define SD_OP_RESTORE 0x92 diff --git a/include/sheep.h b/include/sheep.h index 8632667..5795111 100644 --- a/include/sheep.h +++ b/include/sheep.h @@ -160,7 +160,7 @@ static inline const char *sd_strerror(int err) {SD_RES_WAIT_FOR_JOIN, "Waiting for other nodes to join cluster"}, {SD_RES_JOIN_FAILED, "Node has failed to join cluster"}, {SD_RES_HALT, "IO has halted as there are too few living nodes"}, - {SD_RES_MANUAL_RECOVER, "Cluster is running/halted and cannot be manually recovered"}, + {SD_RES_FORCE_RECOVER, "Cluster is running/halted and cannot be force recovered"}, {SD_RES_NO_STORE, "Targeted backend store is not found"}, {SD_RES_NO_SUPPORT, "Operation is not supported"}, {SD_RES_CLUSTER_RECOVERING, "Cluster is recovering"}, diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h index 45a4b81..66101c4 100644 --- a/include/sheepdog_proto.h +++ b/include/sheepdog_proto.h @@ -62,7 +62,7 @@ #define SD_RES_WAIT_FOR_JOIN 0x17 /* Sheepdog is waiting for other nodes joining */ #define SD_RES_JOIN_FAILED 0x18 /* Target node had failed to join sheepdog */ #define SD_RES_HALT 0x19 /* Sheepdog is stopped doing IO */ -#define SD_RES_MANUAL_RECOVER 0x1A /* Users should not manually recover this cluster */ +#define SD_RES_FORCE_RECOVER 0x1A /* Users should not force recover this cluster */ #define SD_RES_NO_STORE 0x20 /* No targeted backend store */ #define SD_RES_NO_SUPPORT 0x21 /* Operation is not supported by backend store */ #define SD_RES_CLUSTER_RECOVERING 0x22 /* Cluster is recovering. */ diff --git a/sheep/ops.c b/sheep/ops.c index 6c92575..75df906 100644 --- a/sheep/ops.c +++ b/sheep/ops.c @@ -408,7 +408,7 @@ static int local_get_epoch(struct request *req) return SD_RES_SUCCESS; } -static int cluster_manual_recover(const struct sd_req *req, struct sd_rsp *rsp, +static int cluster_force_recover(const struct sd_req *req, struct sd_rsp *rsp, void *data) { struct vnode_info *old_vnode_info, *vnode_info; @@ -422,7 +422,7 @@ static int cluster_manual_recover(const struct sd_req *req, struct sd_rsp *rsp, * In both case, the nodes(s) stat is WAIT_FOR_JOIN. */ if (sys->status != SD_STATUS_WAIT_FOR_JOIN) - return SD_RES_MANUAL_RECOVER; + return SD_RES_FORCE_RECOVER; ret = get_cluster_copies(&c); if (ret) @@ -844,11 +844,11 @@ static struct sd_op_template sd_ops[] = { .type = SD_OP_TYPE_CLUSTER, }, - [SD_OP_RECOVER] = { - .name = "RECOVER", + [SD_OP_FORCE_RECOVER] = { + .name = "FORCE_RECOVER", .type = SD_OP_TYPE_CLUSTER, .force = 1, - .process_main = cluster_manual_recover, + .process_main = cluster_force_recover, }, [SD_OP_SNAPSHOT] = { -- 1.7.11.2 |