From: Liu Yuan <[email protected]>

For storing one object into backend store, either

a) no content change, then point to the same old sha1_file (no stale object)
or
b) content updated, then will point to a new object with a new sha1.

So we need to remove stale object in case b), only in the assumption it is the
object generated by recovery code. [*]

When we try store new snapshot object into the backend store, it is safe and
good timing for us to remove the old object with the same object ID.

[*] Here I assume we don't need to restore to 'sys epoch' state.

Signed-off-by: Liu Yuan <[email protected]>
---
 sheep/farm/trunk.c |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 133 insertions(+), 3 deletions(-)

diff --git a/sheep/farm/trunk.c b/sheep/farm/trunk.c
index ec36081..fd0a525 100644
--- a/sheep/farm/trunk.c
+++ b/sheep/farm/trunk.c
@@ -1,5 +1,7 @@
 #include <pthread.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "farm.h"
 #include "strbuf.h"
@@ -19,6 +21,11 @@ static struct hlist_head trunk_hashtable[HASH_SIZE];
 static pthread_mutex_t hashtable_lock[HASH_SIZE] = { [0 ... HASH_SIZE - 1] = 
PTHREAD_MUTEX_INITIALIZER };
 static unsigned int trunk_entry_active_nr;
 
+struct omap_entry {
+       uint64_t oid;
+       unsigned char sha1[SHA1_LEN];
+};
+
 static inline int trunk_entry_is_dirty(struct __trunk_entry *entry)
 {
        return entry->flags & TRUNK_ENTRY_DIRTY;
@@ -78,6 +85,27 @@ out:
        return entry;
 }
 
+static int create_files(void)
+{
+       int fd, ret = 0;
+       struct strbuf buf = STRBUF_INIT;
+
+       strbuf_addstr(&buf, farm_dir);
+       strbuf_addf(&buf, "/%s", "obj_map");
+
+       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 trunk_init(void)
 {
        DIR *dir;
@@ -96,6 +124,10 @@ int trunk_init(void)
                        continue;
                lookup_trunk_entry(oid, 1);
        }
+
+       if (create_files() < 0)
+               return -1;
+
        closedir(dir);
        return 0;
 }
@@ -148,9 +180,92 @@ static void put_entry(struct __trunk_entry *entry)
        trunk_entry_active_nr--;
 }
 
+
+static int omap_file_init(struct strbuf *outbuf)
+{
+       int fd;
+       int len = -1;
+       void *buffer = NULL;
+       struct strbuf buf = STRBUF_INIT;
+       struct stat st;
+
+       strbuf_addf(&buf, "%s/%s", farm_dir, "obj_map");
+       fd = open(buf.buf, O_RDONLY);
+       if (fd < 0)
+               goto out;
+
+        if (fstat(fd, &st) < 0) {
+                dprintf("%m\n");
+                goto out_close;
+        }
+
+        len = st.st_size;
+       if (len == 0)
+               goto out_close;
+
+        buffer = xmalloc(len);
+        len = xread(fd, buffer, len);
+        if (len != st.st_size) {
+               len = -1;
+                goto out_close;
+        }
+       strbuf_add(outbuf, buffer, len); 
+out_close:
+       close(fd);
+out:
+       strbuf_release(&buf);
+        free(buffer);
+       return len;
+}
+
+static int omap_file_final(struct strbuf *omap_buf)
+{
+        int fd, ret = -1;
+        struct strbuf buf = STRBUF_INIT;
+
+       if (omap_buf->len == 0)
+               return 0;
+
+       strbuf_addf(&buf, "%s/%s", farm_dir, "obj_map");
+        fd = open(buf.buf, O_WRONLY);
+        if (fd < 0) {
+                dprintf("%m\n");
+                goto out;
+        }
+
+        ret = xwrite(fd, omap_buf->buf, omap_buf->len);
+        if (ret != omap_buf->len)
+                ret = -1;
+
+        close(fd);
+out:
+        strbuf_release(&buf);
+        return ret;
+}
+
+static struct omap_entry *omap_file_insert(struct strbuf *buf, struct 
omap_entry *new)
+{
+       unsigned i, nr = buf->len / sizeof(struct omap_entry);
+       struct omap_entry *omap_buf = (struct omap_entry *)buf->buf;
+       for (i = 0; i < nr; i++, omap_buf++)
+               if (omap_buf->oid == new->oid) {
+                       if (memcmp(omap_buf->sha1, new->sha1, SHA1_LEN) == 0)
+                               return NULL;
+                       else {
+                               struct omap_entry *old = xmalloc(sizeof(*old));
+                               memcpy(old, omap_buf, sizeof(*old));
+                               memcpy(omap_buf->sha1, new->sha1, SHA1_LEN);
+                               return old;
+                       }
+               }
+       dprintf("oid, %"PRIx64"\n", new->oid);
+       strbuf_add(buf, new, sizeof(*new));
+       return NULL;
+}
+
 int trunk_file_write(unsigned char *outsha1, int user)
 {
-       struct strbuf buf;
+       struct strbuf buf, omap_buf = STRBUF_INIT;
        uint64_t data_size = sizeof(struct trunk_entry) * trunk_entry_active_nr;
        struct sha1_file_hdr hdr = { .size = data_size,
                                     .priv = trunk_entry_active_nr };
@@ -159,18 +274,32 @@ int trunk_file_write(unsigned char *outsha1, int user)
 
        memcpy(hdr.tag, TAG_TRUNK, TAG_LEN);
        strbuf_init(&buf, sizeof(hdr) + data_size);
+       omap_file_init(&omap_buf);
 
        strbuf_add(&buf, &hdr, sizeof(hdr));
        list_for_each_entry_safe(entry, t, &trunk_active_list, active_list) {
-               if (trunk_entry_no_sha1(entry) || trunk_entry_is_dirty(entry)) {
+               if (trunk_entry_no_sha1(entry) || trunk_entry_is_dirty(entry))
                        if (fill_entry_new_sha1(entry) < 0) {
                                ret = -1;
                                goto out;
                        }
-               }
                strbuf_add(&buf, &entry->raw, sizeof(struct trunk_entry));
+               if (!user) {
+                       struct omap_entry new = { .oid = entry->raw.oid }, *old;
+                       memcpy(new.sha1, entry->raw.sha1, SHA1_LEN);
+                       old = omap_file_insert(&omap_buf, &new);
+                       if (old) {
+                               dprintf("try delete stale %s, oid %"PRIx64"\n",
+                                       sha1_to_hex(old->sha1), old->oid);
+                               sha1_file_delete(old->sha1);
+                               free(old);
+                       }
+               }
                put_entry(entry);
        }
+       if (omap_file_final(&omap_buf) < 0)
+               eprintf("omap_file_final failed\n");
+
        if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) {
                ret = -1;
                goto out;
@@ -178,6 +307,7 @@ int trunk_file_write(unsigned char *outsha1, int user)
        dprintf("trunk sha1: %s\n", sha1_to_hex(outsha1));
 out:
        strbuf_release(&buf);
+       strbuf_release(&omap_buf);
        return ret;
 }
 
-- 
1.7.8.rc3

-- 
sheepdog mailing list
[email protected]
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to