Rather than giving the ID provide a direct pointer to the object.
* persistent storage. */
void bluesky_serialize_superblock(GString *out, BlueSkyFS *fs);
BlueSkyFS *bluesky_deserialize_superblock(const gchar *buf);
-void bluesky_serialize_inode(GString *out, BlueSkyInode *inode);
+BlueSkyCloudLog *bluesky_serialize_inode(BlueSkyInode *inode);
gboolean bluesky_deserialize_inode(BlueSkyInode *inode, const gchar *buf);
/* Storage layer. Requests can be performed asynchronously, so these objects
// TODO: Location in journal/cache
int log_seq, log_offset, log_size;
- // Pointers to other objects
- GArray *pointers;
+ // Pointers to other objects. Each link counts towards the reference count
+ // of the pointed-to object. To avoid memory leaks there should be no
+ // cycles in the reference graph.
+ GArray *links;
// Serialized data, if available in memory (otherwise NULL), and a lock
// count which tracks if there are users that require the data to be kept
log->fs = fs;
log->type = LOGTYPE_UNKNOWN;
log->id = bluesky_cloudlog_new_id();
- log->pointers = g_array_new(FALSE, TRUE, sizeof(BlueSkyCloudID));
+ log->links = g_array_new(FALSE, TRUE, sizeof(BlueSkyCloudLog *));
g_atomic_int_set(&log->refcount, 1);
return log;
log->type = LOGTYPE_INVALID;
g_mutex_free(log->lock);
g_cond_free(log->cond);
- g_array_unref(log->pointers);
+ 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);
bluesky_string_unref(log->data);
g_free(log);
}
g_print("Flushing object %s to cloud...\n",
bluesky_cloudlog_id_to_string(log->id));
- for (int i = 0; i < log->pointers->len; i++) {
- BlueSkyCloudID id = g_array_index(log->pointers, BlueSkyCloudID, i);
- g_print(" ...checking reference %s...\n",
- bluesky_cloudlog_id_to_string(id));
- g_mutex_lock(log->fs->lock);
- BlueSkyCloudLog *log2
- = (BlueSkyCloudLog *)g_hash_table_lookup(log->fs->locations, &id);
- // TODO: refcount
- bluesky_cloudlog_fetch(log2);
- g_assert(log2 != NULL);
- bluesky_cloudlog_ref(log2);
- g_mutex_unlock(log->fs->lock);
- bluesky_cloudlog_serialize(log2, state);
- bluesky_cloudlog_unref(log2);
+ for (int i = 0; i < log->links->len; i++) {
+ BlueSkyCloudLog *ref = g_array_index(log->links,
+ BlueSkyCloudLog *, i);
+ if (ref != NULL)
+ bluesky_cloudlog_serialize(ref, state);
}
g_mutex_lock(log->lock);
void bluesky_inode_start_sync(BlueSkyInode *inode)
{
GList *log_items = NULL;
- BlueSkyFS *fs = inode->fs;
if (inode->type == BLUESKY_REGULAR)
bluesky_file_flush(inode, &log_items);
- GString *buf = g_string_new("");
- bluesky_serialize_inode(buf, inode);
-
- char key[64];
- sprintf(key, "inode-%016"PRIx64, inode->inum);
-
- BlueSkyCloudLog *cloudlog = bluesky_cloudlog_new(fs);
- cloudlog->type = LOGTYPE_INODE;
- cloudlog->inum = inode->inum;
- cloudlog->data = bluesky_string_new_from_gstring(buf);
-
- if (inode->type == BLUESKY_REGULAR) {
- for (int i = 0; i < inode->blocks->len; i++) {
- BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock, i);
- if (b->type == BLUESKY_BLOCK_REF) {
- BlueSkyCloudID id = b->ref->id;
- g_array_append_val(cloudlog->pointers, id);
- }
- }
- }
+ BlueSkyCloudLog *cloudlog = bluesky_serialize_inode(inode);
bluesky_cloudlog_unref(inode->committed_item);
inode->committed_item = cloudlog;
bluesky_cloudlog_sync(cloudlog);
bluesky_cloudlog_ref(cloudlog);
log_items = g_list_prepend(log_items, cloudlog);
- bluesky_cloudlog_insert(cloudlog);
/* Wait for all log items to be committed to disk. */
bluesky_log_finish_all(log_items);
return fs;
}
-void bluesky_serialize_inode(GString *out, BlueSkyInode *inode)
+BlueSkyCloudLog *bluesky_serialize_inode(BlueSkyInode *inode)
{
+ BlueSkyFS *fs = inode->fs;
+ GString *out = g_string_new("");
struct serialized_inode buf;
+ BlueSkyCloudLog *cloudlog = bluesky_cloudlog_new(fs);
+ cloudlog->type = LOGTYPE_INODE;
+ cloudlog->inum = inode->inum;
+
buf.signature = GUINT64_TO_LE(INODE_MAGIC);
buf.type = GUINT32_TO_LE(inode->type);
buf.mode = GUINT32_TO_LE(inode->mode);
g_string_append_len(out, (gchar *)&size, sizeof(uint64_t));
for (int i = 0; i < inode->blocks->len; i++) {
BlueSkyBlock *b = &g_array_index(inode->blocks, BlueSkyBlock, i);
- BlueSkyCloudID id;
- memset(&id, 0, sizeof(id));
- if (b->ref != NULL)
- id = b->ref->id;
- g_string_append_len(out, (const char *)&id, sizeof(id));
+ BlueSkyCloudLog *ref = NULL;
+ if (b->type == BLUESKY_BLOCK_REF)
+ ref = b->ref;
+ bluesky_cloudlog_ref(ref);
+ g_array_append_val(cloudlog->links, ref);
}
break;
}
g_warning("Serialization for inode type %d not implemented!\n",
inode->type);
}
+
+ cloudlog->data = bluesky_string_new_from_gstring(out);
+ bluesky_cloudlog_insert(cloudlog);
+
+ return cloudlog;
}
/* Deserialize an inode into an in-memory representation. Returns a boolean