From: levin li <xingke.lwp at taobao.com> When I was debuging the recovery issue(commit: 470533b), I found it conveninet to have such a tool to track an object's trace at each epoch to check whether an object is placed at the right place, so I add this operation for collie at such case. usage: $collie/collie vdi track debian -i 3 output: obj b1f0b000000003 locations at epoch 1, copies = 3 --------------------------------------------------- 127.0.0.1:7004 127.0.0.1:7000 127.0.0.1:7001 obj b1f0b000000003 locations at epoch 2, copies = 3 --------------------------------------------------- 127.0.0.1:7007 127.0.0.1:7004 127.0.0.1:7000 obj b1f0b000000003 locations at epoch 3, copies = 3 --------------------------------------------------- 127.0.0.1:7007 127.0.0.1:7008 127.0.0.1:7004 Signed-off-by: levin li <xingke.lwp at taobao.com> --- collie/vdi.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sheep.h | 1 + sheep/ops.c | 1 + sheep/sheep_priv.h | 1 + sheep/store.c | 2 +- 5 files changed, 132 insertions(+), 1 deletions(-) diff --git a/collie/vdi.c b/collie/vdi.c index 9675774..ac046b8 100644 --- a/collie/vdi.c +++ b/collie/vdi.c @@ -32,6 +32,9 @@ struct get_vdi_info { uint32_t snapid; }; +struct sd_node latest_node_list[SD_MAX_NODES]; +int nr_latest_node_list; + static int parse_option_size(const char *value, uint64_t *ret) { char *postfix; @@ -791,6 +794,129 @@ static int vdi_object(int argc, char **argv) return EXIT_SUCCESS; } +static int print_obj_epoch(uint64_t oid) +{ + int i, j, fd, ret, idx; + struct sd_vdi_req hdr; + struct sd_vdi_rsp *rsp = (struct sd_vdi_rsp *)&hdr; + unsigned rlen, wlen; + struct sd_vnode vnodes[SD_MAX_VNODES]; + struct epoch_log *logs; + int vnodes_nr, nr_logs, log_length; + char host[128]; + + log_length = node_list_version * sizeof(struct epoch_log); +again: + logs = malloc(log_length); + if (!logs) { + if (log_length < 10) { + fprintf(stderr, "No memory to allocate.\n"); + return EXIT_SYSFAIL; + } + log_length /= 2; + goto again; + } + + fd = connect_to(sdhost, sdport); + if (fd < 0) + goto error; + + memset(&hdr, 0, sizeof(hdr)); + + hdr.opcode = SD_OP_STAT_CLUSTER; + hdr.epoch = node_list_version; + hdr.data_length = log_length; + + rlen = hdr.data_length; + wlen = 0; + ret = exec_req(fd, (struct sd_req *)&hdr, logs, &wlen, &rlen); + close(fd); + + if (ret != 0) + goto error; + + if (rsp->result != SD_RES_SUCCESS) + printf("%s\n", sd_strerror(rsp->result)); + + nr_logs = rsp->data_length / sizeof(struct epoch_log); + for (i = nr_logs - 1; i >= 0; i--) { + vnodes_nr = nodes_to_vnodes(logs[i].nodes, logs[i].nr_nodes, vnodes); + printf("\nobj %"PRIx64" locations at epoch %d, copies = %d\n", + oid, logs[i].epoch, logs[i].nr_copies); + printf("---------------------------------------------------\n"); + for (j = 0; j < logs[i].nr_copies; j++) { + idx = obj_to_sheep(vnodes, vnodes_nr, oid, j); + addr_to_str(host, sizeof(host), vnodes[idx].addr, + vnodes[idx].port); + printf("%s\n", host); + } + } + + free(logs); + return EXIT_SUCCESS; +error: + free(logs); + return EXIT_SYSFAIL; +} + +static int vdi_track(int argc, char **argv) +{ + char *vdiname = argv[optind]; + unsigned idx = vdi_cmd_data.index; + int ret; + struct get_vdi_info info; + uint32_t vid; + + memset(&info, 0, sizeof(info)); + info.name = vdiname; + info.tag = vdi_cmd_data.snapshot_tag; + info.vid = 0; + info.snapid = vdi_cmd_data.snapshot_id; + + ret = parse_vdi(get_oid, SD_INODE_HEADER_SIZE, &info); + + vid = info.vid; + if (vid == 0) { + fprintf(stderr, "VDI not found\n"); + return EXIT_MISSING; + } + + if (idx == ~0) { + printf("Tracking the inode object 0x%" PRIx32 " with %d nodes\n", + vid, nr_nodes); + print_obj_epoch(vid_to_vdi_oid(vid)); + } else { + struct get_data_oid_info oid_info; + + oid_info.success = 0; + oid_info.idx = idx; + + if (idx >= MAX_DATA_OBJS) { + printf("The offset is too large!\n"); + exit(EXIT_FAILURE); + } + + parse_objs(vid_to_vdi_oid(vid), get_data_oid, + &oid_info, SD_DATA_OBJ_SIZE); + + if (oid_info.success) { + if (oid_info.data_oid) { + printf("Tracking the object 0x%" PRIx64 + " (the inode vid 0x%" PRIx32 " idx %u)" + " with %d nodes\n", + oid_info.data_oid, vid, idx, nr_nodes); + print_obj_epoch(oid_info.data_oid); + + } else + printf("The inode object 0x%" PRIx32 " idx %u is not allocated\n", + vid, idx); + } else + fprintf(stderr, "Failed to read the inode object 0x%"PRIx32"\n", vid); + } + + return EXIT_SUCCESS; +} + static int find_vdi_attr_oid(char *vdiname, char *tag, uint32_t snapid, char *key, void *value, unsigned int value_len, uint32_t *vid, uint64_t *oid, unsigned int *nr_copies, @@ -1205,6 +1331,8 @@ static struct subcommand vdi_cmd[] = { 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}, + {"track", "<vdiname>", "isaph", "show the object epoch trace in the image", + 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}, {"getattr", "<vdiname> <key>", "aph", "get a VDI attribute", diff --git a/include/sheep.h b/include/sheep.h index d010fdf..fc2ac58 100644 --- a/include/sheep.h +++ b/include/sheep.h @@ -164,6 +164,7 @@ struct epoch_log { uint64_t time; uint32_t epoch; uint32_t nr_nodes; + uint32_t nr_copies; struct sd_node nodes[SD_MAX_NODES]; }; diff --git a/sheep/ops.c b/sheep/ops.c index ee6dee1..99bde61 100644 --- a/sheep/ops.c +++ b/sheep/ops.c @@ -312,6 +312,7 @@ static int local_stat_cluster(const struct sd_req *req, struct sd_rsp *rsp, log->nr_nodes = epoch_log_read_remote(epoch, (char *)log->nodes, sizeof(log->nodes)); + log->nr_copies = get_max_copies(log->nodes, log->nr_nodes); rsp->data_length += sizeof(*log); log->nr_nodes /= sizeof(log->nodes[0]); diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h index a9e8440..77b1586 100644 --- a/sheep/sheep_priv.h +++ b/sheep/sheep_priv.h @@ -273,6 +273,7 @@ int store_remove_obj(const struct sd_req *, struct sd_rsp *, void *); int store_file_write(void *buffer, size_t len); void *store_file_read(void); +int get_max_copies(struct sd_node *entries, int nr); #define NR_GW_WORKER_THREAD 4 #define NR_IO_WORKER_THREAD 4 diff --git a/sheep/store.c b/sheep/store.c index 739862c..216be97 100644 --- a/sheep/store.c +++ b/sheep/store.c @@ -1118,7 +1118,7 @@ uint64_t get_cluster_ctime(void) return ct; } -static int get_max_copies(struct sd_node *entries, int nr) +int get_max_copies(struct sd_node *entries, int nr) { int i, j; unsigned int nr_zones = 0; -- 1.7.1 |