From: Robin Dong <san...@taobao.com>

Using hyper volume and extent structure of onode to store large number of
objects size of which exceed SD_DATA_OBJ_SIZE.

Signed-off-by: Robin Dong <san...@taobao.com>
---
 sheep/http/kv.c    | 427 +++++++++++++++++++++++++++++++++++++++--------------
 sheep/http/kv.h    |  15 +-
 sheep/http/s3.c    |   8 +-
 sheep/http/swift.c |  30 +---
 4 files changed, 336 insertions(+), 144 deletions(-)

diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index 7d002b0..a47295c 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -21,6 +21,7 @@ struct bucket_inode_hdr {
        uint64_t obj_count;
        uint64_t bytes_used;
        uint32_t onode_vid;
+       uint32_t data_vid;              /* data of objects store in this vdi */
 };
 
 struct bucket_inode {
@@ -159,13 +160,13 @@ int kv_create_account(const char *account)
        return kv_create_hyper_volume(account, &vdi_id);
 }
 
-typedef void (*list_cb)(struct http_request *req, const char *bucket,
-                       void *opaque);
+typedef void (*list_bucket_cb)(struct http_request *req, const char *bucket,
+                              void *opaque);
 
 struct list_buckets_arg {
        struct http_request *req;
        void *opaque;
-       list_cb cb;
+       list_bucket_cb cb;
        uint32_t bucket_counter;
 };
 
@@ -347,7 +348,16 @@ static int delete_bucket(struct sd_inode *account_inode, 
uint64_t idx,
                bnode->hdr.onode_vid = 0;
                snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s",
                         account_inode->name, bucket);
-
+               /* delete vdi which store kv_onode */
+               ret = kv_delete_vdi(vdi_name);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to delete vdi %s", vdi_name);
+                       ret = -1;
+                       goto out;
+               }
+               /* delete vdi which store object data */
+               snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s/allocator",
+                        account_inode->name, bucket);
                ret = kv_delete_vdi(vdi_name);
                if (ret != SD_RES_SUCCESS) {
                        sd_err("Failed to delete vdi %s", vdi_name);
@@ -449,12 +459,29 @@ static int add_bucket(struct sd_inode *account_inode, 
uint64_t idx,
                bnode->hdr.bytes_used = 0;
                snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s",
                         account_inode->name, bucket);
+               /* create vdi to store kv_onode */
                ret = kv_create_hyper_volume(vdi_name, &(bnode->hdr.onode_vid));
                if (ret != SD_RES_SUCCESS) {
                        sd_err("Failed to create hyper volume %d", ret);
                        ret = -1;
                        goto out;
                }
+               snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s/allocator",
+                        account_inode->name, bucket);
+               /* create vdi to store objects */
+               ret = kv_create_hyper_volume(vdi_name, &(bnode->hdr.data_vid));
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to create hyper volume %d", ret);
+                       ret = -1;
+                       goto out;
+               }
+               ret = oalloc_init(bnode->hdr.data_vid);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to init allocator on %x",
+                              bnode->hdr.data_vid);
+                       ret = -1;
+                       goto out;
+               }
                sd_debug("create hyper volume %s success", vdi_name);
                break;
        }
@@ -616,8 +643,8 @@ int kv_delete_bucket(const char *account, const char 
*bucket)
        return SD_RES_SUCCESS;
 }
 
-int kv_list_buckets(struct http_request *req, const char *account, list_cb cb,
-                   void *opaque)
+int kv_list_buckets(struct http_request *req, const char *account,
+                   list_bucket_cb cb, void *opaque)
 {
        struct sd_inode account_inode;
        uint32_t account_vid;
@@ -645,6 +672,34 @@ int kv_list_buckets(struct http_request *req, const char 
*account, list_cb cb,
        return SD_RES_SUCCESS;
 }
 
+/*
+ * A bucket contains two vdi: one (vdi_id)  stores 'struct kv_onode' by hash
+ * algorithm and another one (data_vid) stores data of objects.
+ * The first vdi names "account/bucket" and the second vdi names
+ * "account/bucket/allocator".
+ *
+ * It manage space in data vdi by algorithm in oalloc.c.
+ *
+ * For example: bucket "fruit" with account 'coly' has two objects "banana"
+ *              and "apple"
+ *
+ *
+ *                       --------------------- kv_onode -----------------------
+ *                      |                                                      
|
+ * bucket vdi           v                                                      
v
+ * 
+-----------------+--+---------------------------+--------------------------+
+ * |name: coly/fruit |..|kv_onode_hdr (name: banana)|onode_extent: start, 
count|
+ * 
+-----------------+--+---------------------------+--------------------------+
+ *                                                                  /
+ *                                                                 /
+ *                                                     ------------
+ *                                                    /
+ *                  data_vid                        v
+ *                   +---------------------------+---+-----------------+
+ *                   |name: coly/fruit/allocator |...|       data      |
+ *                   +---------------------------+---+-----------------+
+ */
+
 /* Object operations */
 
 /* 4 KB header of kv object index node */
@@ -668,8 +723,6 @@ struct kv_onode_hdr {
 };
 
 struct onode_extent {
-       uint32_t vdi;
-       uint32_t pad;
        uint64_t start;
        uint64_t count;
 };
@@ -678,24 +731,71 @@ struct kv_onode {
        struct kv_onode_hdr hdr;
        union {
                uint8_t data[SD_DATA_OBJ_SIZE - sizeof(struct kv_onode_hdr)];
-               struct onode_extent *o_extent;
+               struct onode_extent o_extent[0];
        };
 };
 
+typedef void (*list_object_cb)(struct http_request *req, const char *bucket,
+                              const char *object, void *opaque);
+
+struct list_objects_arg {
+       struct http_request *req;
+       void *opaque;
+       const char *bucket;
+       list_object_cb cb;
+       uint32_t object_counter;
+};
+
+static void list_objects_cb(void *data, enum btree_node_type type, void *arg)
+{
+       struct sd_extent *ext;
+       struct list_objects_arg *loarg = arg;
+       struct kv_onode *onode = NULL;
+       uint64_t oid;
+       int ret;
+
+       if (type == BTREE_EXT) {
+               ext = (struct sd_extent *)data;
+               if (!ext->vdi_id)
+                       goto out;
+
+               onode = xmalloc(SD_DATA_OBJ_SIZE);
+
+               oid = vid_to_data_oid(ext->vdi_id, ext->idx);
+               ret = sd_read_object(oid, (char *)onode, SD_DATA_OBJ_SIZE, 0);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to read data object %lx", oid);
+                       goto out;
+               }
+
+               if (onode->hdr.name[0] == '\0')
+                       goto out;
+               if (loarg->cb)
+                       loarg->cb(loarg->req, loarg->bucket, onode->hdr.name,
+                                 loarg->opaque);
+               loarg->object_counter++;
+       }
+out:
+       free(onode);
+}
+
 #define KV_ONODE_INLINE_SIZE (SD_DATA_OBJ_SIZE - sizeof(struct kv_onode_hdr))
 
-static int kv_create_inlined_object(struct sd_inode *inode,
-                                   struct kv_onode *onode,
-                                   uint32_t vid, uint32_t idx,
-                                   bool overwrite)
+static int kv_write_onode(struct sd_inode *inode, struct kv_onode *onode,
+                         uint32_t vid, uint32_t idx, bool overwrite)
 {
-       uint64_t oid = vid_to_data_oid(vid, idx);
+       uint64_t oid = vid_to_data_oid(vid, idx), len;
        int ret;
 
+       if (onode->hdr.inlined)
+               len = onode->hdr.size;
+       else
+               len = sizeof(struct onode_extent) * onode->hdr.nr_extent;
+
        if (overwrite) {
                sd_info("overwrite object %s", onode->hdr.name);
                ret = sd_write_object(oid, (char *)onode,
-                                     sizeof(onode->hdr) + onode->hdr.size,
+                                     sizeof(onode->hdr) + len,
                                      0, false);
                if (ret != SD_RES_SUCCESS) {
                        sd_err("failed to write object, %" PRIx64, oid);
@@ -703,7 +803,7 @@ static int kv_create_inlined_object(struct sd_inode *inode,
                }
        } else {
                ret = sd_write_object(oid, (char *)onode,
-                                     sizeof(onode->hdr) + onode->hdr.size,
+                                     sizeof(onode->hdr) + len,
                                      0, true);
                if (ret != SD_RES_SUCCESS) {
                        sd_err("failed to create object, %" PRIx64, oid);
@@ -722,13 +822,6 @@ out:
        return ret;
 }
 
-static int kv_create_extented_object(struct sd_inode *inode,
-                                    struct kv_onode *onode,
-                                    uint32_t vid, uint32_t idx)
-{
-       return SD_RES_SUCCESS;
-}
-
 /*
  * Create the object if the index isn't taken. Overwrite the object if it 
exists
  * Return SD_RES_OBJ_TAKEN if the index is taken by other object.
@@ -765,48 +858,111 @@ static int do_kv_create_object(struct http_request *req,
                        goto out;
                }
        }
-       if (onode->hdr.inlined)
-               ret = kv_create_inlined_object(inode, onode, vid, idx,
-                                              !!tmp_vid);
-       else
-               ret = kv_create_extented_object(inode, onode, vid, idx);
+
+       ret = kv_write_onode(inode, onode, vid, idx, !!tmp_vid);
+       if (ret != SD_RES_SUCCESS)
+               sd_err("Failed to write onode");
 out:
        free(inode);
        return ret;
 }
 
-int kv_create_object(struct http_request *req, const char *bucket,
-                    const char *name)
+int kv_create_object(struct http_request *req, const char *account,
+                    const char *bucket, const char *name)
 {
        struct kv_onode *onode;
-       ssize_t size;
+       ssize_t size, total_size = 0;
        int ret;
-       uint64_t hval;
-       uint32_t vid;
+       uint64_t hval, start = 0, count, block, limit;
+       uint32_t vid, data_vid;
        struct timeval tv;
+       char vdi_name[SD_MAX_VDI_LEN];
+       char *data_buf = NULL;
 
-       ret = lookup_bucket(req, bucket, &vid);
+       snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+       ret = lookup_bucket(req, vdi_name, &vid);
+       if (ret < 0)
+               return ret;
+
+       snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s/allocator", account, bucket);
+       ret = lookup_bucket(req, vdi_name, &data_vid);
        if (ret < 0)
                return ret;
 
        onode = xzalloc(sizeof(*onode));
 
+       /* for inlined onode */
+       if (req->data_length <= KV_ONODE_INLINE_SIZE) {
+               onode->hdr.inlined = 1;
+               size = http_request_read(req, onode->data, sizeof(onode->data));
+               if (size < 0) {
+                       sd_err("%s: bucket %s, object %s", sd_strerror(ret),
+                              bucket, name);
+                       http_response_header(req, INTERNAL_SERVER_ERROR);
+                       ret = -1;
+                       goto out;
+               }
+               total_size = size;
+       } else {
+               sd_debug("data_length: %lu, %lu", req->data_length,
+                        SD_DATA_OBJ_SIZE);
+               count = (req->data_length + SD_DATA_OBJ_SIZE + 1) /
+                       SD_DATA_OBJ_SIZE;
+               ret = oalloc_new_prepare(data_vid, &start, count);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to prepare allocation of %lu bytes!",
+                              req->data_length);
+                       ret = -1;
+                       goto out;
+               }
+
+               /* receive and write data at first, then write onode */
+               data_buf = xmalloc(SD_DATA_OBJ_SIZE);
+
+               sd_debug("start: %lu, count: %lu", start, count);
+               for (block = start, limit = start + count;
+                    block < limit; block++) {
+                       sd_debug("block: %lu, limit: %lu", block, limit);
+                       size = http_request_read(req, data_buf,
+                                                SD_DATA_OBJ_SIZE);
+                       total_size += size;
+                       ret = sd_write_object(vid_to_data_oid(data_vid, block),
+                                             data_buf, size, 0, true);
+                       if (ret != SD_RES_SUCCESS) {
+                               sd_err("Failed to write data object for %"
+                                      PRIx32" %s", data_vid, sd_strerror(ret));
+                               goto out;
+                       }
+                       if (size < SD_DATA_OBJ_SIZE)
+                               break;
+               }
+
+               sd_debug("DATA_LENGTH: %lu, total size: %lu, last blocks: %lu",
+                        req->data_length, total_size, start);
+
+               sd_debug("finish start: %lu, count: %lu", start, count);
+               ret = oalloc_new_finish(data_vid, start, count);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("Failed to finish allocation of %lu bytes!",
+                              req->data_length);
+                       ret = -1;
+                       goto out;
+               }
+
+               onode->o_extent[0].start = start;
+               onode->o_extent[0].count = count;
+               onode->hdr.nr_extent = 1;
+       }
+
+       /* after write data, we write onode now */
+
        gettimeofday(&tv, NULL);
        pstrcpy(onode->hdr.name, sizeof(onode->hdr.name), name);
        onode->hdr.ctime = (uint64_t) tv.tv_sec << 32 | tv.tv_usec * 1000;
        onode->hdr.mtime = onode->hdr.ctime;
+       onode->hdr.size = total_size;
+       onode->hdr.data_vid = data_vid;
 
-       size = http_request_read(req, onode->data, sizeof(onode->data));
-       if (size < 0) {
-               sd_err("%s: bucket %s, object %s", sd_strerror(ret),
-                      bucket, name);
-               http_response_header(req, INTERNAL_SERVER_ERROR);
-               return -1;
-       }
-
-       onode->hdr.size = size;
-       if (size <= KV_ONODE_INLINE_SIZE)
-               onode->hdr.inlined = 1;
        hval = sd_hash(name, strlen(name));
        for (int i = 0; i < MAX_DATA_OBJS; i++) {
                uint32_t idx = (hval + i) % MAX_DATA_OBJS;
@@ -815,30 +971,66 @@ int kv_create_object(struct http_request *req, const char 
*bucket,
                switch (ret) {
                case SD_RES_SUCCESS:
                        http_response_header(req, CREATED);
-                       free(onode);
-                       return 0;
+                       goto out;
                case SD_RES_OBJ_TAKEN:
                        break;
                default:
                        http_response_header(req, INTERNAL_SERVER_ERROR);
-                       free(onode);
-                       return -1;
+                       goto out;
                }
        }
-
        /* no free space to create a object */
        http_response_header(req, SERVICE_UNAVAILABLE);
+out:
        free(onode);
-       return -1;
+       free(data_buf);
+       return ret;
+}
+
+static int kv_read_extent_onode(struct http_request *req,
+                               struct kv_onode *onode)
+{
+       struct onode_extent *ext;
+       uint64_t oid, block, size, total_size, limit;
+       uint32_t i;
+       int ret;
+       char *data_buf = NULL;
+
+       data_buf = xmalloc(SD_DATA_OBJ_SIZE);
+
+       total_size = onode->hdr.size;
+       ext = onode->o_extent;
+       for (i = 0; i < onode->hdr.nr_extent; i++) {
+               limit = ext->count + ext->start;
+               for (block = ext->start; block < limit; block++) {
+                       oid = vid_to_data_oid(onode->hdr.data_vid, block);
+                       if (total_size < SD_DATA_OBJ_SIZE)
+                               size = total_size;
+                       else
+                               size = SD_DATA_OBJ_SIZE;
+                       ret = sd_read_object(oid, data_buf, size, 0);
+                       if (ret != SD_RES_SUCCESS) {
+                               sd_err("Failed to read oid %lx", oid);
+                               goto out;
+                       }
+                       http_request_write(req, data_buf, size);
+                       total_size -= size;
+                       sd_debug("read extented block %lu, size %lu",
+                                block, size);
+               }
+       }
+out:
+       free(data_buf);
+       return ret;
 }
 
 static int do_kv_read_object(struct http_request *req, const char *obj_name,
-                            struct kv_onode *obj, uint32_t vid, uint32_t idx)
+                            struct kv_onode *onode, uint32_t vid, uint32_t idx)
 {
        uint64_t oid = vid_to_data_oid(vid, idx);
        int ret;
 
-       ret = sd_read_object(oid, (char *)obj, sizeof(*obj), 0);
+       ret = sd_read_object(oid, (char *)onode, sizeof(*onode), 0);
        switch (ret) {
        case SD_RES_SUCCESS:
                break;
@@ -852,42 +1044,51 @@ static int do_kv_read_object(struct http_request *req, 
const char *obj_name,
                return -1;
        }
 
-       if (strcmp(obj->hdr.name, obj_name) == 0) {
+       if (strcmp(onode->hdr.name, obj_name) == 0) {
                http_response_header(req, OK);
-
-               /* TODO: support multi parted object for large object */
-               http_request_write(req, obj->data, obj->hdr.size);
+               /* for inlined onode */
+               if (onode->hdr.inlined)
+                       http_request_write(req, onode->data, onode->hdr.size);
+               else {
+                       ret = kv_read_extent_onode(req, onode);
+                       if (ret) {
+                               sd_err("Failed to read extent onode");
+                               return -1;
+                       }
+               }
        }
 
        return 0;
 }
 
-int kv_read_object(struct http_request *req, const char *bucket,
-                  const char *object)
+int kv_read_object(struct http_request *req, const char *account,
+                  const char *bucket, const char *object)
 {
-       struct kv_onode *obj;
+       struct kv_onode *onode;
        int ret;
        uint64_t hval;
        uint32_t vid;
+       char vdi_name[SD_MAX_VDI_LEN];
 
-       ret = lookup_bucket(req, bucket, &vid);
+       snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+       ret = lookup_bucket(req, vdi_name, &vid);
        if (ret < 0)
                return ret;
 
-       obj = xzalloc(sizeof(*obj));
+       onode = xzalloc(sizeof(*onode));
 
        hval = sd_hash(object, strlen(object));
        for (int i = 0; i < MAX_DATA_OBJS; i++) {
                uint32_t idx = (hval + i) % MAX_DATA_OBJS;
 
-               do_kv_read_object(req, object, obj, vid, idx);
+               do_kv_read_object(req, object, onode, vid, idx);
                if (req->status != UNKNOWN) {
-                       free(obj);
+                       free(onode);
                        return 0;
                }
        }
 
-       free(obj);
+       free(onode);
 
        http_response_header(req, NOT_FOUND);
        return -1;
@@ -980,9 +1181,11 @@ int kv_update_object(struct http_request *req, const char 
*bucket,
 static int do_kv_delete_object(struct http_request *req, const char *obj_name,
                               uint32_t vid, uint32_t idx)
 {
+       struct kv_onode *onode = NULL;
+       struct onode_extent *ext = NULL;
        uint64_t oid = vid_to_data_oid(vid, idx);
        char name[SD_MAX_OBJECT_NAME];
-       int ret;
+       int ret = 0, len, i;
 
        ret = sd_read_object(oid, name, sizeof(name), 0);
        switch (ret) {
@@ -999,6 +1202,7 @@ static int do_kv_delete_object(struct http_request *req, 
const char *obj_name,
        }
 
        if (strcmp(name, obj_name) == 0) {
+               /* delete onode at first */
                memset(name, 0, sizeof(name));
                ret = sd_write_object(oid, name, sizeof(name), 0, false);
                if (ret == SD_RES_SUCCESS)
@@ -1007,21 +1211,48 @@ static int do_kv_delete_object(struct http_request 
*req, const char *obj_name,
                        sd_err("failed to update object, %" PRIx64,
                               oid);
                        http_response_header(req, INTERNAL_SERVER_ERROR);
-                       return -1;
+                       goto out;
+               }
+               /* then free data space */
+               onode = xmalloc(sizeof(struct kv_onode_hdr));
+               ret = sd_read_object(oid, (char *)onode,
+                                    sizeof(struct kv_onode_hdr), 0);
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("failed to read onode hdr %" PRIx64, oid);
+                       goto out;
+               }
+               len = sizeof(struct onode_extent) * onode->hdr.nr_extent;
+               ext = xmalloc(len);
+               ret = sd_read_object(oid, (char *)ext, len,
+                                    sizeof(struct kv_onode_hdr));
+               if (ret != SD_RES_SUCCESS) {
+                       sd_err("failed to read onode extent %" PRIx64, oid);
+                       goto out;
+               }
+               for (i = 0; i < onode->hdr.nr_extent; i++) {
+                       ret = oalloc_free(onode->hdr.data_vid, ext[i].start,
+                                         ext[i].count);
+                       if (ret != SD_RES_SUCCESS)
+                               sd_err("failed to free start %lu count %lu",
+                                      ext[i].start, ext[i].count);
                }
        }
-
-       return 0;
+out:
+       free(ext);
+       free(onode);
+       return ret;
 }
 
-int kv_delete_object(struct http_request *req, const char *bucket,
-                    const char *object)
+int kv_delete_object(struct http_request *req, const char *account,
+                    const char *bucket, const char *object)
 {
        int ret;
        uint64_t hval;
        uint32_t vid;
+       char vdi_name[SD_MAX_VDI_LEN];
 
-       ret = lookup_bucket(req, bucket, &vid);
+       snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+       ret = lookup_bucket(req, vdi_name, &vid);
        if (ret < 0)
                return ret;
 
@@ -1038,53 +1269,31 @@ int kv_delete_object(struct http_request *req, const 
char *bucket,
        return -1;
 }
 
-int kv_list_objects(struct http_request *req, const char *bucket,
-                   void (*cb)(struct http_request *req, const char *bucket,
-                              const char *object, void *opaque),
-                   void *opaque)
+int kv_list_objects(struct http_request *req, const char *account,
+                   const char *bucket, list_object_cb cb, void *opaque)
 {
        int ret;
        uint32_t vid;
-       struct sd_inode *inode;
+       struct sd_inode *inode = NULL;
+       char vdi_name[SD_MAX_VDI_LEN];
 
-       ret = lookup_bucket(req, bucket, &vid);
+       snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+       ret = lookup_bucket(req, vdi_name, &vid);
        if (ret < 0)
-               return ret;
+               goto out;
 
-       inode = xzalloc(sizeof(*inode));
-       ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode->data_vdi_id,
-                            sizeof(inode->data_vdi_id),
-                            offsetof(typeof(*inode), data_vdi_id));
+       inode = xmalloc(sizeof(*inode));
+       ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode,
+                         sizeof(struct sd_inode), 0);
        if (ret != SD_RES_SUCCESS) {
                sd_err("%s: bucket %s", sd_strerror(ret), bucket);
                http_response_header(req, INTERNAL_SERVER_ERROR);
-               return -1;
-       }
-
-       http_response_header(req, OK);
-
-       for (uint32_t idx = 0; idx < MAX_DATA_OBJS; idx++) {
-               uint64_t oid;
-               char name[SD_MAX_OBJECT_NAME];
-
-               if (inode->data_vdi_id[idx] == 0)
-                       continue;
-
-               oid = vid_to_data_oid(vid, idx);
-
-               ret = sd_read_object(oid, name, sizeof(name), 0);
-               switch (ret) {
-               case SD_RES_SUCCESS:
-                       if (name[0] != '\0')
-                               cb(req, bucket, name, opaque);
-                       break;
-               default:
-                       sd_err("%s: bucket %s", sd_strerror(ret), bucket);
-                       break;
-               }
+               goto out;
        }
 
+       struct list_objects_arg arg = {req, opaque, bucket, cb, 0};
+       traverse_btree(sheep_bnode_reader, inode, list_objects_cb, &arg);
+out:
        free(inode);
-
-       return 0;
+       return ret;
 }
diff --git a/sheep/http/kv.h b/sheep/http/kv.h
index 1774a36..4ccb716 100644
--- a/sheep/http/kv.h
+++ b/sheep/http/kv.h
@@ -38,15 +38,16 @@ int kv_list_buckets(struct http_request *req, const char 
*account,
                    void *opaque);
 
 /* Object operations */
-int kv_create_object(struct http_request *req, const char *bucket,
-                    const char *object);
-int kv_read_object(struct http_request *req, const char *bucket,
-                  const char *object);
+int kv_create_object(struct http_request *req, const char *account,
+                    const char *bucket, const char *object);
+int kv_read_object(struct http_request *req, const char *account,
+                  const char *bucket, const char *object);
 int kv_update_object(struct http_request *req, const char *bucket,
                     const char *object);
-int kv_delete_object(struct http_request *req, const char *bucket,
-                    const char *object);
-int kv_list_objects(struct http_request *req, const char *bucket,
+int kv_delete_object(struct http_request *req, const char *account,
+                    const char *bucket, const char *object);
+int kv_list_objects(struct http_request *req, const char *account,
+                   const char *bucket,
                    void (*cb)(struct http_request *req, const char *bucket,
                               const char *object, void *opaque),
                    void *opaque);
diff --git a/sheep/http/s3.c b/sheep/http/s3.c
index 8142bb5..8dde7f3 100644
--- a/sheep/http/s3.c
+++ b/sheep/http/s3.c
@@ -108,7 +108,7 @@ static void s3_get_bucket(struct http_request *req, const 
char *bucket)
 {
        bool print_header = true;
 
-       kv_list_objects(req, bucket, s3_get_bucket_cb, &print_header);
+       kv_list_objects(req, "s3", bucket, s3_get_bucket_cb, &print_header);
 
        switch (req->status) {
        case OK:
@@ -166,7 +166,7 @@ static void s3_head_object(struct http_request *req, const 
char *bucket,
 static void s3_get_object(struct http_request *req, const char *bucket,
                          const char *object)
 {
-       kv_read_object(req, bucket, object);
+       kv_read_object(req, "s3", bucket, object);
 
        if (req->status == NOT_FOUND)
                s3_write_err_response(req, "NoSuchKey",
@@ -176,7 +176,7 @@ static void s3_get_object(struct http_request *req, const 
char *bucket,
 static void s3_put_object(struct http_request *req, const char *bucket,
                          const char *object)
 {
-       kv_create_object(req, bucket, object);
+       kv_create_object(req, "s3", bucket, object);
 
        if (req->status == NOT_FOUND)
                s3_write_err_response(req, "NoSuchBucket",
@@ -192,7 +192,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(req, bucket, object);
+       kv_delete_object(req, "s3", bucket, object);
 
        if (req->status == NOT_FOUND)
                s3_write_err_response(req, "NoSuchKey",
diff --git a/sheep/http/swift.c b/sheep/http/swift.c
index 8b5024d..32a6c2b 100644
--- a/sheep/http/swift.c
+++ b/sheep/http/swift.c
@@ -25,14 +25,6 @@ static char tmp[4096];
 
 static void swift_delete_account(struct http_request *req, const char 
*account);
 
-static void make_bucket_path(char *bucket, size_t size, const char *account,
-                            const char *container)
-{
-       const char *args[] = { account, container };
-
-       make_path(bucket, size, ARRAY_SIZE(args), args);
-}
-
 /* Operations on Accounts */
 
 static void swift_head_account(struct http_request *req, const char *account)
@@ -141,10 +133,9 @@ static void swift_get_container_cb(struct http_request 
*req, const char *bucket,
 static void swift_get_container(struct http_request *req, const char *account,
                                const char *container)
 {
-       char bucket[SD_MAX_BUCKET_NAME];
-
-       make_bucket_path(bucket, sizeof(bucket), account, container);
-       kv_list_objects(req, bucket, swift_get_container_cb, NULL);
+       http_response_header(req, OK);
+       http_request_writes(req, "\n");
+       kv_list_objects(req, account, container, swift_get_container_cb, NULL);
 }
 
 static void swift_put_container(struct http_request *req, const char *account,
@@ -188,19 +179,13 @@ static void swift_head_object(struct http_request *req, 
const char *account,
 static void swift_get_object(struct http_request *req, const char *account,
                             const char *container, const char *object)
 {
-       char bucket[SD_MAX_BUCKET_NAME];
-
-       make_bucket_path(bucket, sizeof(bucket), account, container);
-       kv_read_object(req, bucket, object);
+       kv_read_object(req, account, container, object);
 }
 
 static void swift_put_object(struct http_request *req, const char *account,
                             const char *container, const char *object)
 {
-       char bucket[SD_MAX_BUCKET_NAME];
-
-       make_bucket_path(bucket, sizeof(bucket), account, container);
-       kv_create_object(req, bucket, object);
+       kv_create_object(req, account, container, object);
 }
 
 static void swift_post_object(struct http_request *req, const char *account,
@@ -212,10 +197,7 @@ static void swift_post_object(struct http_request *req, 
const char *account,
 static void swift_delete_object(struct http_request *req, const char *account,
                                const char *container, const char *object)
 {
-       char bucket[SD_MAX_BUCKET_NAME];
-
-       make_bucket_path(bucket, sizeof(bucket), account, container);
-       kv_delete_object(req, bucket, object);
+       kv_delete_object(req, account, container, object);
 }
 
 /* Swift driver interfaces */
-- 
1.7.12.4

-- 
sheepdog mailing list
sheepdog@lists.wpkg.org
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to