[sheepdog] [PATCH 2/2] sheep/http: optimize read/write object by using async request

Liu Yuan namei.unix at gmail.com
Mon Dec 16 14:16:39 CET 2013


Also add Robin and myself to the contributor list of this file

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 sheep/http/kv.c |  102 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 75 insertions(+), 27 deletions(-)

diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index c578716..8dc4db8 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2013 MORITA Kazutaka <morita.kazutaka at gmail.com>
+ * Copyright (C) 2013 Robin Dong <sanbai at taobao.com>
+ * Copyright (C) 2013 Liu Yuan <namei.unix at 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,31 @@ 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);
+			sd_err("%ld", size);
+			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.9.5




More information about the sheepdog mailing list