[sheepdog] [PATCH v3 3/3] sheep/http: refacotor kv_{read, delete}_account

Liu Yuan namei.unix at gmail.com
Thu Dec 26 07:23:14 CET 2013


Also fixes swift_get{account, container} when target doesn't exist.

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 include/internal_proto.h |  2 +-
 sheep/http/http.h        |  4 +--
 sheep/http/kv.c          | 58 ++++++++++++++++++++++++-----------
 sheep/http/swift.c       | 80 +++++++++++++++++++++++++++++-------------------
 4 files changed, 91 insertions(+), 53 deletions(-)

diff --git a/include/internal_proto.h b/include/internal_proto.h
index ac4e3f8..2aefb2d 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -124,7 +124,7 @@
 #define SD_RES_AGAIN            0x8F /* Ask to try again */
 #define SD_RES_STALE_OBJ        0x90 /* Object may be stale */
 #define SD_RES_CLUSTER_ERROR    0x91 /* Cluster driver error */
-#define SD_RES_OBJ_TAKEN        0x92 /* Object ID is taken up */
+#define SD_RES_VDI_NOT_EMPTY    0x92 /* VDI is not empty */
 
 #define SD_CLUSTER_FLAG_STRICT  0x0001 /* Strict mode for write */
 
diff --git a/sheep/http/http.h b/sheep/http/http.h
index 52f5b36..493e10f 100644
--- a/sheep/http/http.h
+++ b/sheep/http/http.h
@@ -116,9 +116,9 @@ int http_request_writef(struct http_request *req, const char *fmt, ...);
 
 /* Account operations */
 int kv_create_account(const char *account);
-int kv_read_account(const char *account, uint32_t *nr_buckets);
+int kv_read_account_meta(struct http_request *req, const char *account);
 int kv_update_account(const char *account);
-int kv_delete_account(const char *account);
+int kv_delete_account(struct http_request *req, const char *account);
 int kv_list_accounts(struct http_request *req,
 		    void (*cb)(struct http_request *req, const char *account,
 			       void *opaque),
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index d04230d..3bb8a1d 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -55,7 +55,9 @@ typedef void (*bucket_iter_cb)(const char *bucket, void *opaque);
 struct bucket_iterater_arg {
 	void *opaque;
 	bucket_iter_cb cb;
-	uint32_t count;
+	uint64_t bucket_count;
+	uint64_t object_count;
+	uint64_t bytes_used;
 };
 
 static int kv_create_hyper_volume(const char *name, uint32_t *vdi_id)
@@ -139,45 +141,55 @@ static void bucket_iterater(void *data, enum btree_node_type type, void *arg)
 			return;
 		if (biarg->cb)
 			biarg->cb(bnode.name, biarg->opaque);
-		biarg->count++;
+		biarg->bucket_count++;
+		biarg->object_count += bnode.object_count;
+		biarg->bytes_used += bnode.bytes_used;
 	}
 }
 
-/* get number of buckets in this account */
-static int kv_get_account(const char *account, uint32_t *nr_buckets)
+static int read_account_meta(const char *account, uint64_t *bucket_count,
+			     uint64_t *object_count, uint64_t *used)
 {
-	struct sd_inode inode;
-	uint64_t oid;
+	struct sd_inode *inode = NULL;
+	struct bucket_iterater_arg arg = {};
 	uint32_t account_vid;
-	struct bucket_iterater_arg arg = {NULL, NULL, 0};
+	uint64_t oid;
 	int ret;
 
 	ret = sd_lookup_vdi(account, &account_vid);
 	if (ret != SD_RES_SUCCESS)
 		goto out;
 
-	/* read account vdi out */
 	oid = vid_to_vdi_oid(account_vid);
-	ret = sd_read_object(oid, (char *)&inode, sizeof(struct sd_inode), 0);
+	inode = xmalloc(sizeof(*inode));
+	ret = sd_read_object(oid, (char *)inode, sizeof(struct sd_inode), 0);
 	if (ret != SD_RES_SUCCESS) {
 		sd_err("Failed to read inode header %lx", oid);
 		goto out;
 	}
 
-	traverse_btree(sheep_bnode_reader, &inode, bucket_iterater, &arg);
-	if (nr_buckets)
-		*nr_buckets = arg.count;
+	traverse_btree(sheep_bnode_reader, inode, bucket_iterater, &arg);
+	*object_count = arg.object_count;
+	*bucket_count = arg.bucket_count;
+	*used = arg.bytes_used;
 out:
+	free(inode);
 	return ret;
 }
 
-int kv_read_account(const char *account, uint32_t *nr_buckets)
+int kv_read_account_meta(struct http_request *req, const char *account)
 {
+	uint64_t bcount, ocount, used;
 	int ret;
 
-	ret = kv_get_account(account, nr_buckets);
+	ret = read_account_meta(account, &bcount, &ocount, &used);
 	if (ret != SD_RES_SUCCESS)
-		sd_err("Failed to get number of buckets in %s", account);
+		return ret;
+
+	http_request_writef(req, "X-Account-Container-Count: %"PRIu64"\n",
+			    bcount);
+	http_request_writef(req, "X-Account-Object-Count: %"PRIu64"\n", ocount);
+	http_request_writef(req, "X-Account-Bytes-Used: %"PRIu64"\n", used);
 	return ret;
 }
 
@@ -187,14 +199,21 @@ int kv_update_account(const char *account)
 	return -1;
 }
 
-int kv_delete_account(const char *account)
+int kv_delete_account(struct http_request *req, const char *account)
 {
+	uint64_t bcount, ocount, used;
 	int ret;
 
+	ret = read_account_meta(account, &bcount, &ocount, &used);
+	if (ret != SD_RES_SUCCESS)
+		return ret;
+
+	if (bcount)
+		return SD_RES_VDI_NOT_EMPTY;
+
 	ret = sd_delete_vdi(account);
 	if (ret != SD_RES_SUCCESS)
 		sd_err("Failed to delete vdi %s", account);
-
 	return ret;
 }
 
@@ -402,6 +421,9 @@ static int bucket_delete(const char *account, uint32_t avid, const char *bucket)
 	if (ret != SD_RES_SUCCESS)
 		return ret;
 
+	if (bnode.object_count > 0)
+		return SD_RES_VDI_NOT_EMPTY;
+
 	ret = sd_discard_object(bnode.oid);
 	if (ret != SD_RES_SUCCESS) {
 		sd_err("failed to discard bnode for %s", bucket);
@@ -561,7 +583,7 @@ out:
 int kv_iterate_bucket(const char *account, bucket_iter_cb cb, void *opaque)
 {
 	struct sd_inode account_inode;
-	struct bucket_iterater_arg arg = {opaque, cb, 0};
+	struct bucket_iterater_arg arg = {opaque, cb, 0, 0, 0};
 	uint32_t account_vid;
 	uint64_t oid;
 	int ret;
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index a2b2e89..1655f9e 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -16,17 +16,13 @@
 
 static void swift_head_account(struct http_request *req, const char *account)
 {
-	uint32_t nr_buckets;
 	int ret;
 
-	ret = kv_read_account(account, &nr_buckets);
-	if (ret)
-		http_response_header(req, UNAUTHORIZED);
-	else {
-		http_request_writef(req, "X-Account-Container-Count: %u\n",
-				    nr_buckets);
+	ret = kv_read_account_meta(req, account);
+	if (ret == SD_RES_SUCCESS)
 		http_response_header(req, NO_CONTENT);
-	}
+	else
+		http_response_header(req, UNAUTHORIZED);
 }
 
 static void swift_get_account_cb(const char *bucket, void *opaque)
@@ -39,11 +35,22 @@ static void swift_get_account_cb(const char *bucket, void *opaque)
 static void swift_get_account(struct http_request *req, const char *account)
 {
 	struct strbuf buf = STRBUF_INIT;
+	int ret;
 
-	kv_iterate_bucket(account, swift_get_account_cb, &buf);
-	req->data_length = buf.len;
-	http_response_header(req, OK);
-	http_request_write(req, buf.buf, buf.len);
+	ret = kv_iterate_bucket(account, swift_get_account_cb, &buf);
+	switch (ret) {
+	case SD_RES_SUCCESS:
+		req->data_length = buf.len;
+		http_response_header(req, OK);
+		http_request_write(req, buf.buf, buf.len);
+		break;
+	case SD_RES_NO_VDI:
+		http_response_header(req, NOT_FOUND);
+		break;
+	default:
+		http_response_header(req, INTERNAL_SERVER_ERROR);
+		break;
+	}
 	strbuf_release(&buf);
 }
 
@@ -67,27 +74,24 @@ static void swift_post_account(struct http_request *req, const char *account)
 
 static void swift_delete_account(struct http_request *req, const char *account)
 {
-	uint32_t nr_buckets;
 	int ret;
 
-	ret = kv_read_account(account, &nr_buckets);
-	if (ret) {
-		http_response_header(req, INTERNAL_SERVER_ERROR);
-		return;
-	}
-
-	if (nr_buckets) {
-		/* return HTTP_CONFLICT when the account is not empty */
+	ret = kv_delete_account(req, account);
+	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;
+	case SD_RES_VDI_NOT_EMPTY:
 		http_response_header(req, CONFLICT);
-		return;
-	}
-
-	ret = kv_delete_account(account);
-	if (ret) {
+		break;
+	default:
 		http_response_header(req, INTERNAL_SERVER_ERROR);
-		return;
+		break;
 	}
-	http_response_header(req, OK);
 }
 
 /* Operations on Containers */
@@ -123,11 +127,23 @@ static void swift_get_container(struct http_request *req, const char *account,
 				const char *container)
 {
 	struct strbuf buf = STRBUF_INIT;
+	int ret;
 
-	kv_iterate_object(account, container, swift_get_container_cb, &buf);
-	req->data_length = buf.len;
-	http_response_header(req, OK);
-	http_request_write(req, buf.buf, buf.len);
+	ret = kv_iterate_object(account, container, swift_get_container_cb,
+				&buf);
+	switch (ret) {
+	case SD_RES_SUCCESS:
+		req->data_length = buf.len;
+		http_response_header(req, OK);
+		http_request_write(req, buf.buf, buf.len);
+		break;
+	case SD_RES_NO_VDI:
+		http_response_header(req, NOT_FOUND);
+		break;
+	default:
+		http_response_header(req, INTERNAL_SERVER_ERROR);
+		break;
+	}
 	strbuf_release(&buf);
 }
 
-- 
1.8.1.2




More information about the sheepdog mailing list