[grilo-plugins] lua-factory: support to cancel operation



commit 173958f16f9455694921cc2382e47328bf59ca85
Author: Victor Toso <me victortoso com>
Date:   Tue Mar 29 23:11:34 2016 +0200

    lua-factory: support to cancel operation
    
    Grilo has optional method to cancel operations which Lua-Factory had
    not implemented so far, till now.
    
    For each operation we create a GCancellabe that should be used in
    async functions in Lua-Library such as grl.fetch and grl.unzip.
    
    The grl_lua_operations_cancel_operation(), will cancel the operation,
    remove the OperationSpec from its internals and free the related data.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=764077

 src/lua-factory/grl-lua-common.h             |    2 +
 src/lua-factory/grl-lua-factory.c            |   20 ++++++++++++++
 src/lua-factory/grl-lua-library-operations.c |   35 +++++++++++++++++++++++++
 src/lua-factory/grl-lua-library.c            |   36 ++++++++++++++++++--------
 4 files changed, 82 insertions(+), 11 deletions(-)
---
diff --git a/src/lua-factory/grl-lua-common.h b/src/lua-factory/grl-lua-common.h
index b27d480..92ef36e 100644
--- a/src/lua-factory/grl-lua-common.h
+++ b/src/lua-factory/grl-lua-common.h
@@ -76,6 +76,7 @@ typedef struct _OperationSpec {
   GrlSource *source;
   guint operation_id;
   GrlOperationOptions *options;
+  GCancellable *cancellable;
   GList *keys;
   LuaOperationType op_type;
   union {
@@ -95,6 +96,7 @@ void grl_lua_library_save_goa_data (lua_State *L, gpointer goa_object);
 void grl_lua_operations_init_priv_state (lua_State *L);
 void grl_lua_operations_set_proxy_table (lua_State *L, gint index);
 void grl_lua_operations_set_source_state (lua_State *L, LuaSourceState state, OperationSpec *os);
+void grl_lua_operations_cancel_operation (lua_State *L, guint operation_id);
 OperationSpec * grl_lua_operations_get_current_op (lua_State *L);
 gboolean grl_lua_operations_pcall (lua_State *L, gint nargs, OperationSpec *os, GError **err);
 
diff --git a/src/lua-factory/grl-lua-factory.c b/src/lua-factory/grl-lua-factory.c
index a11dfee..3f14427 100644
--- a/src/lua-factory/grl-lua-factory.c
+++ b/src/lua-factory/grl-lua-factory.c
@@ -134,6 +134,9 @@ static const GList *grl_lua_factory_source_supported_keys (GrlSource *source);
 
 static const GList *grl_lua_factory_source_slow_keys(GrlSource *source);
 
+static void grl_lua_factory_source_cancel (GrlSource *source,
+                                           guint operation_id);
+
 static void grl_lua_factory_source_search (GrlSource *source,
                                            GrlSourceSearchSpec *ss);
 
@@ -511,6 +514,7 @@ grl_lua_factory_source_class_init (GrlLuaFactorySourceClass *klass)
   source_class->query = grl_lua_factory_source_query;
   source_class->resolve = grl_lua_factory_source_resolve;
   source_class->may_resolve = grl_lua_factory_source_may_resolve;
+  source_class->cancel = grl_lua_factory_source_cancel;
 
   g_type_class_add_private (klass, sizeof (GrlLuaFactorySourcePrivate));
 }
@@ -1510,6 +1514,18 @@ grl_lua_factory_source_supported_operations (GrlSource *source)
 }
 
 static void
+grl_lua_factory_source_cancel (GrlSource *source,
+                               guint operation_id)
+{
+  GrlLuaFactorySource *lua_source = GRL_LUA_FACTORY_SOURCE (source);
+  lua_State *L = lua_source->priv->l_st;
+
+  GRL_DEBUG ("grl_lua_factory_source_cancel (%s) %u",
+             grl_source_get_id (source), operation_id);
+  grl_lua_operations_cancel_operation (L, operation_id);
+}
+
+static void
 grl_lua_factory_source_search (GrlSource *source,
                                GrlSourceSearchSpec *ss)
 {
@@ -1526,6 +1542,7 @@ grl_lua_factory_source_search (GrlSource *source,
   os = g_slice_new0 (OperationSpec);
   os->source = ss->source;
   os->operation_id = ss->operation_id;
+  os->cancellable = g_cancellable_new ();
   os->cb.result = ss->callback;
   os->user_data = ss->user_data;
   os->string = g_strdup (text);
@@ -1562,6 +1579,7 @@ grl_lua_factory_source_browse (GrlSource *source,
   os = g_slice_new0 (OperationSpec);
   os->source = bs->source;
   os->operation_id = bs->operation_id;
+  os->cancellable = g_cancellable_new ();
   os->media = bs->container;
   os->cb.result = bs->callback;
   os->user_data = bs->user_data;
@@ -1599,6 +1617,7 @@ grl_lua_factory_source_query (GrlSource *source,
   os = g_slice_new0 (OperationSpec);
   os->source = qs->source;
   os->operation_id = qs->operation_id;
+  os->cancellable = g_cancellable_new ();
   os->cb.result = qs->callback;
   os->user_data = qs->user_data;
   os->string = g_strdup (query);
@@ -1632,6 +1651,7 @@ grl_lua_factory_source_resolve (GrlSource *source,
   os = g_slice_new0 (OperationSpec);
   os->source = rs->source;
   os->operation_id = rs->operation_id;
+  os->cancellable = g_cancellable_new ();
   os->cb.resolve = rs->callback;
   os->media = rs->media;
   os->user_data = rs->user_data;
diff --git a/src/lua-factory/grl-lua-library-operations.c b/src/lua-factory/grl-lua-library-operations.c
index 68ec319..a58398b 100644
--- a/src/lua-factory/grl-lua-library-operations.c
+++ b/src/lua-factory/grl-lua-library-operations.c
@@ -47,6 +47,11 @@ free_operation_spec (OperationSpec *os)
   g_clear_pointer (&os->string, g_free);
   g_clear_object (&os->options);
 
+  if (os->cancellable) {
+    g_cancellable_cancel (os->cancellable);
+    g_clear_object (&os->cancellable);
+  }
+
   if (os->keys)
     g_list_free (os->keys);
 
@@ -674,6 +679,36 @@ grl_lua_operations_get_current_op (lua_State *L)
   return os;
 }
 
+void
+grl_lua_operations_cancel_operation (lua_State *L,
+                                     guint operation_id)
+{
+    OperationSpec *os, *current_os;
+    LuaSourceState state;
+
+    os = priv_state_operations_source_get_op_data (L, operation_id);
+    g_return_if_fail (os != NULL);
+
+    state = priv_state_operations_source_get_state (L, operation_id);
+    if (state != LUA_SOURCE_WAITING) {
+      GRL_DEBUG ("Can't cancel operation (%u) on source (%s) with as state is: %s",
+                 operation_id, grl_source_get_id (os->source),
+                 source_op_state_str[state]);
+      return;
+    }
+
+    /* All async operations on lua-library should verify os->cancellable to
+     * proper handling the cancelation of ongoing operation */
+    g_cancellable_cancel (os->cancellable);
+
+    current_os = priv_state_current_op_get_op_data (L);
+
+    priv_state_operations_remove_source_state (L, os->operation_id);
+    if (current_os != NULL && current_os->operation_id == os->operation_id)
+      priv_state_current_op_remove (L);
+    free_operation_spec (os);
+}
+
 /*
  * This is a wrapper to do execute the lua_pcall and all internals that might
  * be necessary to Lua-Library before calling the Lua function. The stack
diff --git a/src/lua-factory/grl-lua-library.c b/src/lua-factory/grl-lua-library.c
index c70be08..7711bbc 100644
--- a/src/lua-factory/grl-lua-library.c
+++ b/src/lua-factory/grl-lua-library.c
@@ -53,6 +53,7 @@ typedef struct {
   guint num_urls;
   gboolean is_table;
   gchar **results;
+  GCancellable *cancellable;
   OperationSpec *os;
 } FetchOperation;
 
@@ -62,6 +63,7 @@ typedef struct {
   gint lua_callback;
   gchar *url;
   gchar **filenames;
+  GCancellable *cancellable;
   OperationSpec *os;
 } UnzipOperation;
 
@@ -479,6 +481,10 @@ grl_util_fetch_done (GObject *source_object,
 
   if (!grl_net_wc_request_finish (GRL_NET_WC (source_object),
                                   res, &data, &len, &err)) {
+    if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+      GRL_DEBUG ("fetch operation was cancelled");
+      goto free_fetch_op;
+    }
     data = NULL;
   } else if (!g_utf8_validate(data, len, NULL)) {
     fixed = g_convert (data, len, "UTF-8", "ISO8859-1", NULL, NULL, NULL);
@@ -536,6 +542,8 @@ grl_util_fetch_done (GObject *source_object,
     }
   }
 
+free_fetch_op:
+  g_object_unref (fo->cancellable);
   luaL_unref (L, LUA_REGISTRYINDEX, fo->lua_userdata);
   luaL_unref (L, LUA_REGISTRYINDEX, fo->lua_callback);
 
@@ -638,13 +646,16 @@ grl_util_unzip_done (GObject *source_object,
   OperationSpec *os = uo->os;
   char **results;
 
-  grl_net_wc_request_finish (GRL_NET_WC (source_object),
-                             res, &data, &len, &err);
-
-  if (err != NULL) {
+  if (!grl_net_wc_request_finish (GRL_NET_WC (source_object),
+                                  res, &data, &len, &err)) {
     guint len, i;
-    GRL_WARNING ("Can't fetch zip file (URL: %s): '%s'", uo->url, err->message);
-    g_error_free (err);
+    if (g_error_matches (err, GRL_NET_WC_ERROR, GRL_NET_WC_ERROR_CANCELLED)) {
+      GRL_DEBUG ("unzip operation was cancelled");
+      goto free_unzip_op;
+    } else if (err != NULL) {
+      GRL_WARNING ("Can't fetch zip file (URL: %s): '%s'", uo->url, err->message);
+      g_error_free (err);
+    }
     len = g_strv_length (uo->filenames);
     results = g_new0 (gchar *, len + 1);
     for (i = 0; i < len; i++)
@@ -674,11 +685,12 @@ grl_util_unzip_done (GObject *source_object,
     }
   }
 
-  luaL_unref (L, LUA_REGISTRYINDEX, uo->lua_userdata);
-  luaL_unref (L, LUA_REGISTRYINDEX, uo->lua_callback);
-
   g_strfreev (results);
 
+free_unzip_op:
+  g_object_unref (uo->cancellable);
+  luaL_unref (L, LUA_REGISTRYINDEX, uo->lua_userdata);
+  luaL_unref (L, LUA_REGISTRYINDEX, uo->lua_callback);
   g_strfreev (uo->filenames);
   g_free (uo->url);
   g_free (uo);
@@ -1204,6 +1216,7 @@ grl_l_fetch (lua_State *L)
     fo = g_new0 (FetchOperation, 1);
     fo->L = L;
     fo->os = os;
+    fo->cancellable = g_object_ref (os->cancellable);
     fo->lua_userdata = lua_userdata;
     fo->lua_callback = lua_callback;
     fo->index = i;
@@ -1212,7 +1225,7 @@ grl_l_fetch (lua_State *L)
     fo->is_table = is_table;
     fo->results = results;
 
-    grl_net_wc_request_async (wc, urls[i], NULL, grl_util_fetch_done, fo);
+    grl_net_wc_request_async (wc, urls[i], os->cancellable, grl_util_fetch_done, fo);
   }
   g_object_unref (wc);
   g_free (urls);
@@ -1481,13 +1494,14 @@ grl_l_unzip (lua_State *L)
 
   uo = g_new0 (UnzipOperation, 1);
   uo->L = L;
+  uo->cancellable = g_object_ref (os->cancellable);
   uo->lua_userdata = lua_userdata;
   uo->lua_callback = lua_callback;
   uo->url = g_strdup (url);
   uo->filenames = filenames;
   uo->os = os;
 
-  grl_net_wc_request_async (wc, url, NULL, grl_util_unzip_done, uo);
+  grl_net_wc_request_async (wc, url, os->cancellable, grl_util_unzip_done, uo);
   g_object_unref (wc);
 
   grl_lua_operations_set_source_state (L, LUA_SOURCE_WAITING, os);


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