Cleaner fix part 1
[bluesky.git] / bluesky / imap.c
index 1b9feb8..c50691e 100644 (file)
 
 #include "bluesky-private.h"
 
+/* Magic number at the start of the checkpoint record, to check for version
+ * mismatches. */
+#define CHECKPOINT_MAGIC 0x7ad7dafb42a498b4ULL
+
 /* Inode maps.  There is both an in-memory representation as well as the
  * serialized form in the cloud.
  *
@@ -165,6 +169,21 @@ BlueSkyCloudLog *bluesky_inode_map_serialize(BlueSkyFS *fs)
     log->type = LOGTYPE_CHECKPOINT;
     log->inum = 0;
 
+    /* The checkpoint record starts with a magic number, followed by the
+     * version vector which lists the latest sequence number of all other logs
+     * (currently, only the cleaner) which have been seen. */
+    uint64_t magic = GUINT64_TO_LE(CHECKPOINT_MAGIC);
+    g_string_append_len(buf, (const char *)&magic, sizeof(magic));
+    uint32_t versions;
+    versions = GUINT32_TO_LE(fs->log_state->latest_cleaner_seq_seen >= 0);
+    g_string_append_len(buf, (const char *)&versions, sizeof(versions));
+    if (fs->log_state->latest_cleaner_seq_seen >= 0) {
+        versions = GUINT32_TO_LE(BLUESKY_CLOUD_DIR_CLEANER);
+        g_string_append_len(buf, (const char *)&versions, sizeof(versions));
+        versions = GUINT32_TO_LE(fs->log_state->latest_cleaner_seq_seen);
+        g_string_append_len(buf, (const char *)&versions, sizeof(versions));
+    }
+
     GSequenceIter *i = g_sequence_get_begin_iter(fs->inode_map);
     while (!g_sequence_iter_is_end(i)) {
         InodeMapRange *range = (InodeMapRange *)g_sequence_get(i);
@@ -234,7 +253,30 @@ static void bluesky_inode_map_deserialize(BlueSkyFS *fs, BlueSkyCloudLog *imap)
     g_mutex_lock(imap->lock);
     bluesky_cloudlog_fetch(imap);
     g_assert(imap->data != NULL);
-    g_assert(imap->data->len == 16 * imap->links->len);
+    g_assert(imap->data->len >= 12);
+    uint64_t magic;
+    uint32_t vector_data;
+    memcpy((char *)&magic, imap->data->data, sizeof(magic));
+    g_assert(GUINT64_FROM_LE(magic) == CHECKPOINT_MAGIC);
+    memcpy((char *)&vector_data, imap->data->data + 8, sizeof(vector_data));
+    g_assert(GUINT32_FROM_LE(vector_data) <= 2);
+
+    int vector_size = GUINT32_FROM_LE(vector_data);
+    g_assert(imap->data->len == 16 * imap->links->len + 12 + 8 * vector_size);
+
+    for (int i = 0; i < vector_size; i++) {
+        memcpy((char *)&vector_data, imap->data->data + 12 + 8*i,
+               sizeof(vector_data));
+        if (GUINT32_FROM_LE(vector_data) == 1) {
+            memcpy((char *)&vector_data, imap->data->data + 16 + 8*i,
+                   sizeof(vector_data));
+            fs->log_state->latest_cleaner_seq_seen
+                = GUINT32_FROM_LE(vector_data);
+            g_print("Deserializing checkpoint: last cleaner sequence is %d\n",
+                    GUINT32_FROM_LE(vector_data));
+        }
+    }
+
     //uint64_t *inum_range = (uint64_t *)imap->data->data;
     for (int i = 0; i < imap->links->len; i++) {
         //int64_t start = GUINT64_FROM_LE(*inum_range++);
@@ -267,7 +309,12 @@ static void bluesky_inode_map_deserialize(BlueSkyFS *fs, BlueSkyCloudLog *imap)
  * whether a checkpoint was found and loaded or not. */
 gboolean bluesky_checkpoint_load(BlueSkyFS *fs)
 {
-    char *last_segment = bluesky_store_lookup_last(fs->store, "log-");
+    g_print("Claiming cloud log directory: %d\n",
+            fs->log_state->location.directory);
+    char *prefix = g_strdup_printf("log-%08d",
+                                   fs->log_state->location.directory);
+    char *last_segment = bluesky_store_lookup_last(fs->store, prefix);
+    g_free(prefix);
     if (last_segment == NULL)
         return FALSE;
 
@@ -283,7 +330,7 @@ gboolean bluesky_checkpoint_load(BlueSkyFS *fs)
     }
 
     last = bluesky_string_dup(last);
-    bluesky_cloudlog_decrypt(last->data, last->len, fs->keys);
+    bluesky_cloudlog_decrypt(last->data, last->len, fs->keys, NULL, FALSE);
 
     /* Scan through the contents of the last log segment to find a checkpoint
      * record.  We need to do a linear scan since at this point we don't have a