Make links between cloud log entries direct.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 5 Aug 2010 16:38:20 +0000 (09:38 -0700)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Thu, 5 Aug 2010 16:38:20 +0000 (09:38 -0700)
Rather than giving the ID provide a direct pointer to the object.

bluesky/bluesky-private.h
bluesky/cloudlog.c
bluesky/inode.c
bluesky/serialize.c

index 418c1e5..1560c83 100644 (file)
@@ -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
index 6b80233..30c2db0 100644 (file)
@@ -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);
index a76b4b9..993be73 100644 (file)
@@ -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);
index a9e4182..da9aa97 100644 (file)
@@ -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