[epiphany/wip/ephy-sync: 116/126] sync-bookmarks: Fix merge_locals_with_remotes() function



commit 8347ec9124a4aaf1191975987345f10fb1e3f1c4
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Tue Aug 9 18:50:23 2016 +0300

    sync-bookmarks: Fix merge_locals_with_remotes() function
    
    The purpose of this function is to merge the currently existing
    bookmarks on the local instance with the remote bookmarks existing
    on the Storage Server. It only represents the first step of the sync
    process and should be called exactly once, right after the user signs
    in. The further logic of the periodical sync will be provided by other
    functions.

 src/ephy-sync-bookmarks.c |  164 ++++++++++++++++++++++++++-------------------
 1 files changed, 94 insertions(+), 70 deletions(-)
---
diff --git a/src/ephy-sync-bookmarks.c b/src/ephy-sync-bookmarks.c
index 80f9680..1ec0b94 100644
--- a/src/ephy-sync-bookmarks.c
+++ b/src/ephy-sync-bookmarks.c
@@ -144,6 +144,8 @@ upload_bookmark_to_server_response_cb (SoupSession *session,
     ephy_bookmark_set_modified (bookmark, last_modified);
     manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
     ephy_bookmarks_manager_save_to_file_async (manager, NULL, NULL, NULL);
+
+    LOG ("Successfully uploaded bookmark to server.");
   } else if (message->status_code == 412) {
     /* FIXME: A more recent value is on the server. See how to handle this. */
   } else {
@@ -190,25 +192,32 @@ merge_locals_with_remotes_response_cb (SoupSession *session,
   GSequence *bookmarks;
   JsonParser *parser;
   JsonArray *array;
-  GHashTable *bookmarks_to_upload;
-  GHashTableIter ht_iter;
-  gpointer key;
+  GList *remotes = NULL;
+  GList *locals = NULL;
+  gboolean *marked_locals = NULL;
+  gboolean *marked_remotes = NULL;
+  gsize i;
 
   manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
   bookmarks = ephy_bookmarks_manager_get_bookmarks (manager);
-  bookmarks_to_upload = g_hash_table_new (g_direct_hash, g_direct_equal);
   parser = json_parser_new ();
   json_parser_load_from_data (parser, message->response_body->data, -1, NULL);
   array = json_node_get_array (json_parser_get_root (parser));
 
+  /* Convert all BSOs to EphyBookmark objects. */
+  for (i = 0; i < json_array_get_length (array); i++) {
+    JsonObject *bso = json_array_get_object_element (array, i);
+    EphyBookmark *bookmark = ephy_bookmark_from_bso (bso);
+    remotes = g_list_append (remotes, bookmark);
+  }
+
   /* If we have no remote bookmarks, then we directly upload all the local
    * bookmarks to the server.
    */
-  if (json_array_get_length (array) == 0) {
+  if (g_list_length (remotes) == 0) {
     for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
-         !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter)) {
+         !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter))
       ephy_sync_bookmarks_upload_bookmark_to_server (g_sequence_get (iter), TRUE);
-    }
     goto out;
   }
 
@@ -216,84 +225,99 @@ merge_locals_with_remotes_response_cb (SoupSession *session,
    * local instance.
    */
   if (g_sequence_is_empty (bookmarks) == TRUE) {
-    for (gsize i = 0; i < json_array_get_length (array); i++) {
-      JsonObject *bso = json_array_get_object_element (array, i);
-      EphyBookmark *bookmark = ephy_bookmark_from_bso (bso);
-
-      ephy_bookmarks_manager_add_bookmark (manager, bookmark);
-    }
+    for (GList *r = remotes; r != NULL; r = r->next)
+      ephy_bookmarks_manager_add_bookmark (manager, EPHY_BOOKMARK (r->data));
     goto out;
   }
 
   /* If we have both local and remote bookmarks, then we merge them in the
-   * nicest way possible (see the three cases below).
+   * nicest way possible (see the two cases below).
    */
-  for (gsize i = 0; i < json_array_get_length (array); i++) {
-    JsonObject *bso = json_array_get_object_element (array, i);
-    EphyBookmark *remote = ephy_bookmark_from_bso (bso);
-    const gchar *remote_id = ephy_bookmark_get_id (remote);
-    double remote_modified = ephy_bookmark_get_modified (remote);
-    const gchar *remote_url = ephy_bookmark_get_url (remote);
+  for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
+       !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter))
+    locals = g_list_append (locals, g_sequence_get (iter));
+
+  marked_locals = g_malloc0 (g_list_length (locals) * sizeof (gboolean));
+  marked_remotes = g_malloc0 (g_list_length (remotes) * sizeof (gboolean));
+
+  i = 0;
+  for (GList *l = locals; l != NULL; l = l->next, i++) {
+    EphyBookmark *local = EPHY_BOOKMARK (l->data);
+    const gchar *local_id = ephy_bookmark_get_id (local);
+    double local_modified = ephy_bookmark_get_modified (local);
+    const gchar *local_url = ephy_bookmark_get_url (local);
+    gsize j = 0;
+
+    for (GList *r = remotes; r != NULL; r = r->next, j++) {
+      if (marked_remotes[j] == FALSE) {
+        EphyBookmark *remote = EPHY_BOOKMARK (r->data);
+        const gchar *remote_id = ephy_bookmark_get_id (remote);
+        double remote_modified = ephy_bookmark_get_modified (remote);
+        const gchar *remote_url = ephy_bookmark_get_url (remote);
+
+        /* Case 1: same ids.
+         * Since ids are globally unique, having a bookmark on the server with
+         * the same id means that the bookmark has been synced before in the
+         * past. Keep the one with most recent modified timestamp.
+         */
+        if (g_strcmp0 (local_id, remote_id) == 0) {
+          if (local_modified > remote_modified) {
+            ephy_sync_bookmarks_upload_bookmark_to_server (local, TRUE);
+          } else if (remote_modified > local_modified) {
+            ephy_bookmarks_manager_remove_bookmark (manager, local);
+            ephy_bookmarks_manager_add_bookmark (manager, remote);
+          } else {
+            g_object_unref (remote);
+          }
+          marked_locals[i] = marked_remotes[j] = TRUE;
+          break;
+        }
 
-    for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
-         !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter)) {
-      EphyBookmark *local = g_sequence_get (iter);
-      const gchar *local_id = ephy_bookmark_get_id (local);
-      double local_modified = ephy_bookmark_get_modified (local);
-      const gchar *local_url = ephy_bookmark_get_url (local);
-
-      /* Case 1: same ids.
-       * Since ids are globally unique, having a bookmark on the server with the
-       * same id means that the bookmark has been synced before in the past.
-       * Keep the one with most recent modified timestamp.
-       */
-      if (g_strcmp0 (remote_id, local_id) == 0) {
-        if (remote_modified > local_modified) {
-          ephy_bookmarks_manager_remove_bookmark (manager, local);
-          ephy_bookmarks_manager_add_bookmark (manager, remote);
-        } else if (local_modified > remote_modified) {
+        /* Case 2: different ids, same urls.
+         * Merge tags into the local bookmark, keep the remote id and upload it
+         * to server. The add_tag functions will ignore the duplicates themselves.
+         */
+        if (g_strcmp0 (local_url, remote_url) == 0) {
+          GSequence *tags = ephy_bookmark_get_tags (remote);
+
+          for (GSequenceIter *it = g_sequence_get_begin_iter (tags);
+               !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) {
+            const gchar *tag = g_sequence_get (it);
+            ephy_bookmark_add_tag (local, tag);
+            ephy_bookmarks_manager_add_tag (manager, tag);
+          }
+
+          ephy_bookmark_set_id (local, remote_id);
           ephy_sync_bookmarks_upload_bookmark_to_server (local, TRUE);
+          g_object_unref (remote);
+          marked_locals[i] = marked_remotes[j] = TRUE;
+          break;
         }
       }
-      /* Case 2: different ids, same urls.
-       * Merge tags into the local bookmark, keep the remote id and upload it
-       * to server.
-       */
-      else if (g_strcmp0 (remote_url, local_url) == 0) {
-        GSequence *tags = ephy_bookmark_get_tags (remote);
-
-        for (GSequenceIter *it = g_sequence_get_begin_iter (tags);
-             !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) {
-          const gchar *tag = g_sequence_get (it);
-
-          /* The *_add_tag functions will handle the duplicates for us. */
-          ephy_bookmark_add_tag (local, tag);
-          ephy_bookmarks_manager_add_tag (manager, tag);
-        }
-
-        ephy_bookmark_set_id (local, remote_id);
-        ephy_sync_bookmarks_upload_bookmark_to_server (local, TRUE);
-        g_object_unref (remote);
-      }
-      /* Case 3: different ids, different urls.
-       * These are two different bookmarks. Add the remote one to the local
-       * instance and mark the local one to be later uploaded to the server.
-       */
-      else {
-        g_hash_table_add (bookmarks_to_upload, local);
-        ephy_bookmarks_manager_add_bookmark (manager, remote);
-      }
     }
   }
 
-  /* Send to the server the local bookmarks that have been marked for upload. */
-  g_hash_table_iter_init (&ht_iter, bookmarks_to_upload);
-  while (g_hash_table_iter_next (&ht_iter, &key, NULL) == TRUE)
-    ephy_sync_bookmarks_upload_bookmark_to_server (EPHY_BOOKMARK (key), TRUE);
+  /* The remaining unmarked local bookmarks will be directly uploaded to the server. */
+  i = 0;
+  for (GList *l = locals; l != NULL; l = l->next, i++)
+    if (marked_locals[i] == FALSE)
+      ephy_sync_bookmarks_upload_bookmark_to_server (EPHY_BOOKMARK (l->data), TRUE);
+
+  /* The remaining unmarked remote bookmarks will be added to the local instance. */
+  i = 0;
+  for (GList *r = remotes; r != NULL; r = r->next, i++)
+    if (marked_remotes[i] == FALSE)
+      ephy_bookmarks_manager_add_bookmark (manager, EPHY_BOOKMARK (r->data));
+
+  /* Save changes to file. */
+  ephy_bookmarks_manager_save_to_file_async (manager, NULL, NULL, NULL);
 
 out:
   g_object_unref (parser);
-  g_hash_table_unref (bookmarks_to_upload);
+  g_list_free (locals);
+  g_list_free (remotes);
+  g_free (marked_locals);
+  g_free (marked_remotes);
   service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
   ephy_sync_service_release_next_storage_message (service);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]