[sheepdog] [PATCH] test patch: try compress before write to disk

Liu Yuan namei.unix at gmail.com
Tue Jul 16 11:30:22 CEST 2013


Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 collie/Makefile.am      |    2 +-
 collie/farm/sha1_file.c |   85 +++++++++++++++++++++++++++++++++++------------
 2 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/collie/Makefile.am b/collie/Makefile.am
index 2b45b53..b520c1a 100644
--- a/collie/Makefile.am
+++ b/collie/Makefile.am
@@ -32,7 +32,7 @@ collie_SOURCES          += debug.c
 override CFLAGS         := $(subst -pg -gstabs,,$(CFLAGS))
 endif
 
-collie_LDADD		= ../lib/libsheepdog.a -lpthread
+collie_LDADD		= ../lib/libsheepdog.a -lpthread -lz
 collie_DEPENDENCIES	= ../lib/libsheepdog.a
 
 noinst_HEADERS		= treeview.h collie.h farm/farm.h
diff --git a/collie/farm/sha1_file.c b/collie/farm/sha1_file.c
index dc134a4..3739abf 100644
--- a/collie/farm/sha1_file.c
+++ b/collie/farm/sha1_file.c
@@ -24,9 +24,11 @@
  */
 #include <sys/types.h>
 #include <sys/xattr.h>
+#include <sys/mman.h>
 
 #include "farm.h"
 #include "util.h"
+#include <zlib.h>
 
 static void get_buffer_sha1(void *buf, size_t len, unsigned char *sha1)
 {
@@ -149,8 +151,26 @@ bool sha1_file_exist(const unsigned char *sha1)
 int sha1_file_write(void *buf, size_t len, unsigned char *outsha1)
 {
 	unsigned char sha1[SHA1_DIGEST_SIZE];
+	unsigned char *compressed;
+	z_stream stream;
+	int size;
+
+	memset(&stream, 0, sizeof(stream));
+	deflateInit(&stream, Z_BEST_COMPRESSION);
+	size = deflateBound(&stream, len);
+	compressed = xmalloc(size);
+
+	stream.next_in = buf;
+	stream.avail_in = len;
+	stream.next_out = compressed;
+	stream.avail_out = size;
+	while (deflate(&stream, Z_FINISH) == Z_OK)
+		/* nothing */;
+	deflateEnd(&stream);
+	size = stream.total_out;
+
+	get_buffer_sha1(compressed, size, sha1);
 
-	get_buffer_sha1(buf, len, sha1);
 	if (sha1_buffer_write(sha1, buf, len) < 0)
 		return -1;
 	if (outsha1)
@@ -171,44 +191,65 @@ static int verify_sha1_file(const unsigned char *sha1, void *buf, size_t len)
 	return 0;
 }
 
-void *sha1_file_read(const unsigned char *sha1, size_t *size)
+static void *map_sha1_file(const unsigned char *sha1, size_t *size)
 {
 	char *filename = sha1_to_path(sha1);
 	int fd = open(filename, O_RDONLY);
 	struct stat st;
-	void *buf = NULL;
+	void *map;
 
 	if (fd < 0) {
 		perror(filename);
 		return NULL;
 	}
 	if (fstat(fd, &st) < 0) {
-		fprintf(stderr, "%m\n");
-		goto out;
+		close(fd);
+		return NULL;
 	}
+	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	close(fd);
+	if (map == MAP_FAILED)
+		return NULL;
+	*size = st.st_size;
+	return map;
+}
 
-	buf = xmalloc(st.st_size);
-	if (!buf)
-		goto out;
-
-	if (xread(fd, buf, st.st_size) != st.st_size) {
-		free(buf);
-		buf = NULL;
-		goto out;
-	}
+static void *unpack_sha1_file(void *map, unsigned long mapsize, size_t *size)
+{
+	z_stream stream;
+	unsigned char buffer[512*1024];
+	char *buf;
 
-	if (verify_sha1_file(sha1, buf, st.st_size) < 0) {
-		free(buf);
-		buf = NULL;
-		goto out;
-	}
+	memset(&stream, 0, sizeof(stream));
+	stream.next_in = map;
+	stream.avail_in = mapsize;
+	stream.next_out = buffer;
+	stream.avail_out = sizeof(buffer);
 
-	*size = st.st_size;
-out:
-	close(fd);
+	inflateInit(&stream);
+	while (inflate(&stream, Z_FINISH) == Z_OK)
+		/* do nothing */;
+	*size = stream.total_out;
+	buf = xmalloc(*size);
+	memcpy(buf, buffer, *size);
+	inflateEnd(&stream);
 	return buf;
 }
 
+void *sha1_file_read(const unsigned char *sha1, size_t *size)
+{
+	unsigned long mapsize;
+	void *map, *buf;
+
+	map = map_sha1_file(sha1, &mapsize);
+	if (!map)
+		return NULL;
+	if (verify_sha1_file(sha1, map, mapsize) < 0)
+		return NULL;
+	buf = unpack_sha1_file(map, mapsize, size);
+	munmap(map, mapsize);
+	return buf;
+}
 int sha1_file_try_delete(const unsigned char *sha1)
 {
 	char *filename = sha1_to_path(sha1);
-- 
1.7.9.5




More information about the sheepdog mailing list