[sheepdog] [PATCH V4 1/4] collie: rename 'collie recover' to 'collie recover force'

Yunkai Zhang yunkai.me at gmail.com
Wed Aug 1 09:19:19 CEST 2012


From: Yunkai Zhang <qiushu.zyk at taobao.com>

V4:
- fix some coding style(but reserve some lines overwrited 80 columns which is
  harmless I think)

V3:
- correct commit log
--------------------------------------------- >8

Rename 'collie recover' to 'collie recover force' so that we can introduce
other two recover subcommands: {enable|disable} 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         | 44 +++++++++++++++++------
 collie/collie.c          | 93 ++++++++++++++++++++++++++++++++++++++++--------
 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, 142 insertions(+), 53 deletions(-)

diff --git a/collie/cluster.c b/collie/cluster.c
index bfa06ea..089add9 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,41 @@ 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},
-	{"cleanup", NULL, "aph", "cleanup the useless snapshot data from recovery",
-	0, cluster_cleanup},
+	 NULL, 0, cluster_snapshot},
+	{"cleanup", NULL, "aph",
+	 "cleanup the useless snapshot data from recovery",
+	 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..b112b73 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,32 @@ 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) {
+		n = 0;
+		while (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 +325,16 @@ 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 +349,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..2af4eb3 100644
--- a/collie/node.c
+++ b/collie/node.c
@@ -209,15 +209,15 @@ static int node_kill(int argc, char **argv)
 }
 
 static struct subcommand node_cmd[] = {
-	{"kill", "<node id>", "aprh", "kill node",
+	{"kill", "<node id>", "aprh", "kill node", NULL,
 	 SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, node_kill},
-	{"list", NULL, "aprh", "list nodes",
+	{"list", NULL, "aprh", "list nodes", NULL,
 	 SUBCMD_FLAG_NEED_NODELIST, node_list},
-	{"info", NULL, "aprh", "show information about each node",
+	{"info", NULL, "aprh", "show information about each node", NULL,
 	 SUBCMD_FLAG_NEED_NODELIST, node_info},
-	{"recovery", NULL, "aprh", "show nodes in recovery",
+	{"recovery", NULL, "aprh", "show nodes in recovery", NULL,
 	 SUBCMD_FLAG_NEED_NODELIST, node_recovery},
-	{"cache", "<cache size>", "aprh", "specify max cache size",
+	{"cache", "<cache size>", "aprh", "specify max cache size", 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




More information about the sheepdog mailing list