X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fimap.c;h=c50691e4a343c6001db77aeae95103a407f361e9;hb=388030970805a70cb4fad34ade5e3de7a3607a57;hp=9b5f8e3aeb94362ceb0b83dfab59e5ed674e4469;hpb=4536000021cb67fb248317392336f69c7c045754;p=bluesky.git diff --git a/bluesky/imap.c b/bluesky/imap.c index 9b5f8e3..c50691e 100644 --- a/bluesky/imap.c +++ b/bluesky/imap.c @@ -15,6 +15,10 @@ #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 @@ -315,6 +362,10 @@ gboolean bluesky_checkpoint_load(BlueSkyFS *fs) len -= size; } + if (checkpoint_size == 0) { + g_error("Unable to locate checkpoint record!\n"); + } + g_print("Found checkpoint record at %zd (size %zd)\n", checkpoint - last->data, checkpoint_size);