BlueSkyCloudID bluesky_cloudlog_id_from_string(const gchar *idstr);
void bluesky_cloudlog_ref(BlueSkyCloudLog *log);
void bluesky_cloudlog_unref(BlueSkyCloudLog *log);
+void bluesky_cloudlog_erase(BlueSkyCloudLog *log);
void bluesky_cloudlog_stats_update(BlueSkyCloudLog *log, int type);
void bluesky_cloudlog_sync(BlueSkyCloudLog *log);
void bluesky_cloudlog_insert(BlueSkyCloudLog *log);
+void bluesky_cloudlog_insert_locked(BlueSkyCloudLog *log);
BlueSkyCloudLog *bluesky_cloudlog_get(BlueSkyFS *fs, BlueSkyCloudID id);
void bluesky_cloudlog_fetch(BlueSkyCloudLog *log);
BlueSkyCloudPointer bluesky_cloudlog_serialize(BlueSkyCloudLog *log,
* cloud. When the write completes, we will allow old journal segments (those
* that were fully written _before_ the snapshot process started) to be garbage
* collected. Newer journal segments can't be collected yet since they may
- * still contain data which has not been written persistently to the cloud. */
+ * still contain data which has not been written persistently to the cloud.
+ *
+ * Note that some of this code relies on the fact that only this thread of
+ * control (running flushd_cloud) is manipulating the inode map, and so
+ * concurrent updates to the inode map are prevented even without the
+ * filesystem lock held. Take great care if allowing multi-threaded access to
+ * the inode map... */
static void flushd_cloud(BlueSkyFS *fs)
{
g_mutex_lock(fs->lock);
g_mutex_lock(fs->lock);
}
+ g_mutex_unlock(fs->lock);
/* Write out any updated inode map entries, so that all inodes just written
* can be located, and then a final commit record. */
BlueSkyCloudLog *commit_record = bluesky_inode_map_serialize(fs);
- bluesky_cloudlog_serialize(commit_record, fs);
+ if (commit_record != NULL) {
+ bluesky_cloudlog_serialize(commit_record, fs);
+ } else {
+ g_print("No need for a checkpoint record...\n");
+ }
- g_mutex_unlock(fs->lock);
bluesky_cloudlog_flush(fs);
/* Wait until all segments have been written to the cloud, so that it
}
bluesky_log_write_commit_point(fs, marker);
+ bluesky_cloudlog_unref(commit_record);
g_print("All segments have been flushed, journal < %d is clean\n",
journal_seq_start);
}
}
+/* Erase the information contained within the in-memory cloud log
+ * representation. This does not free up the item itself, but frees the data
+ * and references to other log items and resets the type back to unknown. If
+ * the object was written out to persistent storage, all state about it can be
+ * recovered by loading the object back in. The object must be locked before
+ * calling this function. */
+void bluesky_cloudlog_erase(BlueSkyCloudLog *log)
+{
+ g_assert(log->data_lock_count == 0);
+
+ log->type = LOGTYPE_UNKNOWN;
+ log->data_size = 0;
+ bluesky_string_unref(log->data);
+ log->data = NULL;
+ log->data_lock_count = 0;
+
+ for (int i = 0; i < log->links->len; i++) {
+ BlueSkyCloudLog *c = g_array_index(log->links,
+ BlueSkyCloudLog *, i);
+ bluesky_cloudlog_unref(c);
+ }
+ g_array_unref(log->links);
+ log->links = g_array_new(FALSE, TRUE, sizeof(BlueSkyCloudLog *));
+}
+
/* Start a write of the object to the local log. */
void bluesky_cloudlog_sync(BlueSkyCloudLog *log)
{
/* Add the given entry to the global hash table containing cloud log entries.
* Takes ownership of the caller's reference. */
+void bluesky_cloudlog_insert_locked(BlueSkyCloudLog *log)
+{
+ g_hash_table_insert(log->fs->locations, &log->id, log);
+}
+
void bluesky_cloudlog_insert(BlueSkyCloudLog *log)
{
g_mutex_lock(log->fs->lock);
- g_hash_table_insert(log->fs->locations, &log->id, log);
+ bluesky_cloudlog_insert(log);
g_mutex_unlock(log->fs->lock);
}
log->location.size = state->data->len - log->location.offset;
+ g_string_free(data1, TRUE);
+ g_string_free(data2, TRUE);
+ g_string_free(data3, TRUE);
+
/* If the object we flushed was an inode, update the inode map. */
if (log->type == LOGTYPE_INODE) {
g_mutex_lock(fs->lock);
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;
+
+ if (updated) {
+ return log;
+ } else {
+ bluesky_cloudlog_unref(log);
+ return NULL;
+ }
}
/* Reconstruct the inode map from data stored in the cloud. */