<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-02-27 13:48 GMT+08:00 Liu Yuan <span dir="ltr"><<a href="mailto:namei.unix@gmail.com" target="_blank">namei.unix@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Add a SD_OP_EXIST to check if an object exists in the specific node.<br>
<br>
Signed-off-by: Liu Yuan <<a href="mailto:namei.unix@gmail.com">namei.unix@gmail.com</a>><br>
---<br>
dog/vdi.c | 275 +++++++++++++----------------------------------<br>
include/internal_proto.h | 1 +<br>
sheep/ops.c | 20 ++++<br>
sheep/recovery.c | 17 +--<br>
sheep/sheep_priv.h | 1 +<br>
5 files changed, 106 insertions(+), 208 deletions(-)<br>
<br>
diff --git a/dog/vdi.c b/dog/vdi.c<br>
index debed0a..8a8f089 100644<br>
--- a/dog/vdi.c<br>
+++ b/dog/vdi.c<br>
@@ -210,122 +210,23 @@ static void print_vdi_graph(uint32_t vid, const char *name, const char *tag,<br>
<br>
}<br>
<br>
-static void vdi_info_filler(uint32_t vid, const char *name, const char *tag,<br>
- uint32_t snapid, uint32_t flags,<br>
- const struct sd_inode *i, void *data)<br>
-{<br>
- struct get_vdi_info *info = data;<br>
-<br>
- if (info->name) {<br>
- if (info->tag && info->tag[0]) {<br>
- if (!strcmp(name, info->name) &&<br>
- !strcmp(tag, info->tag)) {<br>
- info->vid = vid;<br>
- info->nr_copies = i->nr_copies;<br>
- info->copy_policy = i->copy_policy;<br>
- }<br>
- } else if (info->snapid) {<br>
- if (!strcmp(name, info->name) &&<br>
- snapid == info->snapid) {<br>
- info->vid = vid;<br>
- info->nr_copies = i->nr_copies;<br>
- info->copy_policy = i->copy_policy;<br>
- }<br>
- } else {<br>
- if (!strcmp(name, info->name)) {<br>
- info->vid = vid;<br>
- info->nr_copies = i->nr_copies;<br>
- info->copy_policy = i->copy_policy;<br>
- }<br>
- }<br>
- }<br>
-}<br>
-<br>
-typedef int (*obj_parser_func_t)(const char *sheep, uint64_t oid,<br>
- struct sd_rsp *rsp, char *buf, void *data);<br>
-<br>
-static int do_print_obj(const char *sheep, uint64_t oid, struct sd_rsp *rsp,<br>
- char *buf, void *data)<br>
-{<br>
- switch (rsp->result) {<br>
- case SD_RES_SUCCESS:<br>
- printf("%s has the object\n", sheep);<br>
- break;<br>
- case SD_RES_NO_OBJ:<br>
- printf("%s doesn't have the object\n", sheep);<br>
- break;<br>
- case SD_RES_OLD_NODE_VER:<br>
- case SD_RES_NEW_NODE_VER:<br>
- sd_err("The node list has changed: please try again");<br>
- break;<br>
- default:<br>
- sd_err("%s: hit an unexpected error (%s)", sheep,<br>
- sd_strerror(rsp->result));<br>
- break;<br>
- }<br>
-<br>
- return 0;<br>
-}<br>
-<br>
-struct obj_info_filler_info {<br>
- bool success;<br>
- uint64_t data_oid;<br>
- unsigned idx;<br>
-};<br>
-<br>
-static int obj_info_filler(const char *sheep, uint64_t oid, struct sd_rsp *rsp,<br>
- char *buf, void *data)<br>
+static void for_each_node_print(uint64_t oid)<br>
{<br>
- struct obj_info_filler_info *info = data;<br>
- struct sd_inode *inode = (struct sd_inode *)buf;<br>
- uint32_t vdi_id;<br>
-<br>
- switch (rsp->result) {<br>
- case SD_RES_SUCCESS:<br>
- if (info->success)<br>
- break;<br>
- info->success = true;<br>
- vdi_id = sd_inode_get_vid(inode, info->idx);<br>
- if (vdi_id) {<br>
- info->data_oid = vid_to_data_oid(vdi_id, info->idx);<br>
- return 1;<br>
- }<br>
- break;<br>
- case SD_RES_NO_OBJ:<br>
- break;<br>
- case SD_RES_OLD_NODE_VER:<br>
- case SD_RES_NEW_NODE_VER:<br>
- sd_err("The node list has changed: please try again");<br>
- break;<br>
- default:<br>
- sd_err("%s: hit an unexpected error (%s)", sheep,<br>
- sd_strerror(rsp->result));<br>
- break;<br>
- }<br>
-<br>
- return 0;<br>
-}<br>
-<br>
-static void parse_objs(uint64_t oid, obj_parser_func_t func, void *data,<br>
- size_t size)<br>
-{<br>
- int ret, cb_ret;<br>
+ int ret;<br>
struct sd_node *n;<br>
- char *buf;<br>
+ const char *sheep;<br>
<br>
- buf = xzalloc(size);<br>
rb_for_each_entry(n, &sd_nroot, rb) {<br>
struct sd_req hdr;<br>
struct sd_rsp *rsp = (struct sd_rsp *)&hdr;<br>
<br>
- sd_init_req(&hdr, SD_OP_READ_PEER);<br>
- hdr.data_length = size;<br>
+ sd_init_req(&hdr, SD_OP_EXIST);<br>
+ hdr.data_length = 0;<br>
hdr.flags = 0;<br>
hdr.epoch = sd_epoch;<br>
hdr.obj.oid = oid;<br>
- hdr.obj.ec_index = SD_MAX_COPIES + 1; /* Ignore index */<br>
<br>
- ret = dog_exec_req(&n->nid, &hdr, buf);<br>
+ ret = dog_exec_req(&n->nid, &hdr, NULL);<br>
if (ret < 0)<br>
continue;<br>
switch (rsp->result) {<br>
@@ -333,16 +234,26 @@ static void parse_objs(uint64_t oid, obj_parser_func_t func, void *data,<br>
continue;<br>
}<br>
<br>
- cb_ret = func(addr_to_str(n->nid.addr, n->nid.port),<br>
- oid, rsp, buf, data);<br>
- if (cb_ret)<br>
+ sheep = addr_to_str(n->nid.addr, n->nid.port);<br>
+ switch (rsp->result) {<br>
+ case SD_RES_SUCCESS:<br>
+ printf("%s has the object\n", sheep);<br>
+ break;<br>
+ case SD_RES_NO_OBJ:<br>
+ printf("%s doesn't have the object\n", sheep);<br>
break;<br>
+ case SD_RES_OLD_NODE_VER:<br>
+ case SD_RES_NEW_NODE_VER:<br>
+ sd_err("The node list has changed: please try again");<br>
+ break;<br>
+ default:<br>
+ sd_err("%s: hit an unexpected error (%s)", sheep,<br>
+ sd_strerror(rsp->result));<br>
+ break;<br>
+ }<br>
}<br>
-<br>
- free(buf);<br>
}<br>
<br>
-<br>
static int vdi_list(int argc, char **argv)<br>
{<br>
const char *vdiname = argv[optind];<br>
@@ -901,67 +812,52 @@ static int vdi_object_map(int argc, char **argv)<br>
static int vdi_object_location(int argc, char **argv)<br>
{<br>
const char *vdiname = argv[optind];<br>
- uint64_t idx = vdi_cmd_data.index;<br>
- struct get_vdi_info info;<br>
- uint32_t vid;<br>
- size_t size;<br>
-<br>
- memset(&info, 0, sizeof(info));<br>
- <a href="http://info.name" target="_blank">info.name</a> = vdiname;<br>
- info.tag = vdi_cmd_data.snapshot_tag;<br>
- info.vid = 0;<br>
- info.snapid = vdi_cmd_data.snapshot_id;<br>
-<br>
- if (parse_vdi(vdi_info_filler, SD_INODE_HEADER_SIZE, &info) < 0)<br>
- return EXIT_SYSFAIL;<br>
+ uint64_t idx = vdi_cmd_data.index, oid;<br>
+ struct sd_inode *inode = xmalloc(sizeof(*inode));<br>
+ uint32_t vid, vdi_id;<br>
+ int ret;<br>
<br>
- vid = info.vid;<br>
- if (vid == 0) {<br>
- sd_err("VDI not found");<br>
- return EXIT_MISSING;<br>
+ ret = read_vdi_obj(vdiname, vdi_cmd_data.snapshot_id,<br>
+ vdi_cmd_data.snapshot_tag, NULL, inode,<br>
+ SD_INODE_SIZE);<br>
+ if (ret != EXIT_SUCCESS) {<br>
+ sd_err("FATAL: no inode objects");<br>
+ return ret;<br></blockquote><div><br></div><div>May be we should use 'goto out' which will free the memory of inode.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
}<br>
+ vid = inode->vdi_id;<br>
<br>
if (idx == ~0) {<br>
- printf("Looking for the inode object 0x%" PRIx32 " with %d nodes\n\n",<br>
+ printf("Looking for the inode object 0x%" PRIx32 " with %d"<br>
+ " nodes\n\n",<br>
vid, sd_nodes_nr);<br>
- parse_objs(vid_to_vdi_oid(vid), do_print_obj, NULL,<br>
- SD_INODE_SIZE);<br>
- } else {<br>
- struct obj_info_filler_info oid_info = {0};<br>
+ for_each_node_print(vid_to_vdi_oid(vid));<br>
+ ret = EXIT_SUCCESS;<br>
+ goto out;<br>
+ }<br>
<br>
- oid_info.success = false;<br>
- oid_info.idx = idx;<br>
+ if (idx >= MAX_DATA_OBJS) {<br>
+ printf("The offset is too large!\n");<br>
+ ret = EXIT_FAILURE;<br>
+ goto out;<br>
+ }<br>
<br>
- if (idx >= MAX_DATA_OBJS) {<br>
- printf("The offset is too large!\n");<br>
- exit(EXIT_FAILURE);<br>
- }<br>
+ vdi_id = sd_inode_get_vid(inode, idx);<br>
+ oid = vid_to_data_oid(vdi_id, idx);<br>
+ if (vdi_id) {<br>
+ printf("Looking for the object 0x%" PRIx64<br>
+ " (vid 0x%" PRIx32 " idx %"PRIu64<br>
+ ", %u copies) with %d nodes\n\n",<br>
+ oid, vid, idx, inode->nr_copies, sd_nodes_nr);<br>
<br>
- size = get_store_objsize(info.copy_policy,<br>
- vid_to_data_oid(vid, 0));<br>
- parse_objs(vid_to_vdi_oid(vid), obj_info_filler, &oid_info,<br>
- size);<br>
-<br>
- if (oid_info.success) {<br>
- if (oid_info.data_oid) {<br>
- printf("Looking for the object 0x%" PRIx64<br>
- " (vid 0x%" PRIx32 " idx %"PRIu64<br>
- ", %u copies) with %d nodes\n\n",<br>
- oid_info.data_oid, vid, idx,<br>
- info.nr_copies, sd_nodes_nr);<br>
-<br>
- parse_objs(oid_info.data_oid, do_print_obj,<br>
- NULL, size);<br>
- } else<br>
- printf("The inode object 0x%" PRIx32 " idx"<br>
- " %"PRIu64" is not allocated\n",<br>
- vid, idx);<br>
- } else<br>
- sd_err("Failed to read the inode object 0x%" PRIx32,<br>
- vid);<br>
- }<br>
+ for_each_node_print(oid);<br>
+ } else<br>
+ printf("The inode object 0x%" PRIx32 " idx"<br>
+ " %"PRIu64" is not allocated\n",<br>
+ vid, idx);<br>
<br>
- return EXIT_SUCCESS;<br>
+out:<br>
+ free(inode);<br>
+ return ret;<br>
}<br>
<br>
static int do_track_object(uint64_t oid, uint8_t nr_copies)<br>
@@ -1032,59 +928,37 @@ static int vdi_track(int argc, char **argv)<br>
{<br>
const char *vdiname = argv[optind];<br>
unsigned idx = vdi_cmd_data.index;<br>
- struct get_vdi_info info;<br>
- struct obj_info_filler_info oid_info = {0};<br>
- uint32_t vid;<br>
uint8_t nr_copies;<br>
uint64_t oid = vdi_cmd_data.oid;<br>
+ struct sd_inode *inode = xmalloc(sizeof(*inode));<br>
+ uint32_t vid, vdi_id;<br>
+ int ret;<br>
<br>
- memset(&info, 0, sizeof(info));<br>
- <a href="http://info.name" target="_blank">info.name</a> = vdiname;<br>
- info.tag = vdi_cmd_data.snapshot_tag;<br>
- info.vid = 0;<br>
- info.snapid = vdi_cmd_data.snapshot_id;<br>
-<br>
- if (parse_vdi(vdi_info_filler, SD_INODE_HEADER_SIZE, &info) < 0)<br>
- return EXIT_SYSFAIL;<br>
-<br>
- vid = info.vid;<br>
- nr_copies = info.nr_copies;<br>
- if (vid == 0) {<br>
- sd_err("VDI not found");<br>
- return EXIT_MISSING;<br>
+ ret = read_vdi_obj(vdiname, vdi_cmd_data.snapshot_id,<br>
+ vdi_cmd_data.snapshot_tag, NULL, inode,<br>
+ SD_INODE_SIZE);<br>
+ if (ret != EXIT_SUCCESS) {<br>
+ sd_err("FATAL: no inode objects");<br>
+ return ret;<br></blockquote><div><br></div><div>ditto</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
}<br>
+ vid = inode->vdi_id;<br>
+ nr_copies = inode->nr_copies;<br>
<br>
if (!oid) {<br>
if (idx == ~0) {<br>
printf("Tracking the inode object 0x%" PRIx32<br>
" with %d nodes\n", vid, sd_nodes_nr);<br>
+ free(inode);<br>
return do_track_object(vid_to_vdi_oid(vid), nr_copies);<br>
}<br>
<br>
- oid_info.success = false;<br>
- oid_info.idx = idx;<br>
-<br>
if (idx >= MAX_DATA_OBJS) {<br>
printf("The offset is too large!\n");<br>
goto err;<br>
}<br>
<br>
- parse_objs(vid_to_vdi_oid(vid), obj_info_filler, &oid_info,<br>
- get_store_objsize(info.copy_policy,<br>
- vid_to_data_oid(vid, 0)));<br>
-<br>
- if (!oid_info.success) {<br>
- sd_err("Failed to read the inode object 0x%" PRIx32,<br>
- vid);<br>
- goto err;<br>
- }<br>
- if (!oid_info.data_oid) {<br>
- printf("The inode object 0x%"PRIx32<br>
- " idx %u is not allocated\n", vid, idx);<br>
- goto err;<br>
- }<br>
-<br>
- oid = oid_info.data_oid;<br>
+ vdi_id = sd_inode_get_vid(inode, idx);<br>
+ oid = vid_to_data_oid(vdi_id, idx);<br>
<br>
printf("Tracking the object 0x%" PRIx64<br>
" (the inode vid 0x%" PRIx32 " idx %u)"<br>
@@ -1094,9 +968,10 @@ static int vdi_track(int argc, char **argv)<br>
" (the inode vid 0x%" PRIx32 ")"<br>
" with %d nodes\n", oid, vid, sd_nodes_nr);<br>
<br>
+ free(inode);<br>
return do_track_object(oid, nr_copies);<br>
-<br>
err:<br>
+ free(inode);<br>
return EXIT_FAILURE;<br>
}<br>
<br>
diff --git a/include/internal_proto.h b/include/internal_proto.h<br>
index 460264c..ace4ac5 100644<br>
--- a/include/internal_proto.h<br>
+++ b/include/internal_proto.h<br>
@@ -99,6 +99,7 @@<br>
#define SD_OP_SET_LOGLEVEL 0xBA<br>
#define SD_OP_NFS_CREATE 0xBB<br>
#define SD_OP_NFS_DELETE 0xBC<br>
+#define SD_OP_EXIST 0xBD<br>
<br>
/* internal flags for hdr.flags, must be above 0x80 */<br>
#define SD_FLAG_CMD_RECOVERY 0x0080<br>
diff --git a/sheep/ops.c b/sheep/ops.c<br>
index 0e9bc82..ca00a18 100644<br>
--- a/sheep/ops.c<br>
+++ b/sheep/ops.c<br>
@@ -1015,6 +1015,19 @@ static int local_set_loglevel(struct request *req)<br>
return SD_RES_SUCCESS;<br>
}<br>
<br>
+static int local_oid_exist(struct request *req)<br>
+{<br>
+ uint64_t oid = req->rq.obj.oid;<br>
+ uint8_t ec_index = local_ec_index(req->vinfo, oid);<br>
+<br>
+ if (is_erasure_oid(oid) && ec_index == SD_MAX_COPIES)<br>
+ return SD_RES_NO_OBJ;<br>
+<br>
+ if (sd_store->exist(oid, ec_index))<br>
+ return SD_RES_SUCCESS;<br>
+ return SD_RES_NO_OBJ;<br>
+}<br>
+<br>
#ifdef HAVE_NFS<br>
<br>
static int local_nfs_create(struct request *req)<br>
@@ -1336,6 +1349,13 @@ static struct sd_op_template sd_ops[] = {<br>
.process_work = local_set_loglevel,<br>
},<br>
<br>
+ [SD_OP_EXIST] = {<br>
+ .name = "EXIST",<br>
+ .type = SD_OP_TYPE_LOCAL,<br>
+ .force = true,<br>
+ .process_work = local_oid_exist,<br>
+ },<br>
+<br>
#ifdef HAVE_NFS<br>
[SD_OP_NFS_CREATE] = {<br>
.name = "NFS_CREATE",<br>
diff --git a/sheep/recovery.c b/sheep/recovery.c<br>
index 1e5f1af..859375d 100644<br>
--- a/sheep/recovery.c<br>
+++ b/sheep/recovery.c<br>
@@ -445,19 +445,20 @@ out:<br>
return lost;<br>
}<br>
<br>
-static uint8_t local_node_copy_index(struct vnode_info *vinfo, uint64_t oid)<br>
+uint8_t local_ec_index(struct vnode_info *vinfo, uint64_t oid)<br>
{<br>
- int idx;<br>
+ int idx, m = min(get_vdi_copy_number(oid_to_vid(oid)), vinfo->nr_zones);<br>
<br>
if (!is_erasure_oid(oid))<br>
- return 0; /* no need to proceed */<br>
+ return SD_MAX_COPIES;<br>
<br>
- for (idx = 0; idx < vinfo->nr_zones; idx++) {<br>
+ for (idx = 0; idx < m; idx++) {<br>
const struct sd_node *n = oid_to_node(oid, &vinfo->vroot, idx);<br>
if (node_is_local(n))<br>
return idx;<br>
}<br>
- panic("can't get valid index for %"PRIx64, oid);<br>
+ sd_debug("can't get valid index for %"PRIx64, oid);<br>
+ return SD_MAX_COPIES;<br>
}<br>
<br>
/*<br>
@@ -486,7 +487,7 @@ static int recover_erasure_object(struct recovery_obj_work *row)<br>
uint8_t idx;<br>
int ret = -1;<br>
<br>
- idx = local_node_copy_index(cur, oid);<br>
+ idx = local_ec_index(cur, oid);<br>
buf = read_erasure_object(oid, idx, row);<br>
if (!buf && !row->stop)<br>
buf = rebuild_erasure_object(oid, idx, row);<br>
@@ -530,7 +531,7 @@ static void recover_object_work(struct work *work)<br>
struct vnode_info *cur = rw->cur_vinfo;<br>
int ret, epoch;<br>
<br>
- if (sd_store->exist(oid, local_node_copy_index(cur, oid))) {<br>
+ if (sd_store->exist(oid, local_ec_index(cur, oid))) {<br>
sd_debug("the object is already recovered");<br>
return;<br>
}<br>
@@ -585,7 +586,7 @@ main_fn bool oid_in_recovery(uint64_t oid)<br>
return false;<br>
<br>
cur = rinfo->cur_vinfo;<br>
- if (sd_store->exist(oid, local_node_copy_index(cur, oid))) {<br>
+ if (sd_store->exist(oid, local_ec_index(cur, oid))) {<br>
sd_debug("the object %" PRIx64 " is already recoverd", oid);<br>
return false;<br>
}<br>
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h<br>
index f9c5062..3737f5a 100644<br>
--- a/sheep/sheep_priv.h<br>
+++ b/sheep/sheep_priv.h<br>
@@ -436,6 +436,7 @@ int gateway_write_obj(struct request *req);<br>
int gateway_create_and_write_obj(struct request *req);<br>
int gateway_remove_obj(struct request *req);<br>
bool is_erasure_oid(uint64_t oid);<br>
+uint8_t local_ec_index(struct vnode_info *vinfo, uint64_t oid);<br>
<br>
/* object_cache */<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
1.8.1.2<br>
<br>
--<br>
sheepdog mailing list<br>
<a href="mailto:sheepdog@lists.wpkg.org">sheepdog@lists.wpkg.org</a><br>
<a href="http://lists.wpkg.org/mailman/listinfo/sheepdog" target="_blank">http://lists.wpkg.org/mailman/listinfo/sheepdog</a><br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br>--<br>Best Regard<br>Robin Dong
</div></div>