static int cluster_info(int argc, char **argv) { int i, ret; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; struct epoch_log *logs; int nr_logs, log_length; time_t ti, ct; struct tm tm; char time_str[128]; log_length = sd_epoch * sizeof(struct epoch_log); logs = xmalloc(log_length); sd_init_req(&hdr, SD_OP_STAT_CLUSTER); hdr.data_length = log_length; ret = dog_exec_req(&sd_nid, &hdr, logs); if (ret < 0) goto error; /* show cluster status */ if (!raw_output) printf("Cluster status: "); if (rsp->result == SD_RES_SUCCESS) printf("running, auto-recovery %s\n", logs->disable_recovery ? "disabled" : "enabled"); else printf("%s\n", sd_strerror(rsp->result)); /* show cluster backend store */ if (cluster_cmd_data.show_store) { if (!raw_output) printf("Cluster store: "); if (rsp->result == SD_RES_SUCCESS) { char copy[10]; int data, parity; if (!logs->copy_policy) snprintf(copy, sizeof(copy), "%d", logs->nr_copies); else { ec_policy_to_dp(logs->copy_policy, &data, &parity); snprintf(copy, sizeof(copy), "%d:%d", data, parity); } printf("%s with %s redundancy policy\n", logs->drv_name, copy); } else printf("%s\n", sd_strerror(rsp->result)); } if (!raw_output && rsp->data_length > 0) { ct = logs[0].ctime >> 32; printf("\nCluster created at %s\n", ctime(&ct)); printf("Epoch Time Version\n"); }
static int onode_populate_extents(struct kv_onode *onode, struct http_request *req) { ssize_t size; uint64_t start = 0, count, done = 0, total, offset; int ret; char *data_buf = NULL; uint32_t data_vid = onode->data_vid; uint64_t write_buffer_size = MIN(MAX_RW_BUFFER, req->data_length); count = DIV_ROUND_UP(req->data_length, SD_DATA_OBJ_SIZE); sys->cdrv->lock(data_vid); ret = oalloc_new_prepare(data_vid, &start, count); sys->cdrv->unlock(data_vid); if (ret != SD_RES_SUCCESS) { sd_err("oalloc_new_prepare failed for %s, %s", onode->name, sd_strerror(ret)); goto out; } data_buf = xmalloc(write_buffer_size); offset = start * SD_DATA_OBJ_SIZE; total = req->data_length; while (done < total) { size = http_request_read(req, data_buf, write_buffer_size); ret = vdi_read_write(data_vid, data_buf, size, offset, false); if (ret != SD_RES_SUCCESS) { sd_err("Failed to write data object for %s, %s", onode->name, sd_strerror(ret)); goto out; } done += size; offset += size; } sys->cdrv->lock(data_vid); ret = oalloc_new_finish(data_vid, start, count); sys->cdrv->unlock(data_vid); if (ret != SD_RES_SUCCESS) { sd_err("oalloc_new_finish failed for %s, %s", onode->name, sd_strerror(ret)); goto out; } onode->o_extent[0].start = start; onode->o_extent[0].count = count; onode->nr_extent = 1; out: free(data_buf); return ret; }
static int node_md_info(struct node_id *nid) { struct sd_md_info info = {}; char size_str[UINT64_DECIMAL_SIZE], used_str[UINT64_DECIMAL_SIZE], avail_str[UINT64_DECIMAL_SIZE]; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; int ret, i; sd_init_req(&hdr, SD_OP_MD_INFO); hdr.data_length = sizeof(info); ret = dog_exec_req(nid->addr, nid->port, &hdr, &info); if (ret < 0) return EXIT_SYSFAIL; if (rsp->result != SD_RES_SUCCESS) { sd_err("failed to get multi-disk infomation: %s", sd_strerror(rsp->result)); return EXIT_FAILURE; } for (i = 0; i < info.nr; i++) { uint64_t size = info.disk[i].free + info.disk[i].used; int ratio = (int)(((double)info.disk[i].used / size) * 100); size_to_str(size, size_str, sizeof(size_str)); size_to_str(info.disk[i].used, used_str, sizeof(used_str)); size_to_str(info.disk[i].free, avail_str, sizeof(avail_str)); fprintf(stdout, "%2d\t%s\t%s\t%s\t%3d%%\t%s\n", info.disk[i].idx, size_str, used_str, avail_str, ratio, info.disk[i].path); } return EXIT_SUCCESS; }
int sd_read_object(uint64_t oid, void *data, unsigned int datalen, uint64_t offset, bool direct) { struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; int ret; sd_init_req(&hdr, SD_OP_READ_OBJ); hdr.data_length = datalen; hdr.obj.oid = oid; hdr.obj.offset = offset; if (direct) hdr.flags |= SD_FLAG_CMD_DIRECT; ret = collie_exec_req(sdhost, sdport, &hdr, data); if (ret < 0) { fprintf(stderr, "Failed to read object %" PRIx64 "\n", oid); return SD_RES_EIO; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Failed to read object %" PRIx64 " %s\n", oid, sd_strerror(rsp->result)); return rsp->result; } untrim_zero_sectors(data, rsp->obj.offset, rsp->data_length, datalen); return SD_RES_SUCCESS; }
static int trace_disable(int argc, char **argv) { const char *tracer = argv[optind]; int ret; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; sd_init_req(&hdr, SD_OP_TRACE_DISABLE); hdr.flags = SD_FLAG_CMD_WRITE; hdr.data_length = strlen(tracer) + 1; ret = dog_exec_req(&sd_nid, &hdr, (void *)tracer); if (ret < 0) return EXIT_SYSFAIL; switch (rsp->result) { case SD_RES_SUCCESS: break; case SD_RES_NO_SUPPORT: sd_err("no such tracer %s", tracer); return EXIT_FAILURE; case SD_RES_INVALID_PARMS: sd_err("tracer %s is not enabled", tracer); return EXIT_FAILURE; default: sd_err("unknown error (%s)", sd_strerror(rsp->result)); return EXIT_SYSFAIL; } return trace_read_buffer(); }
static int list_store(void) { int fd, ret; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; char buf[512] = { 0 }; fd = connect_to(sdhost, sdport); if (fd < 0) return EXIT_SYSFAIL; sd_init_req(&hdr, SD_OP_GET_STORE_LIST); hdr.data_length = 512; ret = exec_req(fd, &hdr, buf); close(fd); if (ret) { fprintf(stderr, "Failed to connect\n"); return EXIT_SYSFAIL; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Restore failed: %s\n", sd_strerror(rsp->result)); return EXIT_FAILURE; } printf("Available stores:\n"); printf("---------------------------------------\n"); printf("%s\n", buf); return EXIT_SYSFAIL; }
int sheep_exec_req(const struct node_id *nid, struct sd_req *hdr, void *buf) { struct sd_rsp *rsp = (struct sd_rsp *)hdr; struct sockfd *sfd; int ret; assert(is_worker_thread()); sfd = sockfd_cache_get(nid); if (!sfd) return SD_RES_NETWORK_ERROR; ret = exec_req(sfd->fd, hdr, buf, sheep_need_retry, hdr->epoch, MAX_RETRY_COUNT); if (ret) { sd_dprintf("remote node might have gone away"); sockfd_cache_del(nid, sfd); return SD_RES_NETWORK_ERROR; } ret = rsp->result; if (ret != SD_RES_SUCCESS) sd_eprintf("failed %s", sd_strerror(ret)); sockfd_cache_put(nid, sfd); return ret; }
static int bnode_create(struct kv_bnode *bnode, uint32_t account_vid) { struct sd_inode *inode = xmalloc(sizeof(struct sd_inode)); uint32_t tmp_vid, idx; uint64_t hval, i; int ret; ret = sd_read_object(vid_to_vdi_oid(account_vid), (char *)inode, sizeof(*inode), 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read %" PRIx32 " %s", account_vid, sd_strerror(ret)); goto out; } hval = sd_hash(bnode->name, strlen(bnode->name)); for (i = 0; i < MAX_DATA_OBJS; i++) { idx = (hval + i) % MAX_DATA_OBJS; tmp_vid = INODE_GET_VID(inode, idx); if (tmp_vid) continue; else break; } if (i == MAX_DATA_OBJS) { ret = SD_RES_NO_SPACE; goto out; } ret = bnode_do_create(bnode, inode, idx); out: free(inode); return ret; }
int sd_read_object(uint64_t oid, void *data, unsigned int datalen, uint64_t offset, bool direct) { struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; int ret; sd_init_req(&hdr, SD_OP_READ_OBJ); hdr.data_length = datalen; hdr.obj.oid = oid; hdr.obj.offset = offset; if (direct) hdr.flags |= SD_FLAG_CMD_DIRECT; ret = dog_exec_req(&sd_nid, &hdr, data); if (ret < 0) { sd_err("Failed to read object %" PRIx64, oid); return SD_RES_EIO; } if (rsp->result != SD_RES_SUCCESS) { sd_err("Failed to read object %" PRIx64 " %s", oid, sd_strerror(rsp->result)); return rsp->result; } return SD_RES_SUCCESS; }
int update_node_list(int max_nodes, uint32_t epoch) { int fd, ret; unsigned int size; char *buf = NULL; struct sd_node *ent; struct sd_node_req hdr; struct sd_node_rsp *rsp = (struct sd_node_rsp *)&hdr; fd = connect_to(sdhost, sdport); if (fd < 0) return -1; size = sizeof(*ent) * max_nodes; buf = xzalloc(size); sd_init_req((struct sd_req *)&hdr, SD_OP_GET_NODE_LIST); hdr.request_ver = epoch; hdr.data_length = size; ret = collie_exec_req(fd, (struct sd_req *)&hdr, buf); if (ret) { ret = -1; goto out; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Failed to update node list: %s\n", sd_strerror(rsp->result)); ret = -1; goto out; } size = rsp->data_length; sd_nodes_nr = size / sizeof(*ent); if (sd_nodes_nr == 0) { fprintf(stderr, "There are no active sheep daemons\n"); exit(EXIT_FAILURE); } /* FIXME */ if (sd_nodes_nr > max_nodes) { ret = -1; goto out; } memcpy(sd_nodes, buf, size); sd_vnodes_nr = nodes_to_vnodes(sd_nodes, sd_nodes_nr, sd_vnodes); sd_epoch = hdr.epoch; master_idx = rsp->master_idx; out: if (buf) free(buf); if (fd >= 0) close(fd); return ret; }
int parse_vdi(vdi_parser_func_t func, size_t size, void *data) { int ret; unsigned long nr; static struct sd_inode i; struct sd_req req; struct sd_rsp *rsp = (struct sd_rsp *)&req; static DECLARE_BITMAP(vdi_inuse, SD_NR_VDIS); unsigned int rlen = sizeof(vdi_inuse); sd_init_req(&req, SD_OP_READ_VDIS); req.data_length = sizeof(vdi_inuse); ret = dog_exec_req(sdhost, sdport, &req, &vdi_inuse); if (ret < 0) goto out; if (rsp->result != SD_RES_SUCCESS) { sd_err("%s", sd_strerror(rsp->result)); goto out; } FOR_EACH_VDI(nr, vdi_inuse) { uint64_t oid; uint32_t snapid; oid = vid_to_vdi_oid(nr); memset(&i, 0, sizeof(i)); ret = sd_read_object(oid, &i, SD_INODE_HEADER_SIZE, 0, true); if (ret != SD_RES_SUCCESS) { sd_err("Failed to read inode header"); continue; } if (i.name[0] == '\0') /* this VDI has been deleted */ continue; if (size > SD_INODE_HEADER_SIZE) { rlen = DIV_ROUND_UP(i.vdi_size, SD_DATA_OBJ_SIZE) * sizeof(i.data_vdi_id[0]); if (rlen > size - SD_INODE_HEADER_SIZE) rlen = size - SD_INODE_HEADER_SIZE; ret = sd_read_object(oid, ((char *)&i) + SD_INODE_HEADER_SIZE, rlen, SD_INODE_HEADER_SIZE, true); if (ret != SD_RES_SUCCESS) { sd_err("Failed to read inode"); continue; } } snapid = vdi_is_snapshot(&i) ? i.snap_id : 0; func(i.vdi_id, i.name, i.tag, snapid, 0, &i, data); }
int parse_vdi(vdi_parser_func_t func, size_t size, void *data) { int ret; unsigned long nr; struct sd_inode *i = xmalloc(sizeof(*i)); struct sd_req req; struct sd_rsp *rsp = (struct sd_rsp *)&req; static DECLARE_BITMAP(vdi_inuse, SD_NR_VDIS); uint32_t rlen; sd_init_req(&req, SD_OP_READ_VDIS); req.data_length = sizeof(vdi_inuse); ret = dog_exec_req(&sd_nid, &req, vdi_inuse); if (ret < 0) goto out; if (rsp->result != SD_RES_SUCCESS) { sd_err("%s", sd_strerror(rsp->result)); goto out; } FOR_EACH_VDI(nr, vdi_inuse) { uint64_t oid; uint32_t snapid; oid = vid_to_vdi_oid(nr); /* for B-tree inode, we also need sd_index_header */ ret = dog_read_object(oid, i, SD_INODE_HEADER_SIZE + sizeof(struct sd_index_header), 0, true); if (ret != SD_RES_SUCCESS) { sd_err("Failed to read inode header"); continue; } if (i->name[0] == '\0') /* this VDI has been deleted */ continue; if (size > SD_INODE_HEADER_SIZE) { rlen = sd_inode_get_meta_size(i, size); ret = dog_read_object(oid, ((char *)i) + SD_INODE_HEADER_SIZE, rlen, SD_INODE_HEADER_SIZE, true); if (ret != SD_RES_SUCCESS) { sd_err("Failed to read inode"); continue; } } snapid = vdi_is_snapshot(i) ? i->snap_id : 0; func(i->vdi_id, i->name, i->tag, snapid, 0, i, data); }
static int trace_read_buffer(void) { int fd, ret, tfd; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; unsigned rlen, wlen; #define TRACE_BUF_LEN (1024 * 1024 * 20) char *buf = xzalloc(TRACE_BUF_LEN); tfd = open(tracefile, O_CREAT | O_RDWR | O_APPEND | O_TRUNC, 0644); if (tfd < 0) { fprintf(stderr, "can't create tracefile\n"); return EXIT_SYSFAIL; } fd = connect_to(sdhost, sdport); if (fd < 0) return EXIT_SYSFAIL; read_buffer: sd_init_req(&hdr, SD_OP_TRACE_READ_BUF); hdr.data_length = rlen = TRACE_BUF_LEN; hdr.epoch = sd_epoch; wlen = 0; ret = exec_req(fd, &hdr, buf, &wlen, &rlen); if (ret) { fprintf(stderr, "Failed to connect\n"); close(fd); return EXIT_SYSFAIL; } if (rsp->result == SD_RES_AGAIN) goto read_buffer; if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Trace failed: %s\n", sd_strerror(rsp->result)); close(fd); return EXIT_FAILURE; } xwrite(tfd, buf, rlen); if (rlen == TRACE_BUF_LEN) { memset(buf, 0, TRACE_BUF_LEN); goto read_buffer; } close(fd); free(buf); return EXIT_SUCCESS; }
static int node_recovery(int argc, char **argv) { int i, ret; if (node_cmd_data.recovery_progress) return node_recovery_progress(); if (!raw_output) { printf("Nodes In Recovery:\n"); printf(" Id Host:Port V-Nodes Zone" " Progress\n"); } for (i = 0; i < sd_nodes_nr; i++) { struct sd_req req; struct sd_rsp *rsp = (struct sd_rsp *)&req; struct recovery_state state; memset(&state, 0, sizeof(state)); sd_init_req(&req, SD_OP_STAT_RECOVERY); req.data_length = sizeof(state); ret = dog_exec_req(sd_nodes[i].nid.addr, sd_nodes[i].nid.port, &req, &state); if (ret < 0) return EXIT_SYSFAIL; if (rsp->result != SD_RES_SUCCESS) { sd_err("%s", sd_strerror(rsp->result)); return EXIT_FAILURE; } if (state.in_recovery) { const char *host = addr_to_str(sd_nodes[i].nid.addr, sd_nodes[i].nid.port); if (raw_output) printf("%d %s %d %d %"PRIu64" %"PRIu64"\n", i, host, sd_nodes[i].nr_vnodes, sd_nodes[i].zone, state.nr_finished, state.nr_total); else printf("%4d %-20s%5d%11d%11.1f%%\n", i, host, sd_nodes[i].nr_vnodes, sd_nodes[i].zone, 100 * (float)state.nr_finished / state.nr_total); } } return EXIT_SUCCESS; }
static int do_vdi_create(char *vdiname, int64_t vdi_size, uint32_t base_vid, uint32_t *vdi_id, int snapshot) { struct sd_vdi_req hdr; struct sd_vdi_rsp *rsp = (struct sd_vdi_rsp *)&hdr; int fd, ret; unsigned int wlen, rlen = 0; char buf[SD_MAX_VDI_LEN]; fd = connect_to(sdhost, sdport); if (fd < 0) { fprintf(stderr, "failed to connect\n"); return EXIT_SYSFAIL; } memset(buf, 0, sizeof(buf)); strncpy(buf, vdiname, SD_MAX_VDI_LEN); memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_NEW_VDI; hdr.base_vdi_id = base_vid; wlen = SD_MAX_VDI_LEN; hdr.flags = SD_FLAG_CMD_WRITE; hdr.snapid = snapshot; hdr.data_length = wlen; hdr.vdi_size = vdi_size; ret = exec_req(fd, (struct sd_req *)&hdr, buf, &wlen, &rlen); close(fd); if (ret) { fprintf(stderr, "failed to send a request\n"); return EXIT_SYSFAIL; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "%s, %s\n", sd_strerror(rsp->result), vdiname); return EXIT_FAILURE; } if (vdi_id) *vdi_id = rsp->vdi_id; return EXIT_SUCCESS; }
static int do_vdi_create(char *vdiname, int64_t vdi_size, uint32_t base_vid, uint32_t *vdi_id, int snapshot, int nr_copies) { struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; int fd, ret; unsigned int wlen, rlen = 0; char buf[SD_MAX_VDI_LEN]; fd = connect_to(sdhost, sdport); if (fd < 0) { fprintf(stderr, "Failed to connect\n"); return EXIT_SYSFAIL; } memset(buf, 0, sizeof(buf)); strncpy(buf, vdiname, SD_MAX_VDI_LEN); wlen = SD_MAX_VDI_LEN; sd_init_req(&hdr, SD_OP_NEW_VDI); hdr.flags = SD_FLAG_CMD_WRITE; hdr.data_length = wlen; hdr.vdi.base_vdi_id = base_vid; hdr.vdi.snapid = snapshot; hdr.vdi.vdi_size = roundup(vdi_size, 512); hdr.vdi.copies = nr_copies; ret = exec_req(fd, &hdr, buf, &wlen, &rlen); close(fd); if (ret) { fprintf(stderr, "Failed to send a request\n"); return EXIT_SYSFAIL; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Failed to create VDI %s: %s\n", vdiname, sd_strerror(rsp->result)); return EXIT_FAILURE; } if (vdi_id) *vdi_id = rsp->vdi.vdi_id; return EXIT_SUCCESS; }
/* Light request only contains header, without body content. */ int send_light_req(struct sd_req *hdr, const uint8_t *addr, int port) { int ret = dog_exec_req(addr, port, hdr, NULL); struct sd_rsp *rsp = (struct sd_rsp *)hdr; if (ret == -1) return -1; if (rsp->result != SD_RES_SUCCESS) { sd_err("Response's result: %s", sd_strerror(rsp->result)); return -1; } return 0; }
int sd_discard_object(uint64_t oid) { int ret; struct sd_req hdr; sd_init_req(&hdr, SD_OP_DISCARD_OBJ); hdr.obj.oid = oid; ret = exec_local_req(&hdr, NULL); if (ret != SD_RES_SUCCESS) sd_err("Failed to discard data obj %"PRIu64" %s", oid, sd_strerror(ret)); return ret; }
/* Light request only contains header, without body content. */ int send_light_req(const struct node_id *nid, struct sd_req *hdr) { int ret = dog_exec_req(nid, hdr, NULL); struct sd_rsp *rsp = (struct sd_rsp *)hdr; if (ret == -1) return -1; if (rsp->result != SD_RES_SUCCESS) { sd_err("Response's result: %s", sd_strerror(rsp->result)); return -1; } return 0; }
/* Light request only contains header, without body content. */ int send_light_req(struct sd_req *hdr, const char *host, int port) { int ret = send_light_req_get_response(hdr, host, port); if (ret == -1) return -1; if (ret != SD_RES_SUCCESS) { fprintf(stderr, "Response's result: %s\n", sd_strerror(ret)); return -1; } return 0; }
int update_node_list(int max_nodes) { int ret; unsigned int size; char *buf = NULL; struct sd_node *ent; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; size = sizeof(*ent) * max_nodes; buf = xzalloc(size); sd_init_req(&hdr, SD_OP_GET_NODE_LIST); hdr.data_length = size; ret = dog_exec_req(sdhost, sdport, &hdr, buf); if (ret < 0) goto out; if (rsp->result != SD_RES_SUCCESS) { sd_err("Failed to update node list: %s", sd_strerror(rsp->result)); ret = -1; goto out; } size = rsp->data_length; sd_nodes_nr = size / sizeof(*ent); if (sd_nodes_nr == 0) { sd_err("There are no active sheep daemons"); exit(EXIT_FAILURE); } /* FIXME */ if (sd_nodes_nr > max_nodes) { ret = -1; goto out; } memcpy(sd_nodes, buf, size); sd_vnodes_nr = nodes_to_vnodes(sd_nodes, sd_nodes_nr, sd_vnodes); sd_epoch = hdr.epoch; out: if (buf) free(buf); return ret; }
static int cluster_format(int argc, char **argv) { int fd, ret; struct sd_so_req hdr; struct sd_so_rsp *rsp = (struct sd_so_rsp *)&hdr; unsigned rlen, wlen; struct timeval tv; char store_name[STORE_LEN]; fd = connect_to(sdhost, sdport); if (fd < 0) return EXIT_SYSFAIL; gettimeofday(&tv, NULL); memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_MAKE_FS; hdr.copies = cluster_cmd_data.copies; if (cluster_cmd_data.nohalt) set_nohalt(&hdr.flags); hdr.epoch = node_list_version; hdr.ctime = (uint64_t) tv.tv_sec << 32 | tv.tv_usec * 1000; if (strlen(cluster_cmd_data.name)) strncpy(store_name, cluster_cmd_data.name, STORE_LEN); else strcpy(store_name, DEFAULT_STORE); hdr.data_length = wlen = strlen(store_name) + 1; hdr.flags |= SD_FLAG_CMD_WRITE; printf("using backend %s store\n", store_name); ret = exec_req(fd, (struct sd_req *)&hdr, store_name, &wlen, &rlen); close(fd); if (ret) { fprintf(stderr, "Failed to connect\n"); return EXIT_SYSFAIL; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Format failed: %s\n", sd_strerror(rsp->result)); return list_store(); } return EXIT_SUCCESS; }
static int cluster_info(int argc, char **argv) { int i, fd, ret; struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; struct epoch_log *logs; int nr_logs, log_length; time_t ti, ct; struct tm tm; char time_str[128]; log_length = sd_epoch * 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; sd_init_req(&hdr, SD_OP_STAT_CLUSTER); hdr.data_length = log_length; ret = exec_req(fd, &hdr, logs); close(fd); if (ret != 0) goto error; if (!raw_output) printf("Cluster status: "); if (rsp->result == SD_RES_SUCCESS) printf("running\n"); else printf("%s\n", sd_strerror(rsp->result)); if (!raw_output && rsp->data_length > 0) { ct = logs[0].ctime >> 32; printf("\nCluster created at %s\n", ctime(&ct)); printf("Epoch Time Version\n"); }
int remove_object(uint64_t oid) { struct sd_req hdr; int ret; sd_init_req(&hdr, SD_OP_REMOVE_OBJ); hdr.obj.oid = oid; hdr.obj.copies = get_vdi_copy_number(oid_to_vid(oid)); ret = exec_local_req(&hdr, NULL); if (ret != SD_RES_SUCCESS) sd_eprintf("failed to remove object %" PRIx64 ", %s", oid, sd_strerror(ret)); return ret; }
static int find_vdi_name(char *vdiname, uint32_t snapid, const char *tag, uint32_t *vid, int for_snapshot) { int ret, fd; struct sd_vdi_req hdr; struct sd_vdi_rsp *rsp = (struct sd_vdi_rsp *)&hdr; unsigned int wlen, rlen = 0; char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN]; fd = connect_to(sdhost, sdport); if (fd < 0) return -1; memset(buf, 0, sizeof(buf)); strncpy(buf, vdiname, SD_MAX_VDI_LEN); strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN); memset(&hdr, 0, sizeof(hdr)); if (for_snapshot) hdr.opcode = SD_OP_GET_VDI_INFO; else hdr.opcode = SD_OP_LOCK_VDI; wlen = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN; hdr.proto_ver = SD_PROTO_VER; hdr.data_length = wlen; hdr.snapid = snapid; hdr.flags = SD_FLAG_CMD_WRITE; ret = exec_req(fd, (struct sd_req *)&hdr, buf, &wlen, &rlen); if (ret) { ret = -1; goto out; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "cannot get vdi info, %s, %s %d %s\n", sd_strerror(rsp->result), vdiname, snapid, tag); ret = -1; goto out; } *vid = rsp->vdi_id; ret = 0; out: close(fd); return ret; }
static int onode_create(struct kv_onode *onode, uint32_t bucket_vid) { struct sd_inode *inode = xmalloc(sizeof(struct sd_inode)); uint32_t tmp_vid, idx; uint64_t hval, i; int ret; bool create = true; sys->cdrv->lock(bucket_vid); ret = sd_read_object(vid_to_vdi_oid(bucket_vid), (char *)inode, sizeof(*inode), 0); if (ret != SD_RES_SUCCESS) { sd_err("failed to read %" PRIx32 " %s", bucket_vid, sd_strerror(ret)); goto out; } hval = sd_hash(onode->name, strlen(onode->name)); for (i = 0; i < MAX_DATA_OBJS; i++) { idx = (hval + i) % MAX_DATA_OBJS; tmp_vid = INODE_GET_VID(inode, idx); if (tmp_vid) { uint64_t oid = vid_to_data_oid(bucket_vid, idx); char name[SD_MAX_OBJECT_NAME] = { }; ret = sd_read_object(oid, name, sizeof(name), 0); if (ret != SD_RES_SUCCESS) goto out; if (name[0] == 0) { create = false; goto create; } } else break; } if (i == MAX_DATA_OBJS) { ret = SD_RES_NO_SPACE; goto out; } create: ret = onode_do_create(onode, inode, idx, create); out: free(inode); sys->cdrv->unlock(bucket_vid); return ret; }
int read_backend_object(uint64_t oid, char *data, unsigned int datalen, uint64_t offset) { struct sd_req hdr; int ret; sd_init_req(&hdr, SD_OP_READ_OBJ); hdr.data_length = datalen; hdr.obj.oid = oid; hdr.obj.offset = offset; ret = exec_local_req(&hdr, data); if (ret != SD_RES_SUCCESS) sd_err("failed to read object %" PRIx64 ", %s", oid, sd_strerror(ret)); return ret; }
int sd_write_object(uint64_t oid, uint64_t cow_oid, void *data, unsigned int datalen, uint64_t offset, uint32_t flags, int copies, bool create, bool direct) { struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; int fd, ret; fd = connect_to(sdhost, sdport); if (fd < 0) { fprintf(stderr, "Failed to connect\n"); return SD_RES_EIO; } if (create) sd_init_req(&hdr, SD_OP_CREATE_AND_WRITE_OBJ); else sd_init_req(&hdr, SD_OP_WRITE_OBJ); hdr.data_length = datalen; hdr.flags = flags | SD_FLAG_CMD_WRITE; if (cow_oid) hdr.flags |= SD_FLAG_CMD_COW; if (direct) hdr.flags |= SD_FLAG_CMD_DIRECT; hdr.obj.copies = copies; hdr.obj.oid = oid; hdr.obj.cow_oid = cow_oid; hdr.obj.offset = offset; ret = collie_exec_req(fd, &hdr, data); close(fd); if (ret) { fprintf(stderr, "Failed to write object %" PRIx64 "\n", oid); return SD_RES_EIO; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "Failed to write object %" PRIx64 ": %s\n", oid, sd_strerror(rsp->result)); return rsp->result; } return SD_RES_SUCCESS; }
int sd_read_object(uint64_t oid, void *data, unsigned int datalen, uint64_t offset) { struct sd_obj_req hdr; struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr; char name[128]; int n, fd, ret; unsigned wlen = 0, rlen = datalen; n = obj_to_sheep(vnode_list_entries, nr_vnodes, oid, 0); addr_to_str(name, sizeof(name), vnode_list_entries[n].addr, 0); fd = connect_to(name, vnode_list_entries[n].port); if (fd < 0) { fprintf(stderr, "failed to connect %s:%d\n", name, vnode_list_entries[n].port); return SD_RES_EIO; } memset(&hdr, 0, sizeof(hdr)); hdr.epoch = node_list_version; hdr.opcode = SD_OP_READ_OBJ; hdr.oid = oid; /* use direct to avoid checking consistency */ hdr.flags = SD_FLAG_CMD_DIRECT; hdr.data_length = rlen; hdr.offset = offset; ret = exec_req(fd, (struct sd_req *)&hdr, data, &wlen, &rlen); close(fd); if (ret) { fprintf(stderr, "failed to read object, %lx\n", oid); return SD_RES_EIO; } if (rsp->result != SD_RES_SUCCESS) { fprintf(stderr, "failed to read object, %lx %s\n", oid, sd_strerror(rsp->result)); return rsp->result; } return SD_RES_SUCCESS; }
/* * Read data firstly from local object cache(if enabled), if fail, * try read backends */ int read_object(uint64_t oid, char *data, unsigned int datalen, uint64_t offset) { int ret; if (sys->enable_object_cache && object_is_cached(oid)) { ret = object_cache_read(oid, data, datalen, offset); if (ret != SD_RES_SUCCESS) { sd_eprintf("try forward read %"PRIx64" %s", oid, sd_strerror(ret)); goto forward_read; } return ret; } forward_read: return read_backend_object(oid, data, datalen, offset); }