<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2013/12/7 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">
<div class="HOEnZb"><div class="h5">On Fri, Dec 06, 2013 at 05:04:18PM +0800, Robin Dong wrote:<br>
> From: Robin Dong <<a href="mailto:sanbai@taobao.com">sanbai@taobao.com</a>><br>
><br>
> Using hyper volume (size up to 16PB) to store large number of accounts<br>
> and containers.<br>
><br>
> Signed-off-by: Robin Dong <<a href="mailto:sanbai@taobao.com">sanbai@taobao.com</a>><br>
> ---<br>
> sheep/http/http.c | 2 +<br>
> sheep/http/http.h | 1 +<br>
> sheep/http/kv.c | 630 +++++++++++++++++++++++++++++++++++++++++++++++------<br>
> sheep/http/kv.h | 20 +-<br>
> sheep/http/s3.c | 4 +-<br>
> sheep/http/swift.c | 98 ++++++---<br>
> 6 files changed, 654 insertions(+), 101 deletions(-)<br>
><br>
> diff --git a/sheep/http/http.c b/sheep/http/http.c<br>
> index 04ef364..cae3f44 100644<br>
> --- a/sheep/http/http.c<br>
> +++ b/sheep/http/http.c<br>
> @@ -52,6 +52,7 @@ static inline const char *strstatus(enum http_status status)<br>
> [NO_CONTENT] = "204 No Content",<br>
> [PARTIAL_CONTENT] = "206 Partial Content",<br>
> [BAD_REQUEST] = "400 Bad Request",<br>
> + [UNAUTHORIZED] = "401 Unauthorized",<br>
> [NOT_FOUND] = "404 Not Found",<br>
> [METHOD_NOT_ALLOWED] = "405 Method Not Allowed",<br>
> [CONFLICT] = "409 Conflict",<br>
> @@ -233,6 +234,7 @@ static void http_run_request(struct work *work)<br>
><br>
> if (method != NULL) {<br>
> method(req);<br>
> + sd_debug("req->status %d", req->status);<br>
> if (req->status != UNKNOWN)<br>
> goto out;<br>
> }<br>
> diff --git a/sheep/http/http.h b/sheep/http/http.h<br>
> index 046d412..a8527d1 100644<br>
> --- a/sheep/http/http.h<br>
> +++ b/sheep/http/http.h<br>
> @@ -32,6 +32,7 @@ enum http_status {<br>
> NO_CONTENT, /* 204 */<br>
> PARTIAL_CONTENT, /* 206 */<br>
> BAD_REQUEST, /* 400 */<br>
> + UNAUTHORIZED, /* 401 */<br>
> NOT_FOUND, /* 404 */<br>
> METHOD_NOT_ALLOWED, /* 405 */<br>
> CONFLICT, /* 409 */<br>
> diff --git a/sheep/http/kv.c b/sheep/http/kv.c<br>
> index 8113389..55a7e24 100644<br>
> --- a/sheep/http/kv.c<br>
> +++ b/sheep/http/kv.c<br>
> @@ -16,14 +16,25 @@<br>
><br>
> #define FOR_EACH_VDI(nr, vdis) FOR_EACH_BIT(nr, vdis, SD_NR_VDIS)<br>
><br>
> -static int lookup_bucket(struct http_request *req, const char *bucket,<br>
> - uint32_t *vid)<br>
> +struct bucket_inode {<br>
> + char bucket_name[SD_MAX_BUCKET_NAME];<br>
> + uint64_t obj_count;<br>
> + uint64_t bytes_used;<br>
> + uint32_t vdi_id; /* kv_onode stores in this vdi */<br>
<br>
</div></div>simply name it as onode_vid and no need for comment.<br>
<div class="im"><br>
> + uint32_t pad;<br>
> + uint64_t reserved[SD_MAX_BUCKET_NAME/sizeof(uint64_t) - 3];<br>
> +};<br>
<br>
</div>Use a union like in kv_onode to expelictly set how much space it actually takes.<br>
<div><div class="h5"><br>
> +<br>
> +#define MAX_BUCKETS (SD_MAX_VDI_SIZE / sizeof(struct bucket_inode))<br>
> +#define BUCKETS_PER_SD_OBJ (SD_DATA_OBJ_SIZE / sizeof(struct bucket_inode))<br>
> +<br>
> +static int lookup_vdi(const char *name, uint32_t *vid)<br>
> {<br>
> int ret;<br>
> struct vdi_info info = {};<br>
> struct vdi_iocb iocb = {<br>
> - .name = bucket,<br>
> - .data_len = strlen(bucket),<br>
> + .name = name,<br>
> + .data_len = strlen(name),<br>
> };<br>
><br>
> ret = vdi_lookup(&iocb, &info);<br>
> @@ -32,27 +43,23 @@ static int lookup_bucket(struct http_request *req, const char *bucket,<br>
> *vid = info.vid;<br>
> break;<br>
> case SD_RES_NO_VDI:<br>
> - sd_info("no such bucket %s", bucket);<br>
> - http_response_header(req, NOT_FOUND);<br>
> - return -1;<br>
> + sd_info("no such vdi %s", name);<br>
> + break;<br>
> default:<br>
> - sd_err("%s: bucket %s", sd_strerror(ret), bucket);<br>
> - http_response_header(req, INTERNAL_SERVER_ERROR);<br>
> - return -1;<br>
> + sd_err("Failed to find vdi %s %s", name, sd_strerror(ret));<br>
> }<br>
><br>
> - return 0;<br>
> + return ret;<br>
> }<br>
><br>
> -/* Bucket operations */<br>
> -<br>
> -int kv_create_bucket(struct http_request *req, const char *bucket)<br>
> +static int kv_create_hyper_volume(const char *name, uint32_t *vdi_id)<br>
> {<br>
> struct sd_req hdr;<br>
> + struct sd_rsp *rsp = (struct sd_rsp *)&hdr;<br>
> int ret;<br>
> char buf[SD_MAX_VDI_LEN] = {0};<br>
><br>
> - pstrcpy(buf, SD_MAX_VDI_LEN, bucket);<br>
> + pstrcpy(buf, SD_MAX_VDI_LEN, name);<br>
><br>
> sd_init_req(&hdr, SD_OP_NEW_VDI);<br>
> hdr.flags = SD_FLAG_CMD_WRITE;<br>
> @@ -64,44 +71,50 @@ int kv_create_bucket(struct http_request *req, const char *bucket)<br>
> hdr.vdi.store_policy = 1;<br>
><br>
> ret = exec_local_req(&hdr, buf);<br>
> - switch (ret) {<br>
> - case SD_RES_SUCCESS:<br>
> - http_response_header(req, CREATED);<br>
> - break;<br>
> - case SD_RES_VDI_EXIST:<br>
> - http_response_header(req, ACCEPTED);<br>
> - break;<br>
> - default:<br>
> - sd_err("%s: bucket %s", sd_strerror(ret), bucket);<br>
> - http_response_header(req, INTERNAL_SERVER_ERROR);<br>
> - return -1;<br>
> - }<br>
> + if (rsp->result != SD_RES_SUCCESS)<br>
> + sd_err("Failed to create VDI %s: %s", name,<br>
> + sd_strerror(rsp->result));<br>
><br>
> - return 0;<br>
> -}<br>
> + if (vdi_id)<br>
> + *vdi_id = rsp->vdi.vdi_id;<br>
><br>
> -int kv_read_bucket(struct http_request *req, const char *bucket)<br>
> -{<br>
> - /* TODO: read metadata of the bucket */<br>
> - return -1;<br>
> + return ret;<br>
> }<br>
><br>
> -int kv_update_bucket(struct http_request *req, const char *bucket)<br>
> +static int discard_data_obj(uint64_t oid)<br>
> {<br>
> - /* TODO: update metadata of the bucket */<br>
> - return -1;<br>
> + int ret;<br>
> + struct sd_req hdr;<br>
> +<br>
> + sd_init_req(&hdr, SD_OP_DELETE_CACHE);<br>
> + hdr.obj.oid = oid;<br>
> +<br>
> + ret = exec_local_req(&hdr, NULL);<br>
> + if (ret != SD_RES_SUCCESS) {<br>
> + sd_err("Failed to execute request");<br>
> + return ret;<br>
> + }<br>
> +<br>
<br>
</div></div>Since our container can be accessed by multiple clients, I think we will never<br>
allow object cache for it, which is designed for a single client. So need to run<br>
SD_OP_DELETE_CACHE request.<br></blockquote><div><br></div><div>Do you mean "No need to run SD_OP_DELETE_CAHCE" ? </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
For account HEAD operation:<br>
<br>
yliu@ubuntu-precise:~/sheepdog$ curl -i -X HEAD <a href="http://localhost/v1/yliu
HTTP/1.1" target="_blank">http://localhost/v1/yliu<br>
HTTP/1.1</a> 204 No Content<br>
Server: nginx/1.1.19<br>
Date: Sat, 07 Dec 2013 06:41:46 GMT<br>
Content-Type: text/plain;<br>
Connection: keep-alive<br>
X-Account-Container-Count: 2<br>
<br>
Seems that we need to pass X-Account-Bytes-Used too?<br>
<br>
For account GET operation:<br>
yliu@ubuntu-precise:~/sheepdog$ curl -X GET <a href="http://localhost/v1/yliu" target="_blank">http://localhost/v1/yliu</a><br>
<br>
girls<br>
wives<br>
<br>
Seems that we write extra blank line and lack Content-Length field?<br>
<br>
Thanks<br>
<span class="HOEnZb"><font color="#888888">Yuan<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br>--<br>Best Regard<br>Robin Dong
</div></div>