[sheepdog] [PATCH v1 2/4] sheep/http: change routine of kv_create_object()
Robin Dong
robin.k.dong at gmail.com
Fri Feb 21 07:47:31 CET 2014
From: Robin Dong <sanbai at taobao.com>
Change routine of kv_create_object(): create onode and alloc space first,
then recveive data from fastcgi of http, and write it.
Signed-off-by: Robin Dong <sanbai at taobao.com>
---
sheep/http/kv.c | 170 +++++++++++++++++++++++++++++++++++---------------------
1 file changed, 108 insertions(+), 62 deletions(-)
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index 4ac69fc..037df66 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -62,6 +62,9 @@ struct bucket_iterater_arg {
uint64_t bytes_used;
};
+static int kv_delete_object_nolock(const char *account, const char *bucket,
+ const char *name);
+
/* Account operations */
/*
@@ -646,15 +649,12 @@ static int vdi_read_write(uint32_t vid, char *data, size_t length,
return local_req_wait(iocb);
}
-static int onode_populate_extents(struct kv_onode *onode,
+static int onode_allocate_extents(struct kv_onode *onode,
struct http_request *req)
{
- ssize_t size;
- uint64_t start = 0, count, done = 0, total, offset;
+ uint64_t start = 0, count;
int ret;
- char *data_buf = NULL;
uint32_t data_vid = onode->data_vid;
- uint64_t write_buffer_size = MIN(kv_rw_buffer, req->data_length);
count = DIV_ROUND_UP(req->data_length, SD_DATA_OBJ_SIZE);
sys->cdrv->lock(data_vid);
@@ -666,6 +666,36 @@ static int onode_populate_extents(struct kv_onode *onode,
goto out;
}
+ sys->cdrv->lock(data_vid);
+ ret = oalloc_new_finish(data_vid, start, count);
+ sys->cdrv->unlock(data_vid);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("oalloc_new_finish failed for %s, %s", onode->name,
+ sd_strerror(ret));
+ goto out;
+ }
+
+ onode->o_extent[0].start = start;
+ onode->o_extent[0].count = count;
+ onode->nr_extent = 1;
+out:
+ return ret;
+}
+
+static int onode_populate_extents(struct kv_onode *onode,
+ struct http_request *req)
+{
+ ssize_t size;
+ uint64_t start = onode->o_extent[0].start;
+ uint64_t count = onode->o_extent[0].count;
+ uint64_t done = 0, total, offset;
+ uint64_t write_buffer_size = MIN(kv_rw_buffer, req->data_length);
+ int ret;
+ char *data_buf = NULL;
+ uint32_t data_vid = onode->data_vid;
+
+ count = DIV_ROUND_UP(req->data_length, SD_DATA_OBJ_SIZE);
+
data_buf = xmalloc(write_buffer_size);
offset = start * SD_DATA_OBJ_SIZE;
total = req->data_length;
@@ -673,9 +703,6 @@ static int onode_populate_extents(struct kv_onode *onode,
size = http_request_read(req, data_buf, write_buffer_size);
if (size <= 0) {
sd_err("Failed to read http request: %ld", size);
- sys->cdrv->lock(data_vid);
- oalloc_free(data_vid, start, count);
- sys->cdrv->unlock(data_vid);
ret = SD_RES_EIO;
goto out;
}
@@ -683,27 +710,11 @@ static int onode_populate_extents(struct kv_onode *onode,
if (ret != SD_RES_SUCCESS) {
sd_err("Failed to write data object for %s, %s",
onode->name, sd_strerror(ret));
- sys->cdrv->lock(data_vid);
- oalloc_free(data_vid, start, count);
- sys->cdrv->unlock(data_vid);
goto out;
}
done += size;
offset += size;
}
-
- sys->cdrv->lock(data_vid);
- ret = oalloc_new_finish(data_vid, start, count);
- sys->cdrv->unlock(data_vid);
- if (ret != SD_RES_SUCCESS) {
- sd_err("oalloc_new_finish failed for %s, %s", onode->name,
- sd_strerror(ret));
- goto out;
- }
-
- onode->o_extent[0].start = start;
- onode->o_extent[0].count = count;
- onode->nr_extent = 1;
out:
free(data_buf);
return ret;
@@ -719,13 +730,30 @@ static uint64_t get_seconds(void)
return seconds;
}
+static int onode_allocate_data(struct kv_onode *onode, struct http_request *req)
+{
+ int ret = SD_RES_SUCCESS;
+
+ if (req->data_length <= KV_ONODE_INLINE_SIZE)
+ onode->inlined = 1;
+ else {
+ ret = onode_allocate_extents(onode, req);
+ if (ret != SD_RES_SUCCESS)
+ goto out;
+ }
+
+ onode->mtime = get_seconds();
+ onode->size = req->data_length;
+out:
+ return ret;
+}
+
static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
{
ssize_t size;
int ret = SD_RES_SUCCESS;
if (req->data_length <= KV_ONODE_INLINE_SIZE) {
- onode->inlined = 1;
size = http_request_read(req, onode->data, sizeof(onode->data));
if (size < 0 || req->data_length != size) {
sd_err("Failed to read from web server for %s",
@@ -733,14 +761,15 @@ static int onode_populate_data(struct kv_onode *onode, struct http_request *req)
ret = SD_RES_SYSTEM_ERROR;
goto out;
}
+ ret = sd_write_object(onode->oid, (char *)onode,
+ BLOCK_SIZE + size, 0, false);
+ if (ret != SD_RES_SUCCESS)
+ goto out;
} else {
ret = onode_populate_extents(onode, req);
if (ret != SD_RES_SUCCESS)
goto out;
}
-
- onode->mtime = get_seconds();
- onode->size = req->data_length;
out:
return ret;
}
@@ -824,17 +853,6 @@ out:
return ret;
}
-static int onode_create(struct kv_onode *onode, uint32_t bucket_vid)
-{
- int ret;
-
- sys->cdrv->lock(bucket_vid);
- ret = onode_create_nolock(onode, bucket_vid);
- sys->cdrv->unlock(bucket_vid);
-
- return ret;
-}
-
static int onode_free_data(struct kv_onode *onode, int lock)
{
uint32_t data_vid = onode->data_vid;
@@ -863,6 +881,7 @@ static int onode_read_extents(struct kv_onode *onode, struct http_request *req)
char *data_buf = NULL;
uint64_t read_buffer_size = MIN(kv_rw_buffer, onode->size);
+ sd_err("req->len: %"PRIu64, len);
data_buf = xmalloc(read_buffer_size);
total_size = len;
for (i = 0; i < onode->nr_extent; i++) {
@@ -880,8 +899,8 @@ static int onode_read_extents(struct kv_onode *onode, struct http_request *req)
size = MIN(total - done, read_buffer_size);
ret = vdi_read_write(onode->data_vid, data_buf,
size, offset, true);
- sd_debug("vdi_read_write size: %"PRIx64", offset: %"
- PRIx64, size, offset);
+ sd_debug("vdi_read_write size: %"PRIu64", offset: %"
+ PRIu64", ret:%d", size, offset, ret);
if (ret != SD_RES_SUCCESS) {
sd_err("Failed to read for vid %"PRIx32,
onode->data_vid);
@@ -1029,30 +1048,20 @@ static int onode_delete(struct kv_onode *onode, int lock)
return SD_RES_SUCCESS;
}
-/*
- * user object name -> struct kv_onode -> sheepdog objects -> user data
- *
- * onode is a index node that maps name to sheepdog objects which hold the user
- * data, similar to UNIX inode. We use simple hashing for [name, onode] mapping.
- */
-int kv_create_object(struct http_request *req, const char *account,
- const char *bucket, const char *name)
+/* Create onode and allocate space for it */
+static int onode_create_for_space(struct http_request *req, const char *account,
+ uint32_t bucket_vid, const char *bucket,
+ const char *name, struct kv_onode *onode)
{
char vdi_name[SD_MAX_VDI_LEN];
- struct kv_onode *onode;
- uint32_t bucket_vid, data_vid;
- int ret;
-
- snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
- ret = sd_lookup_vdi(vdi_name, &bucket_vid);
- if (ret != SD_RES_SUCCESS)
- return ret;
+ uint32_t data_vid;
+ int ret = SD_RES_SUCCESS;
- onode = xzalloc(sizeof(*onode));
- ret = onode_lookup(onode, bucket_vid, name);
+ sys->cdrv->lock(bucket_vid);
+ ret = onode_lookup_nolock(onode, bucket_vid, name);
if (ret == SD_RES_SUCCESS) {
/* For overwrite, we delete old object and then create */
- ret = kv_delete_object(account, bucket, name);
+ ret = kv_delete_object_nolock(account, bucket, name);
if (ret != SD_RES_SUCCESS) {
sd_err("Failed to delete exists object %s", name);
goto out;
@@ -1069,13 +1078,13 @@ int kv_create_object(struct http_request *req, const char *account,
pstrcpy(onode->name, sizeof(onode->name), name);
onode->data_vid = data_vid;
- ret = onode_populate_data(onode, req);
+ ret = onode_allocate_data(onode, req);
if (ret != SD_RES_SUCCESS) {
sd_err("failed to write data for %s", name);
goto out;
}
- ret = onode_create(onode, bucket_vid);
+ ret = onode_create_nolock(onode, bucket_vid);
if (ret != SD_RES_SUCCESS) {
sd_err("failed to create onode for %s", name);
onode_free_data(onode, 1);
@@ -1089,6 +1098,43 @@ int kv_create_object(struct http_request *req, const char *account,
goto out;
}
out:
+ sys->cdrv->unlock(bucket_vid);
+ return ret;
+}
+
+/*
+ * user object name -> struct kv_onode -> sheepdog objects -> user data
+ *
+ * onode is a index node that maps name to sheepdog objects which hold the user
+ * data, similar to UNIX inode. We use simple hashing for [name, onode] mapping.
+ */
+int kv_create_object(struct http_request *req, const char *account,
+ const char *bucket, const char *name)
+{
+ char vdi_name[SD_MAX_VDI_LEN];
+ struct kv_onode *onode = NULL;
+ uint32_t bucket_vid;
+ int ret;
+
+ snprintf(vdi_name, SD_MAX_VDI_LEN, "%s/%s", account, bucket);
+ ret = sd_lookup_vdi(vdi_name, &bucket_vid);
+ if (ret != SD_RES_SUCCESS)
+ goto out;
+
+ onode = xzalloc(sizeof(*onode));
+ ret = onode_create_for_space(req, account, bucket_vid, bucket,
+ name, onode);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("Failed to create onode and allocate space %s", name);
+ goto out;
+ }
+
+ ret = onode_populate_data(onode, req);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("Failed to write data to onode %s", name);
+ goto out;
+ }
+out:
free(onode);
return ret;
}
--
1.7.12.4
More information about the sheepdog
mailing list