[sheepdog] [PATCH v2 4/6] sheep/http: add flag for onode
Robin Dong
robin.k.dong at gmail.com
Tue Feb 25 07:07:22 CET 2014
From: Robin Dong <sanbai at taobao.com>
Add flag for onode, so we can identify which object is upload complete and
which has been interrupted by client when uploading.
Signed-off-by: Robin Dong <sanbai at taobao.com>
---
include/sheepdog_proto.h | 1 +
sheep/http/kv.c | 54 +++++++++++++++++++++++++++++++++++++++++++++---
sheep/http/swift.c | 10 +++++++++
3 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index d553da9..17c727e 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -74,6 +74,7 @@
#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_READONLY 0x1A /* Object is read-only */
+#define SD_RES_INCOMPLETE 0x1B /* Object (in kv) is complete uploading */
/* errors above 0x80 are sheepdog-internal */
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index 34417c4..4e1f0c6 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -30,6 +30,10 @@ struct onode_extent {
uint64_t count;
};
+/* for onode->flags */
+#define ONODE_INIT 1 /* created and allocated space, but no data */
+#define ONODE_COMPLETE 2 /* data upload complete */
+
struct kv_onode {
union {
struct {
@@ -42,6 +46,7 @@ struct kv_onode {
uint32_t nr_extent;
uint64_t oid;
uint8_t inlined;
+ uint8_t flags;
};
uint8_t pad[BLOCK_SIZE];
@@ -748,7 +753,7 @@ out:
static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
{
ssize_t size;
- int ret = SD_RES_SUCCESS;
+ int ret = SD_RES_SUCCESS, offset;
if (req->data_length <= KV_ONODE_INLINE_SIZE) {
size = http_request_read(req, onode->data, sizeof(onode->data));
@@ -767,6 +772,13 @@ static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
if (ret != SD_RES_SUCCESS)
goto out;
}
+ /* write ONODE_COMPLETE to onode->flags */
+ onode->flags = ONODE_COMPLETE;
+ offset = offsetof(struct kv_onode, flags);
+ ret = sd_write_object(onode->oid, (char *)onode + offset,
+ sizeof(uint8_t), offset, false);
+ if (ret != SD_RES_SUCCESS)
+ sd_err("Failed to write flags of onode %s", onode->name);
out:
return ret;
}
@@ -1054,6 +1066,12 @@ static int onode_allocate_space(struct http_request *req, const char *account,
sys->cdrv->lock(bucket_vid);
ret = onode_lookup_nolock(onode, bucket_vid, name);
if (ret == SD_RES_SUCCESS) {
+ /* if the exists onode has not been uploaded complete */
+ if (onode->flags != ONODE_COMPLETE) {
+ ret = SD_RES_INCOMPLETE;
+ sd_err("The exists onode %s is incomplete", name);
+ goto out;
+ }
/* For overwrite, we delete old object and then create */
ret = onode_delete(onode);
if (ret != SD_RES_SUCCESS) {
@@ -1065,8 +1083,10 @@ static int onode_allocate_space(struct http_request *req, const char *account,
sd_err("Failed to update bnode for %s", name);
goto out;
}
- } else if (ret != SD_RES_NO_OBJ)
+ } else if (ret != SD_RES_NO_OBJ) {
+ sd_err("Failed to lookup onode %s %s", name, sd_strerror(ret));
goto out;
+ }
snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s/allocator", account, bucket);
ret = sd_lookup_vdi(vdi_name, &data_vid);
@@ -1076,6 +1096,7 @@ static int onode_allocate_space(struct http_request *req, const char *account,
memset(onode, 0, sizeof(*onode));
pstrcpy(onode->name, sizeof(onode->name), name);
onode->data_vid = data_vid;
+ onode->flags = ONODE_INIT;
ret = onode_allocate_data(onode, req);
if (ret != SD_RES_SUCCESS) {
@@ -1106,6 +1127,15 @@ out:
*
* onode is a index node that maps name to sheepdog objects which hold the user
* data, similar to UNIX inode. We use simple hashing for [name, onode] mapping.
+ *
+ * Cases:
+ * 1. create objects with same name simultaneously,
+ * only one object will be create.
+ * 2. create object and delete object simultaneously,
+ * return FAIL for "delete object" request if "create object" is running.
+ * 3. kill client if it is uploading object,
+ * the object is "INCOMPLETED", it will return "PARTIAL_CONTENT" when
+ * client GET or HEAD object.
*/
int kv_create_object(struct http_request *req, const char *account,
const char *bucket, const char *name)
@@ -1156,9 +1186,15 @@ int kv_read_object(struct http_request *req, const char *account,
if (ret != SD_RES_SUCCESS)
goto out;
+ /* this object has not been uploaded complete */
+ if (onode->flags != ONODE_COMPLETE) {
+ ret = SD_RES_EIO;
+ goto out;
+ }
+
ret = onode_read_data(onode, req);
if (ret != SD_RES_SUCCESS)
- sd_err("failed to read data for %s", name);
+ sd_err("failed to read data for %s ret %d", name, ret);
out:
free(onode);
return ret;
@@ -1181,6 +1217,12 @@ int kv_delete_object(const char *account, const char *bucket, const char *name)
if (ret != SD_RES_SUCCESS)
goto out;
+ /* this object has not been uploaded complete */
+ if (onode->flags != ONODE_COMPLETE) {
+ ret = SD_RES_INCOMPLETE;
+ goto out;
+ }
+
ret = onode_delete(onode);
if (ret != SD_RES_SUCCESS) {
sd_err("failed to delete bnode for %s", name);
@@ -1245,6 +1287,12 @@ int kv_read_object_meta(struct http_request *req, const char *account,
req->data_length = onode->size;
http_request_writef(req, "Last-Modified: %s\n",
http_time(onode->mtime));
+
+ /* this object has not been uploaded complete */
+ if (onode->flags != ONODE_COMPLETE) {
+ ret = SD_RES_INCOMPLETE;
+ goto out;
+ }
out:
free(onode);
return ret;
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index 7b9685a..aff0f09 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -210,6 +210,9 @@ static void swift_head_object(struct http_request *req, const char *account,
case SD_RES_NO_OBJ:
http_response_header(req, NOT_FOUND);
break;
+ case SD_RES_INCOMPLETE:
+ http_response_header(req, PARTIAL_CONTENT);
+ break;
default:
http_response_header(req, INTERNAL_SERVER_ERROR);
break;
@@ -256,6 +259,10 @@ static void swift_put_object(struct http_request *req, const char *account,
break;
case SD_RES_NO_SPACE:
http_response_header(req, SERVICE_UNAVAILABLE);
+ break;
+ case SD_RES_INCOMPLETE:
+ http_response_header(req, CONFLICT);
+ break;
default:
http_response_header(req, INTERNAL_SERVER_ERROR);
break;
@@ -282,6 +289,9 @@ static void swift_delete_object(struct http_request *req, const char *account,
case SD_RES_NO_OBJ:
http_response_header(req, NOT_FOUND);
break;
+ case SD_RES_INCOMPLETE:
+ http_response_header(req, CONFLICT);
+ break;
default:
http_response_header(req, INTERNAL_SERVER_ERROR);
break;
--
1.7.12.4
More information about the sheepdog
mailing list