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 |