[sheepdog] [PATCH v4 5/6] sheep/http: allow 'Force: true' http header to delete 'incompleted' object forcely

Robin Dong robin.k.dong at gmail.com
Wed Feb 26 04:00:20 CET 2014


From: Robin Dong <sanbai at taobao.com>

Imaging a scenario:

1. Client A is uploading a large object which names 'elephant', it
   only allocate meta-data in oalloc and is creating SD_OBJ_DATA files.
2. Client B send a DELETE request to remove object 'elephant', it
   will remove all the backend files for 'elephant'.
   At the same time, Client A dosen't know what happend because uploading
   progress don't need to lock any vdi.
3. Client A return Create-object-success, but the real data have all been
   removed.

To avoid this scenario, we let DELETE operation do nothing but only return
'CONFLICT' when the object is 'incompleted'. And, users can send the DELETE
request with a new header 'Force: true' which will remove 'incompleted'
object forcely when users make sure that there isn't any uploading progress
for this object.

Signed-off-by: Robin Dong <sanbai at taobao.com>
---
 sheep/http/http.c  |  5 +++++
 sheep/http/http.h  |  4 +++-
 sheep/http/kv.c    | 23 +++++++++++++++++++++--
 sheep/http/s3.c    |  2 +-
 sheep/http/swift.c |  2 +-
 5 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/sheep/http/http.c b/sheep/http/http.c
index 6a04252..3027153 100644
--- a/sheep/http/http.c
+++ b/sheep/http/http.c
@@ -197,6 +197,11 @@ static int request_init_operation(struct http_request *req)
 		req->data_length = max - req->offset;
 		sd_debug("HTTP_RANGE: %"PRIu64" %"PRIu64, req->offset, max);
 	}
+	p = FCGX_GetParam("FORCE", env);
+	if (p && p[0] != '\0') {
+		if (!strcmp("true", p))
+			req->force = true;
+	}
 
 	req->status = UNKNOWN;
 
diff --git a/sheep/http/http.h b/sheep/http/http.h
index 5bcd528..06dfd5d 100644
--- a/sheep/http/http.h
+++ b/sheep/http/http.h
@@ -49,6 +49,7 @@ struct http_request {
 	enum http_status status;
 	uint64_t data_length;
 	uint64_t offset;
+	bool force;
 };
 
 struct http_driver {
@@ -146,7 +147,8 @@ int kv_read_object(struct http_request *req, const char *account,
 		   const char *bucket, const char *object);
 int kv_read_object_meta(struct http_request *req, const char *account,
 			const char *bucket, const char *object);
-int kv_delete_object(const char *account, const char *bucket, const char *);
+int kv_delete_object(const char *account, const char *bucket, const char *,
+		     bool force);
 int kv_iterate_object(const char *account, const char *bucket,
 		      void (*cb)(const char *object, void *opaque),
 		      void *opaque);
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index c9d3e9c..34ccbb4 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -1237,7 +1237,26 @@ out:
 	return ret;
 }
 
-int kv_delete_object(const char *account, const char *bucket, const char *name)
+/*
+ * Imaging a scenario:
+ *
+ * 1. Client A is uploading a large object which names 'elephant', it
+ *    only allocate meta-data in oalloc and is creating SD_OBJ_DATA files.
+ * 2. Client B send a DELETE request to remove object 'elephant', it
+ *    will remove all the backend files for 'elephant'.
+ *    At the same time, Client A dosen't know what happend because uploading
+ *    progress don't need to lock any vdi.
+ * 3. Client A return Create-object-success, but the real data have all been
+ *    removed.
+ *
+ * To avoid this scenario, we let DELETE operation do nothing but only return
+ * 'CONFLICT' when the object is 'incompleted'. And, users can send the DELETE
+ * request with a new header 'Force: true' which will remove 'incompleted'
+ * object forcely when users make sure that there isn't any uploading progress
+ * for this object.
+ */
+int kv_delete_object(const char *account, const char *bucket, const char *name,
+		     bool force)
 {
 	char vdi_name[SD_MAX_VDI_LEN];
 	uint32_t bucket_vid;
@@ -1255,7 +1274,7 @@ int kv_delete_object(const char *account, const char *bucket, const char *name)
 		goto out;
 
 	/* this object has not been uploaded complete */
-	if (onode->flags != ONODE_COMPLETE) {
+	if (!force && onode->flags != ONODE_COMPLETE) {
 		ret = SD_RES_INCOMPLETE;
 		goto out;
 	}
diff --git a/sheep/http/s3.c b/sheep/http/s3.c
index aab1d1c..bf7b311 100644
--- a/sheep/http/s3.c
+++ b/sheep/http/s3.c
@@ -137,7 +137,7 @@ static void s3_post_object(struct http_request *req, const char *bucket,
 static void s3_delete_object(struct http_request *req, const char *bucket,
 			     const char *object)
 {
-	kv_delete_object("s3", bucket, object);
+	kv_delete_object("s3", bucket, object, 0);
 
 	if (req->status == NOT_FOUND)
 		s3_write_err_response(req, "NoSuchKey",
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index aff0f09..e5707ee 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -280,7 +280,7 @@ static void swift_delete_object(struct http_request *req, const char *account,
 {
 	int ret;
 
-	ret = kv_delete_object(account, container, object);
+	ret = kv_delete_object(account, container, object, req->force);
 	switch (ret) {
 	case SD_RES_SUCCESS:
 		http_response_header(req, NO_CONTENT);
-- 
1.7.12.4




More information about the sheepdog mailing list