[sheepdog] [PATCH v3 1/3] sheep/http: implement HEAD operation for bucket

Liu Yuan namei.unix at gmail.com
Thu Dec 26 07:38:53 CET 2013


Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/http/http.h  |  3 +-
 sheep/http/kv.c    | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 sheep/http/swift.c | 16 ++++++++++-
 3 files changed, 92 insertions(+), 7 deletions(-)

diff --git a/sheep/http/http.h b/sheep/http/http.h
index dea34e0..40ff307 100644
--- a/sheep/http/http.h
+++ b/sheep/http/http.h
@@ -126,7 +126,8 @@ int kv_list_accounts(struct http_request *req,
 
 /* Bucket operations */
 int kv_create_bucket(const char *account, const char *bucket);
-int kv_read_bucket(const char *account, const char *bucket);
+int kv_read_bucket(struct http_request *req, const char *account,
+		   const char *bucket);
 int kv_update_bucket(const char *account, const char *bucket);
 int kv_delete_bucket(const char *account, const char *bucket);
 int kv_iterate_bucket(const char *account,
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index 5fde277..a58310f 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -18,7 +18,7 @@
 
 struct kv_bnode {
 	char name[SD_MAX_BUCKET_NAME];
-	uint64_t obj_count;
+	uint64_t object_count;
 	uint64_t bytes_used;
 	uint64_t oid;
 };
@@ -320,7 +320,7 @@ static int bucket_create(const char *account, uint32_t account_vid,
 
 	pstrcpy(bnode.name, sizeof(bnode.name), bucket);
 	bnode.bytes_used = 0;
-	bnode.obj_count = 0;
+	bnode.object_count = 0;
 	ret = bnode_create(&bnode, account_vid);
 	if (ret != SD_RES_SUCCESS)
 		goto err;
@@ -355,6 +355,39 @@ out:
 	return ret;
 }
 
+static int bnode_update(const char *account, const char *bucket, uint64_t used,
+			bool create)
+{
+	uint32_t account_vid;
+	struct kv_bnode bnode;
+	int ret;
+
+	ret = sd_lookup_vdi(account, &account_vid);
+	if (ret != SD_RES_SUCCESS) {
+		sd_err("Failed to find account %s", account);
+		return ret;
+	}
+
+	ret = bnode_lookup(&bnode, account_vid, bucket);
+	if (ret != SD_RES_SUCCESS)
+		return ret;
+
+	if (create) {
+		bnode.object_count++;
+		bnode.bytes_used += used;
+	} else {
+		bnode.object_count--;
+		bnode.bytes_used -= used;
+	}
+
+	ret = sd_write_object(bnode.oid, (char *)&bnode, sizeof(bnode), 0, 0);
+	if (ret != SD_RES_SUCCESS) {
+		sd_err("failed to update bnode for %s", bucket);
+		return ret;
+	}
+	return SD_RES_SUCCESS;
+}
+
 static int bucket_delete(const char *account, uint32_t avid, const char *bucket)
 {
 	struct kv_bnode bnode;
@@ -470,10 +503,29 @@ out:
 	return ret;
 }
 
-int kv_read_bucket(const char *account, const char *bucket)
+int kv_read_bucket(struct http_request *req, const char *account,
+		   const char *bucket)
 {
-	/* TODO: read metadata of the bucket */
-	return -1;
+	uint32_t account_vid;
+	struct kv_bnode bnode;
+	int ret;
+
+	ret = sd_lookup_vdi(account, &account_vid);
+	if (ret != SD_RES_SUCCESS) {
+		sd_err("Failed to find account %s", account);
+		return ret;
+	}
+
+	ret = bnode_lookup(&bnode, account_vid, bucket);
+	if (ret != SD_RES_SUCCESS)
+		goto out;
+	http_request_writef(req, "X-Container-Object-Count: %"PRIu64"\n",
+			    bnode.object_count);
+
+	http_request_writef(req, "X-Container-Bytes-Used: %"PRIu64"\n",
+			    bnode.bytes_used);
+out:
+	return ret;
 }
 
 int kv_update_bucket(const char *account, const char *bucket)
@@ -948,6 +1000,13 @@ int kv_create_object(struct http_request *req, const char *account,
 	if (ret != SD_RES_SUCCESS) {
 		sd_err("failed to create onode for %s", name);
 		onode_free_data(onode);
+		goto out;
+	}
+
+	ret = bnode_update(account, bucket, req->data_length, true);
+	if (ret != SD_RES_SUCCESS) {
+		ret = onode_delete(onode);
+		goto out;
 	}
 out:
 	free(onode);
@@ -1000,6 +1059,17 @@ int kv_delete_object(const char *account, const char *bucket, const char *name)
 		goto out;
 
 	ret = onode_delete(onode);
+	if (ret != SD_RES_SUCCESS)
+		goto out;
+
+	/*
+	 * If bnode is deleted successfully, we consider it successful deletion
+	 * even if bnode_update() fails.
+	 *
+	 * FIXME: make bnode metadata consistent
+	 */
+	if (bnode_update(account, bucket, onode->size, false) != SD_RES_SUCCESS)
+		sd_err("failed to update bnode for %s/%s", account, bucket);
 out:
 	free(onode);
 	return ret;
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index 01e864a..c3985be 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -95,7 +95,21 @@ static void swift_delete_account(struct http_request *req, const char *account)
 static void swift_head_container(struct http_request *req, const char *account,
 				 const char *container)
 {
-	http_response_header(req, NOT_IMPLEMENTED);
+	int ret;
+
+	ret = kv_read_bucket(req, account, container);
+	switch (ret) {
+	case SD_RES_SUCCESS:
+		http_response_header(req, NO_CONTENT);
+		break;
+	case SD_RES_NO_VDI:
+	case SD_RES_NO_OBJ:
+		http_response_header(req, NOT_FOUND);
+		break;
+	default:
+		http_response_header(req, INTERNAL_SERVER_ERROR);
+		break;
+	}
 }
 
 static void swift_get_container_cb(const char *object, void *opaque)
-- 
1.8.1.2




More information about the sheepdog mailing list