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