[Sheepdog] [PATCH v3 06/12] farm: add snapshot object

Liu Yuan namei.unix at gmail.com
Fri Dec 23 15:39:24 CET 2011


From: Liu Yuan <tailai.ly at taobao.com>

snap object is the meta data that describe the snapshot.

todo:
 - add more description.

Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheep/farm.h      |   13 +++++
 sheep/farm/snap.c |  152 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 0 deletions(-)
 create mode 100644 sheep/farm/snap.c

diff --git a/sheep/farm.h b/sheep/farm.h
index d808e3c..726ee4c 100644
--- a/sheep/farm.h
+++ b/sheep/farm.h
@@ -48,6 +48,12 @@ struct __trunk_entry {
 	struct hlist_node hash;
 };
 
+struct snap_log {
+	int epoch;
+	uint64_t time;
+	unsigned char sha1[SHA1_LEN];
+};
+
 extern char *epoch_path;
 
 /* sha1_file.c */
@@ -63,4 +69,11 @@ extern int trunk_file_write(unsigned char *outsha1);
 extern void *trunk_file_read(unsigned char *sha1, struct sha1_file_hdr *);
 extern int trunk_update_entry(uint64_t oid);
 
+/* snap.c */
+extern int snap_init(void);
+extern void *snap_file_read(unsigned char *sha1, struct sha1_file_hdr *outhdr);
+extern int snap_file_write(int epoch, unsigned char *outsha1, int user);
+extern void *snap_log_read(int *, int user);
+extern int snap_log_write(int epoch, unsigned char *sha1, int user);
+
 #endif
diff --git a/sheep/farm/snap.c b/sheep/farm/snap.c
new file mode 100644
index 0000000..e3de585
--- /dev/null
+++ b/sheep/farm/snap.c
@@ -0,0 +1,152 @@
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "farm.h"
+#include "sheep_priv.h"
+
+int snap_init(void)
+{
+	int fd, ret = 0;
+	struct strbuf buf = STRBUF_INIT;
+
+	strbuf_addstr(&buf, farm_dir);
+	strbuf_addf(&buf, "/%s", "sys_snap");
+
+	fd = open(buf.buf, O_CREAT | O_EXCL, 0666);
+	if (fd < 0) {
+		if (errno != EEXIST) {
+			ret = -1;
+			goto out;
+		}
+	}
+	close(fd);
+	
+	strbuf_reset(&buf);
+	strbuf_addstr(&buf, farm_dir);
+	strbuf_addf(&buf, "/%s", "user_snap");
+
+	fd = open(buf.buf, O_CREAT | O_EXCL, 0666);
+	if (fd < 0) {
+		if (errno != EEXIST) {
+			ret = -1;
+			goto out;
+		}
+	}
+	close(fd);
+
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
+int snap_log_write(int epoch, unsigned char *sha1, int user)
+{
+	int fd, ret = -1;
+	struct strbuf buf = STRBUF_INIT;
+	struct snap_log log = { .epoch = epoch,
+				.time = time(NULL) };
+
+	memcpy(log.sha1, sha1, SHA1_LEN);
+	strbuf_addstr(&buf, farm_dir);
+	strbuf_addf(&buf, "/%s", user ? "user_snap" : "sys_snap");
+
+	fd = open(buf.buf, O_WRONLY | O_APPEND);
+	if (fd < 0) {
+		dprintf("%m\n");
+		goto out;
+	}
+
+	strbuf_reset(&buf);
+	strbuf_add(&buf, &log, sizeof(log));
+	ret = xwrite(fd, buf.buf, buf.len);
+	if (ret != buf.len)
+		ret = -1;
+
+	close(fd);
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
+void *snap_log_read(int *out_nr, int user)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct stat st;
+	void *buffer = NULL;
+	int len, fd;
+
+	strbuf_addstr(&buf, farm_dir);
+	strbuf_addf(&buf, "/%s", user ? "user_snap" : "sys_snap");
+	
+	fd = open(buf.buf, O_RDONLY);
+	if (fd < 0) {
+		dprintf("%m\n");
+		goto out;
+	}
+	if (fstat(fd, &st) < 0) {
+		dprintf("%m\n");
+		goto out_close;
+	}
+	
+	len = st.st_size;
+	buffer = xmalloc(len);
+	len = xread(fd, buffer, len);
+	if (len != st.st_size) {
+		free(buffer);
+		buffer = NULL;
+		goto out_close;
+	}
+	*out_nr = len / sizeof(struct snap_log);
+out_close:
+	close(fd);
+out:
+	strbuf_release(&buf);
+	return buffer;
+}
+
+void *snap_file_read(unsigned char *sha1, struct sha1_file_hdr *outhdr)
+{
+	void *buffer = NULL;
+
+	dprintf("%s\n", sha1_to_hex(sha1));
+	buffer = sha1_file_read(sha1, outhdr);
+	if (!buffer)
+		return NULL;
+	if (strcmp(outhdr->tag, TAG_SNAP) != 0) {
+		free(buffer);
+		return NULL;
+	}
+
+	return buffer;
+}
+
+int snap_file_write(int epoch, unsigned char *outsha1, int user)
+{
+	int ret = 0;
+	struct strbuf buf = STRBUF_INIT;
+	struct sd_node nodes[SD_MAX_NODES];
+	int tgt_epoch = user ? sys->epoch : epoch;
+	uint64_t epoch_size = epoch_log_read(tgt_epoch, (char *)nodes, sizeof(nodes));
+	unsigned char trunk[SHA1_LEN];
+	struct sha1_file_hdr hdr = { .size = epoch_size + SHA1_LEN,
+				     .priv = tgt_epoch };
+	memcpy(hdr.tag, TAG_SNAP, TAG_LEN);
+
+	if (trunk_file_write(trunk) < 0) {
+		ret =  -1;
+		goto err;
+	}
+	strbuf_add(&buf, &hdr, sizeof(hdr));
+	strbuf_add(&buf, trunk, SHA1_LEN);
+	strbuf_add(&buf, (char *)nodes, epoch_size);
+	if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) {
+		ret = -1;
+		goto err;
+	}
+
+	dprintf("epoch %u, sha1: %s\n", epoch, sha1_to_hex(outsha1));
+err:
+	strbuf_release(&buf);
+	return ret;
+}
-- 
1.7.8.rc3




More information about the sheepdog mailing list