From: Liu Yuan <namei.u...@gmail.com> Also add Robin and myself to the contributor list of this file
Reviewed-by: Hitoshi Mitake <mitake.hito...@lab.ntt.co.jp> Reviewed-by: Robin Dong <san...@taobao.com> Signed-off-by: Liu Yuan <namei.u...@gmail.com> --- sheep/http/kv.c | 101 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/sheep/http/kv.c b/sheep/http/kv.c index ab8241a..d94608a 100644 --- a/sheep/http/kv.c +++ b/sheep/http/kv.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2013 MORITA Kazutaka <morita.kazut...@gmail.com> + * Copyright (C) 2013 Robin Dong <san...@taobao.com> + * Copyright (C) 2013 Liu Yuan <namei.u...@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -919,11 +921,57 @@ out: return ret; } +static int vdi_read_write(uint32_t vid, char *data, size_t length, + off_t offset, bool read) +{ + struct sd_req hdr; + uint32_t idx = offset / SD_DATA_OBJ_SIZE; + uint64_t done = 0; + struct request_iocb *iocb; + int ret; + + iocb = local_req_init(); + if (!iocb) + return SD_RES_SYSTEM_ERROR; + + offset %= SD_DATA_OBJ_SIZE; + while (done < length) { + size_t len = min(length - done, SD_DATA_OBJ_SIZE - offset); + + if (read) { + sd_init_req(&hdr, SD_OP_READ_OBJ); + } else { + sd_init_req(&hdr, SD_OP_CREATE_AND_WRITE_OBJ); + hdr.flags = SD_FLAG_CMD_WRITE; + } + hdr.data_length = len; + hdr.obj.oid = vid_to_data_oid(vid, idx); + hdr.obj.offset = offset; + + ret = exec_local_req_async(&hdr, data, iocb); + if (ret != SD_RES_SUCCESS) + sd_err("failed to write object %" PRIx64 ", %s", + hdr.obj.oid, sd_strerror(ret)); + + offset += len; + if (offset == SD_DATA_OBJ_SIZE) { + offset = 0; + idx++; + } + done += len; + data += len; + } + + return local_req_wait(iocb); +} + +#define READ_WRITE_BUFFER (SD_DATA_OBJ_SIZE * 25) /* no rationale */ + static int kv_create_extent_onode(struct http_request *req, uint32_t data_vid, struct kv_onode *onode, ssize_t *total_size) { ssize_t size; - uint64_t start = 0, count, limit, block; + uint64_t start = 0, count, done = 0, total, offset; int ret; char *data_buf = NULL; @@ -931,6 +979,7 @@ static int kv_create_extent_onode(struct http_request *req, uint32_t data_vid, sys->cdrv->lock(data_vid); ret = oalloc_new_prepare(data_vid, &start, count); sys->cdrv->unlock(data_vid); + sd_debug("start: %lu, count: %lu", start, count); if (ret != SD_RES_SUCCESS) { sd_err("Failed to prepare allocation of %lu bytes!", req->data_length); @@ -939,24 +988,23 @@ static int kv_create_extent_onode(struct http_request *req, uint32_t data_vid, } /* 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); + data_buf = xmalloc(READ_WRITE_BUFFER); + offset = start * SD_DATA_OBJ_SIZE; + total = req->data_length; + while (done < total) { + size = http_request_read(req, data_buf, READ_WRITE_BUFFER); + ret = vdi_read_write(data_vid, data_buf, size, offset, false); 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; + done += size; + offset += size; } + *total_size = done; + sd_debug("DATA_LENGTH: %lu, total size: %lu, last blocks: %lu", req->data_length, *total_size, start); @@ -975,6 +1023,7 @@ static int kv_create_extent_onode(struct http_request *req, uint32_t data_vid, onode->o_extent[0].count = count; onode->hdr.nr_extent = 1; out: + free(data_buf); return ret; } @@ -1075,32 +1124,30 @@ 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; + uint64_t size, total, total_size, offset, done = 0; uint32_t i; int ret; char *data_buf = NULL; - data_buf = xmalloc(SD_DATA_OBJ_SIZE); - + data_buf = xmalloc(READ_WRITE_BUFFER); 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); + ext = onode->o_extent + i; + total = min(ext->count * SD_DATA_OBJ_SIZE, total_size); + offset = ext->start * SD_DATA_OBJ_SIZE; + while (done < total) { + size = MIN(total - done, READ_WRITE_BUFFER); + ret = vdi_read_write(onode->hdr.data_vid, data_buf, + size, offset, true); if (ret != SD_RES_SUCCESS) { - sd_err("Failed to read oid %lx", oid); + sd_err("Failed to read for vid %"PRIx32, + onode->hdr.data_vid); goto out; } http_request_write(req, data_buf, size); + done += size; + offset += size; total_size -= size; - sd_debug("read extented block %lu, size %lu", - block, size); } } out: -- 1.7.10.4 -- sheepdog mailing list sheepdog@lists.wpkg.org http://lists.wpkg.org/mailman/listinfo/sheepdog