+
+/* Find the most recent checkpoint record in the cloud and reload inode map
+ * data from it to initialize the filesystem. Returns a boolean indicating
+ * 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-");
+ if (last_segment == NULL)
+ return FALSE;
+
+ g_print("Last cloud log segment: %s\n", last_segment);
+ int seq = atoi(last_segment + 13);
+ fs->log_state->location.sequence = seq + 1;
+
+ BlueSkyRCStr *last = bluesky_store_get(fs->store, last_segment);
+ g_free(last_segment);
+ if (last == NULL) {
+ g_warning("Unable to fetch last log segment from cloud!");
+ return 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
+ * direct pointer; once we have the last commit record then all other data
+ * can be loaded by directly following pointers. */
+ const char *buf = last->data;
+ size_t len = last->len;
+ const char *checkpoint = NULL;
+ size_t checkpoint_size = 0;
+ while (len > sizeof(struct cloudlog_header)) {
+ struct cloudlog_header *header = (struct cloudlog_header *)buf;
+ if (memcmp(header->magic, CLOUDLOG_MAGIC, 4) != 0) {
+ g_warning("Could not parse cloudlog entry!");
+ break;
+ }
+ int size = sizeof(struct cloudlog_header);
+ size += GUINT32_FROM_LE(header->size1);
+ size += GUINT32_FROM_LE(header->size2);
+ size += GUINT32_FROM_LE(header->size3);
+ if (size > len) {
+ g_warning("Cloudlog entry is malformed (size too large)!");
+ break;
+ }
+ if (header->type - '0' == LOGTYPE_CHECKPOINT) {
+ checkpoint = buf;
+ checkpoint_size = size;
+ }
+ buf += size;
+ len -= size;
+ }
+
+ g_print("Found checkpoint record at %zd (size %zd)\n",
+ checkpoint - last->data, checkpoint_size);
+
+ /* Bootstrap the loading process by manually setting the location of this
+ * log item. */
+ BlueSkyCloudLog *commit;
+ commit = bluesky_cloudlog_get(fs,
+ ((struct cloudlog_header *)checkpoint)->id);
+ g_mutex_lock(commit->lock);
+ commit->location_flags |= CLOUDLOG_CLOUD;
+ commit->location.directory = 0;
+ commit->location.sequence = seq;
+ commit->location.offset = checkpoint - last->data;
+ commit->location.size = checkpoint_size;
+ g_mutex_unlock(commit->lock);
+
+ bluesky_inode_map_deserialize(fs, commit);
+ //bluesky_cloudlog_unref(commit);
+
+ return TRUE;
+}