[sheepdog] [PATCH v1 1/2] sheepfs/http: read next cache if data of current cache has been read out

Robin Dong robin.k.dong at gmail.com
Fri Mar 21 06:13:58 CET 2014


From: Robin Dong <sanbai at taobao.com>

When we use command 'tar' to extract a tar-file in http interface of sheepfs,
it report error and quit. The reason is that if a read operation has almost
reach the end of current cache, it will only return the size which has not
been read in CURRENT CACHE at present.
For example, if a read operation want to read 1MB and it already reach the
offset of (63MB + 500K) in current cache, the read() will return 524K even
the file has more data to read. The tool of 'tar' read 10KB every time, so if
its read() return size below 10KB, it will think the file is end and quit
which cause problems.

The solution is simple: if current cache has almost been read out, try to
read data of next cache.

Signed-off-by: Robin Dong <sanbai at taobao.com>
---
 sheepfs/http.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/sheepfs/http.c b/sheepfs/http.c
index 630129c..3732db3 100644
--- a/sheepfs/http.c
+++ b/sheepfs/http.c
@@ -324,6 +324,15 @@ static void *fetch_thread_run(void *arg)
 	return NULL;
 }
 
+static int object_wait_cache(struct cache_handle *ch)
+{
+	sem_wait(&ch->ready_sem);
+	swap_cache(ch);
+	ch->fetch_offset = ch->ready->offset + ch->ready->size;
+	sem_post(&ch->prepare_sem);
+	return  ch->ready->size;
+}
+
 int object_read(const char *path, char *buf, size_t size, off_t offset,
 		struct fuse_file_info *fi)
 {
@@ -351,19 +360,24 @@ int object_read(const char *path, char *buf, size_t size, off_t offset,
 			else
 				ret = (cache->offset + cache->size) - offset;
 			memcpy(buf, cache->mem + (offset - cache->offset), ret);
+			/* read next cache if not fulfill the 'size' */
+			if (ret < size && object_wait_cache(ch) > 0) {
+				int extra_read;
+				buf += ret;
+				offset += ret;
+				cache = ch->ready;
+				extra_read = min(cache->size, size - ret);
+				memcpy(buf, cache->mem +
+				       (offset - cache->offset), extra_read);
+				ret += extra_read;
+			}
 			break;
 		} else if (offset >= ch->obj_size) {
 			ret = 0;
 			break;
-		} else {
-			sem_wait(&ch->ready_sem);
-			swap_cache(ch);
-			ch->fetch_offset = ch->ready->offset + ch->ready->size;
-			sem_post(&ch->prepare_sem);
-			if (ch->ready->size == 0) {
-				ret = 0;
-				break;
-			}
+		} else if (!object_wait_cache(ch)) {
+			ret = 0;
+			break;
 		}
 	}
 out:
-- 
1.7.12.4




More information about the sheepdog mailing list