[gom] gom: Don't do get/set properties in != main thread when saving



commit b14e7044bf5cbfe4b6baac4b3ce66dba7dc8f458
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Nov 4 13:33:17 2014 +0100

    gom: Don't do get/set properties in != main thread when saving
    
    Avoid manipulating properties from within a thread other than the
    main thread when saving. This breaks Javascript and Python bindings.
    
    Note, reading from the database is likely still broken though.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=728301

 gom/gom-resource.c |  120 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 96 insertions(+), 24 deletions(-)
---
diff --git a/gom/gom-resource.c b/gom/gom-resource.c
index 21e4456..4680918 100644
--- a/gom/gom-resource.c
+++ b/gom/gom-resource.c
@@ -544,22 +544,48 @@ has_primary_key (GomResource *resource)
    return ret;
 }
 
-static gboolean
-gom_resource_do_save (GomResource  *resource,
-                      GomAdapter   *adapter,
-                      GError      **error)
+static void
+set_post_save_properties (GomResource *resource)
+{
+   GValue *value;
+
+   gom_resource_set_is_from_table(resource,
+                                  GPOINTER_TO_INT(g_object_get_data(G_OBJECT(resource), "is-from-table")));
+   g_object_set_data (G_OBJECT(resource), "is-from-table", NULL);
+
+   value = g_object_get_data(G_OBJECT(resource), "row-id");
+   if (!value)
+      return;
+   set_pkey(resource, value);
+   g_object_set_data(G_OBJECT(resource), "row-id", NULL);
+}
+
+static void
+free_save_cmds (gpointer data)
+{
+   GList *cmds = data;
+
+   g_list_free_full (cmds, g_object_unref);
+}
+
+static void
+value_free (gpointer data)
+{
+   GValue *value = data;
+   g_value_unset (value);
+   g_free (value);
+}
+
+static void
+gom_resource_build_save_cmd (GomResource *resource,
+                             GomAdapter  *adapter)
 {
    GomCommandBuilder *builder;
-   gboolean ret = FALSE;
-   gboolean is_insert;
-   gint64 row_id = -1;
+   gboolean has_pkey, is_insert;
    GSList *types = NULL;
    GSList *iter;
    GType resource_type;
-   gboolean has_pkey;
-
-   g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE);
-   g_return_val_if_fail(GOM_IS_ADAPTER(adapter), FALSE);
+   GList *cmds = NULL;
 
    resource_type = G_TYPE_FROM_INSTANCE(resource);
    g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));
@@ -577,6 +603,8 @@ gom_resource_do_save (GomResource  *resource,
      is_insert = TRUE;
    }
 
+   g_object_set_data (G_OBJECT (resource), "is-insert", GINT_TO_POINTER (is_insert));
+
    do {
       types = g_slist_prepend(types, GINT_TO_POINTER(resource_type));
    } while ((resource_type = g_type_parent(resource_type)) != GOM_TYPE_RESOURCE);
@@ -596,33 +624,66 @@ gom_resource_do_save (GomResource  *resource,
          command = gom_command_builder_build_update(builder, resource);
       }
 
-      if (!gom_command_execute(command, NULL, error)) {
-         g_object_unref(command);
+      if (is_insert && gom_resource_has_dynamic_pkey(resource_type))
+        is_insert = FALSE;
+
+      cmds = g_list_prepend (cmds, command);
+   }
+
+   cmds = g_list_reverse (cmds);
+   g_object_set_data_full (G_OBJECT(resource), "save-commands", cmds, free_save_cmds);
+
+   g_slist_free(types);
+   g_object_unref (builder);
+}
+
+static gboolean
+gom_resource_do_save (GomResource  *resource,
+                      GomAdapter   *adapter,
+                      GError      **error)
+{
+   gboolean ret = FALSE;
+   gboolean is_insert;
+   gint64 row_id = -1;
+   GType resource_type;
+   GList *cmds, *l;
+
+   g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE);
+   g_return_val_if_fail(GOM_IS_ADAPTER(adapter), FALSE);
+
+   resource_type = G_TYPE_FROM_INSTANCE(resource);
+   g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));
+
+   is_insert = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(resource), "is-insert"));
+   cmds = g_object_get_data(G_OBJECT(resource), "save-commands");
+
+   for (l = cmds; l != NULL; l = l->next) {
+      GomCommand *command = l->data;
+
+      if (!gom_command_execute(command, NULL, error))
          goto out;
-      }
 
       if (is_insert && row_id == -1 && gom_resource_has_dynamic_pkey(resource_type)) {
          sqlite3 *handle = gom_adapter_get_handle(adapter);
-         GValue value = { 0 };
+         GValue *value;
 
          row_id = sqlite3_last_insert_rowid(handle);
-         g_value_init(&value, G_TYPE_INT64);
-         g_value_set_int64(&value, row_id);
-         set_pkey(resource, &value);
-         gom_resource_set_is_from_table(resource, TRUE);
-         g_value_unset(&value);
+         value = g_new0 (GValue, 1);
+         g_value_init(value, G_TYPE_INT64);
+         g_value_set_int64(value, row_id);
+         g_object_set_data_full(G_OBJECT(resource), "row-id", value, value_free);
+
+         g_object_set_data (G_OBJECT(resource), "is-from-table", GINT_TO_POINTER(TRUE));
 
          is_insert = FALSE;
       }
-
-      g_object_unref(command);
    }
 
    ret = TRUE;
 
 out:
-   g_slist_free(types);
-   g_object_unref(builder);
+   g_object_set_data (G_OBJECT (resource), "save-commands", NULL);
+   g_object_set_data (G_OBJECT (resource), "is-insert", NULL);
 
    return ret;
 }
@@ -692,6 +753,8 @@ gom_resource_save_sync (GomResource  *resource,
    g_object_set_data(G_OBJECT(simple), "queue", queue);
    g_assert(GOM_IS_ADAPTER(adapter));
 
+   gom_resource_build_save_cmd(resource, adapter);
+
    gom_adapter_queue_write(adapter, gom_resource_save_cb, simple);
    g_async_queue_pop(queue);
    g_async_queue_unref(queue);
@@ -699,6 +762,10 @@ gom_resource_save_sync (GomResource  *resource,
    if (!(ret = g_simple_async_result_get_op_res_gboolean(simple))) {
       g_simple_async_result_propagate_error(simple, error);
    }
+
+   if (ret)
+      set_post_save_properties(resource);
+
    g_object_unref(simple);
 
    return ret;
@@ -727,6 +794,7 @@ gom_resource_save_async (GomResource         *resource,
                                       gom_resource_save_async);
    adapter = gom_repository_get_adapter(priv->repository);
    g_assert(GOM_IS_ADAPTER(adapter));
+   gom_resource_build_save_cmd(resource, adapter);
    gom_adapter_queue_write(adapter, gom_resource_save_cb, simple);
 }
 
@@ -744,6 +812,10 @@ gom_resource_save_finish (GomResource   *resource,
    if (!(ret = g_simple_async_result_get_op_res_gboolean(simple))) {
       g_simple_async_result_propagate_error(simple, error);
    }
+
+   if (ret)
+      set_post_save_properties(resource);
+
    g_object_unref(simple);
 
    return ret;


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