[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