entry->inum = inum;
g_sequence_insert_sorted(range->map_entries, entry, compare, NULL);
- g_print("Created inode map entry for %"PRIu64"\n", inum);
+ if (bluesky_verbose)
+ g_print("Created inode map entry for %"PRIu64"\n", inum);
}
if (action != 0) {
- bluesky_cloudlog_unref(range->serialized);
+ bluesky_cloudlog_unref_delayed(range->serialized);
range->serialized = NULL;
}
InodeMapEntry *entry = (InodeMapEntry *)g_sequence_get(i);
uint64_t inum = GUINT64_TO_LE(entry->inum);
g_string_append_len(buf, (const char *)&inum, sizeof(inum));
+ bluesky_cloudlog_ref(entry->item);
g_array_append_val(log->links, entry->item);
i = g_sequence_iter_next(i);
}
log->data = bluesky_string_new_from_gstring(buf);
bluesky_cloudlog_unref(range->serialized);
range->serialized = log;
+ bluesky_cloudlog_stats_update(log, 1);
}
BlueSkyCloudLog *bluesky_inode_map_serialize(BlueSkyFS *fs)
{
+ gboolean updated = FALSE;
GString *buf = g_string_new("");
BlueSkyCloudLog *log = bluesky_cloudlog_new(fs, NULL);
log->type = LOGTYPE_CHECKPOINT;
inum = GUINT64_TO_LE(range->end);
g_string_append_len(buf, (const char *)&inum, sizeof(inum));
- if (range->serialized == NULL)
+ if (range->serialized == NULL) {
bluesky_inode_map_serialize_section(fs, range);
+ updated = TRUE;
+ }
bluesky_cloudlog_ref(range->serialized);
g_array_append_val(log->links, range->serialized);
i = g_sequence_iter_next(i);
}
log->data = bluesky_string_new_from_gstring(buf);
- return log;
+ bluesky_cloudlog_stats_update(log, 1);
+
+ if (updated) {
+ return log;
+ } else {
+ bluesky_cloudlog_unref(log);
+ return NULL;
+ }
+}
+
+/* Minimize resources consumed the inode map. This should only be called once
+ * an updated inode map has been serialized to the cloud, and will replace
+ * cloud log objects with skeletal versions that just reference the data
+ * location in the cloud (rather than pinning all object data in memory). */
+void bluesky_inode_map_minimize(BlueSkyFS *fs)
+{
+ GSequenceIter *i = g_sequence_get_begin_iter(fs->inode_map);
+ while (!g_sequence_iter_is_end(i)) {
+ InodeMapRange *range = (InodeMapRange *)g_sequence_get(i);
+
+ if (range->serialized != NULL)
+ bluesky_cloudlog_erase(range->serialized);
+
+ GSequenceIter *j;
+ for (j = g_sequence_get_begin_iter(range->map_entries);
+ !g_sequence_iter_is_end(j); j = g_sequence_iter_next(j))
+ {
+ InodeMapEntry *entry = (InodeMapEntry *)g_sequence_get(j);
+ BlueSkyCloudLog *item = entry->item;
+ if (item != NULL) {
+ g_mutex_lock(item->lock);
+ if (g_atomic_int_get(&item->refcount) == 1) {
+ bluesky_cloudlog_erase(item);
+ }
+ g_mutex_unlock(item->lock);
+ } else {
+ g_warning("Null item for inode map entry %"PRIu64"!",
+ entry->inum);
+ }
+ }
+
+ i = g_sequence_iter_next(i);
+ }
}
/* Reconstruct the inode map from data stored in the cloud. */
for (int j = 0; j < section->links->len; j++) {
InodeMapEntry *entry;
entry = bluesky_inode_map_lookup(fs->inode_map, *inum, 1);
- entry->inum = *inum;
+ entry->inum = GUINT64_FROM_LE(*inum);
+ bluesky_cloudlog_unref_delayed(entry->item);
entry->item = g_array_index(section->links,
BlueSkyCloudLog *, j);
bluesky_cloudlog_ref(entry->item);
- entry->id = entry->item->id;
- entry->location = entry->item->location;
+ fs->next_inum = MAX(fs->next_inum, entry->inum + 1);
inum++;
}
g_mutex_unlock(section->lock);
return FALSE;
}
+ last = bluesky_string_dup(last);
+ bluesky_cloudlog_decrypt(last->data, last->len, fs->keys);
+
/* 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
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);
commit->location.offset = checkpoint - last->data;
commit->location.size = checkpoint_size;
g_mutex_unlock(commit->lock);
+ bluesky_cloudlog_stats_update(commit, 1);
bluesky_inode_map_deserialize(fs, commit);
- //bluesky_cloudlog_unref(commit);
+ bluesky_cloudlog_unref(commit);
return TRUE;
}