发自我的 iPhone 在 2012-7-31,17:05,Yunkai Zhang <yunkai.me at gmail.com> 写道: > 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 Sorry,there is a typo in commit log: s/{stop|start}/{enable|disable}/ I use 'enable' and 'disable' instead of 'start' and 'stop' in the new cold. I think they will be more descriptive. > 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 > |