<div dir="ltr">I think we should add check in <span style="font-family:arial,sans-serif;font-size:14px">kv_delete_bucket() because users can't delete a bucket which still contains objects.</span></div><div class="gmail_extra">
<br><br><div class="gmail_quote">2013/12/26 Liu Yuan <span dir="ltr"><<a href="mailto:namei.unix@gmail.com" target="_blank">namei.unix@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Signed-off-by: Liu Yuan <<a href="mailto:namei.unix@gmail.com">namei.unix@gmail.com</a>><br>
---<br>
 sheep/http/http.h  |  3 +-<br>
 sheep/http/kv.c    | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++----<br>
 sheep/http/swift.c | 16 ++++++++++-<br>
 3 files changed, 92 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/sheep/http/http.h b/sheep/http/http.h<br>
index dea34e0..40ff307 100644<br>
--- a/sheep/http/http.h<br>
+++ b/sheep/http/http.h<br>
@@ -126,7 +126,8 @@ int kv_list_accounts(struct http_request *req,<br>
<br>
 /* Bucket operations */<br>
 int kv_create_bucket(const char *account, const char *bucket);<br>
-int kv_read_bucket(const char *account, const char *bucket);<br>
+int kv_read_bucket(struct http_request *req, const char *account,<br>
+                  const char *bucket);<br>
 int kv_update_bucket(const char *account, const char *bucket);<br>
 int kv_delete_bucket(const char *account, const char *bucket);<br>
 int kv_iterate_bucket(const char *account,<br>
diff --git a/sheep/http/kv.c b/sheep/http/kv.c<br>
index 5fde277..a58310f 100644<br>
--- a/sheep/http/kv.c<br>
+++ b/sheep/http/kv.c<br>
@@ -18,7 +18,7 @@<br>
<br>
 struct kv_bnode {<br>
        char name[SD_MAX_BUCKET_NAME];<br>
-       uint64_t obj_count;<br>
+       uint64_t object_count;<br>
        uint64_t bytes_used;<br>
        uint64_t oid;<br>
 };<br>
@@ -320,7 +320,7 @@ static int bucket_create(const char *account, uint32_t account_vid,<br>
<br>
        pstrcpy(<a href="http://bnode.name" target="_blank">bnode.name</a>, sizeof(<a href="http://bnode.name" target="_blank">bnode.name</a>), bucket);<br>
        bnode.bytes_used = 0;<br>
-       bnode.obj_count = 0;<br>
+       bnode.object_count = 0;<br>
        ret = bnode_create(&bnode, account_vid);<br>
        if (ret != SD_RES_SUCCESS)<br>
                goto err;<br>
@@ -355,6 +355,39 @@ out:<br>
        return ret;<br>
 }<br>
<br>
+static int bnode_update(const char *account, const char *bucket, uint64_t used,<br>
+                       bool create)<br>
+{<br>
+       uint32_t account_vid;<br>
+       struct kv_bnode bnode;<br>
+       int ret;<br>
+<br>
+       ret = sd_lookup_vdi(account, &account_vid);<br>
+       if (ret != SD_RES_SUCCESS) {<br>
+               sd_err("Failed to find account %s", account);<br>
+               return ret;<br>
+       }<br>
+<br>
+       ret = bnode_lookup(&bnode, account_vid, bucket);<br>
+       if (ret != SD_RES_SUCCESS)<br>
+               return ret;<br>
+<br>
+       if (create) {<br>
+               bnode.object_count++;<br>
+               bnode.bytes_used += used;<br>
+       } else {<br>
+               bnode.object_count--;<br>
+               bnode.bytes_used -= used;<br>
+       }<br>
+<br>
+       ret = sd_write_object(bnode.oid, (char *)&bnode, sizeof(bnode), 0, 0);<br>
+       if (ret != SD_RES_SUCCESS) {<br>
+               sd_err("failed to update bnode for %s", bucket);<br>
+               return ret;<br>
+       }<br>
+       return SD_RES_SUCCESS;<br>
+}<br>
+<br>
 static int bucket_delete(const char *account, uint32_t avid, const char *bucket)<br>
 {<br>
        struct kv_bnode bnode;<br>
@@ -470,10 +503,29 @@ out:<br>
        return ret;<br>
 }<br>
<br>
-int kv_read_bucket(const char *account, const char *bucket)<br>
+int kv_read_bucket(struct http_request *req, const char *account,<br>
+                  const char *bucket)<br>
 {<br>
-       /* TODO: read metadata of the bucket */<br>
-       return -1;<br>
+       uint32_t account_vid;<br>
+       struct kv_bnode bnode;<br>
+       int ret;<br>
+<br>
+       ret = sd_lookup_vdi(account, &account_vid);<br>
+       if (ret != SD_RES_SUCCESS) {<br>
+               sd_err("Failed to find account %s", account);<br>
+               return ret;<br>
+       }<br>
+<br>
+       ret = bnode_lookup(&bnode, account_vid, bucket);<br>
+       if (ret != SD_RES_SUCCESS)<br>
+               goto out;<br>
+       http_request_writef(req, "X-Container-Object-Count: %"PRIu64"\n",<br>
+                           bnode.object_count);<br>
+<br>
+       http_request_writef(req, "X-Container-Bytes-Used: %"PRIu64"\n",<br>
+                           bnode.bytes_used);<br>
+out:<br>
+       return ret;<br>
 }<br>
<br>
 int kv_update_bucket(const char *account, const char *bucket)<br>
@@ -948,6 +1000,13 @@ int kv_create_object(struct http_request *req, const char *account,<br>
        if (ret != SD_RES_SUCCESS) {<br>
                sd_err("failed to create onode for %s", name);<br>
                onode_free_data(onode);<br>
+               goto out;<br>
+       }<br>
+<br>
+       ret = bnode_update(account, bucket, req->data_length, true);<br>
+       if (ret != SD_RES_SUCCESS) {<br>
+               ret = onode_delete(onode);<br>
+               goto out;<br>
        }<br>
 out:<br>
        free(onode);<br>
@@ -1000,6 +1059,17 @@ int kv_delete_object(const char *account, const char *bucket, const char *name)<br>
                goto out;<br>
<br>
        ret = onode_delete(onode);<br>
+       if (ret != SD_RES_SUCCESS)<br>
+               goto out;<br>
+<br>
+       /*<br>
+        * If bnode is deleted successfully, we consider it successful deletion<br>
+        * even if bnode_update() fails.<br>
+        *<br>
+        * FIXME: make bnode metadata consistent<br>
+        */<br>
+       if (bnode_update(account, bucket, onode->size, false) != SD_RES_SUCCESS)<br>
+               sd_err("failed to update bnode for %s/%s", account, bucket);<br>
 out:<br>
        free(onode);<br>
        return ret;<br>
diff --git a/sheep/http/swift.c b/sheep/http/swift.c<br>
index 01e864a..c3985be 100644<br>
--- a/sheep/http/swift.c<br>
+++ b/sheep/http/swift.c<br>
@@ -95,7 +95,21 @@ static void swift_delete_account(struct http_request *req, const char *account)<br>
 static void swift_head_container(struct http_request *req, const char *account,<br>
                                 const char *container)<br>
 {<br>
-       http_response_header(req, NOT_IMPLEMENTED);<br>
+       int ret;<br>
+<br>
+       ret = kv_read_bucket(req, account, container);<br>
+       switch (ret) {<br>
+       case SD_RES_SUCCESS:<br>
+               http_response_header(req, NO_CONTENT);<br>
+               break;<br>
+       case SD_RES_NO_VDI:<br>
+       case SD_RES_NO_OBJ:<br>
+               http_response_header(req, NOT_FOUND);<br>
+               break;<br>
+       default:<br>
+               http_response_header(req, INTERNAL_SERVER_ERROR);<br>
+               break;<br>
+       }<br>
 }<br>
<br>
 static void swift_get_container_cb(const char *object, void *opaque)<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.1.2<br>
<br>
--<br>
sheepdog mailing list<br>
<a href="mailto:sheepdog@lists.wpkg.org">sheepdog@lists.wpkg.org</a><br>
<a href="http://lists.wpkg.org/mailman/listinfo/sheepdog" target="_blank">http://lists.wpkg.org/mailman/listinfo/sheepdog</a><br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br>--<br>Best Regard<br>Robin Dong
</div>