From bf5f9f2e43078f7d31858be259b9c60a8c08a096 Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 5 Aug 2010 09:38:20 -0700 Subject: [PATCH] Make links between cloud log entries direct. Rather than giving the ID provide a direct pointer to the object. --- bluesky/bluesky-private.h | 8 +++++--- bluesky/cloudlog.c | 28 ++++++++++++---------------- bluesky/inode.c | 23 +---------------------- bluesky/serialize.c | 23 +++++++++++++++++------ 4 files changed, 35 insertions(+), 47 deletions(-) diff --git a/bluesky/bluesky-private.h b/bluesky/bluesky-private.h index 418c1e5..1560c83 100644 --- a/bluesky/bluesky-private.h +++ b/bluesky/bluesky-private.h @@ -44,7 +44,7 @@ BlueSkyInode *bluesky_list_tail(GList *head); * 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 @@ -207,8 +207,10 @@ struct _BlueSkyCloudLog { // 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 diff --git a/bluesky/cloudlog.c b/bluesky/cloudlog.c index 6b80233..30c2db0 100644 --- a/bluesky/cloudlog.c +++ b/bluesky/cloudlog.c @@ -91,7 +91,7 @@ BlueSkyCloudLog *bluesky_cloudlog_new(BlueSkyFS *fs) 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; @@ -135,7 +135,12 @@ void bluesky_cloudlog_unref(BlueSkyCloudLog *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); } @@ -183,20 +188,11 @@ BlueSkyCloudPointer bluesky_cloudlog_serialize(BlueSkyCloudLog *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); diff --git a/bluesky/inode.c b/bluesky/inode.c index a76b4b9..993be73 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -292,31 +292,11 @@ void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode) 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; @@ -324,7 +304,6 @@ void bluesky_inode_start_sync(BlueSkyInode *inode) 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); diff --git a/bluesky/serialize.c b/bluesky/serialize.c index a9e4182..da9aa97 100644 --- a/bluesky/serialize.c +++ b/bluesky/serialize.c @@ -67,10 +67,16 @@ BlueSkyFS *bluesky_deserialize_superblock(const gchar *buf) 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); @@ -93,11 +99,11 @@ void bluesky_serialize_inode(GString *out, BlueSkyInode *inode) 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; } @@ -138,6 +144,11 @@ void bluesky_serialize_inode(GString *out, BlueSkyInode *inode) 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 -- 2.20.1