Commit 5bdffa0f authored by Thomas Haller's avatar Thomas Haller

libnm: implement nm_client_checkpoint_create() by using GDBusConnection directly

parent b44d883d
......@@ -2554,25 +2554,6 @@ dns_notify (GObject *object,
}
}
static void
checkpoint_create_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
NMCheckpoint *checkpoint;
GError *error = NULL;
checkpoint = nm_manager_checkpoint_create_finish (NM_MANAGER (object), result, &error);
if (checkpoint)
g_simple_async_result_set_op_res_gpointer (simple, checkpoint, g_object_unref);
else
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
/**
* nm_client_get_checkpoints:
* @client: a #NMClient
......@@ -2596,6 +2577,35 @@ nm_client_get_checkpoints (NMClient *client)
return nm_manager_get_checkpoints (NM_CLIENT_GET_PRIVATE (client)->manager);
}
static void
checkpoint_create_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient *self;
gs_unref_object GTask *task = user_data;
gs_unref_variant GVariant *ret = NULL;
const char *checkpoint_path;
GError *error = NULL;
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
if (!ret) {
g_dbus_error_strip_remote_error (error);
g_task_return_error (task, error);
return;
}
g_variant_get (ret,
"(&o)",
&checkpoint_path);
self = g_task_get_source_object (task);
nm_manager_wait_for_checkpoint (NM_CLIENT_GET_PRIVATE (self)->manager,
checkpoint_path,
g_steal_pointer (&task));
}
/**
* nm_client_checkpoint_create:
* @client: the %NMClient
......@@ -2623,23 +2633,35 @@ nm_client_checkpoint_create (NMClient *client,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
gs_free const char **paths = NULL;
guint i;
g_return_if_fail (NM_IS_CLIENT (client));
if (!_nm_client_check_nm_running (client, &error)) {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
return;
if ( devices
&& devices->len > 0) {
paths = g_new (const char *, devices->len + 1);
for (i = 0; i < devices->len; i++)
paths[i] = nm_object_get_path (NM_OBJECT (devices->pdata[i]));
paths[i] = NULL;
}
simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
nm_client_checkpoint_create);
if (cancellable)
g_simple_async_result_set_check_cancellable (simple, cancellable);
nm_manager_checkpoint_create (NM_CLIENT_GET_PRIVATE (client)->manager,
devices, rollback_timeout, flags,
cancellable, checkpoint_create_cb, simple);
_nm_object_dbus_call (client,
nm_client_checkpoint_create,
cancellable,
callback,
user_data,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
"CheckpointCreate",
g_variant_new ("(^aouu)",
paths ?: NM_PTRARRAY_EMPTY (const char *),
rollback_timeout,
flags),
G_VARIANT_TYPE ("(o)"),
G_DBUS_CALL_FLAGS_NONE,
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
checkpoint_create_cb);
}
/**
......@@ -2660,16 +2682,10 @@ nm_client_checkpoint_create_finish (NMClient *client,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
g_return_val_if_fail (nm_g_task_is_valid (result, client, nm_client_checkpoint_create), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
......
......@@ -46,7 +46,6 @@ typedef struct {
GPtrArray *all_devices;
GPtrArray *active_connections;
GPtrArray *checkpoints;
GSList *added_checkpoints;
NMConnectivityState connectivity;
NMActiveConnection *primary_connection;
NMActiveConnection *activating_connection;
......@@ -60,6 +59,8 @@ typedef struct {
*/
CList wait_for_active_connection_lst_head;
CList wait_for_checkpoint_lst_head;
gboolean networking_enabled;
gboolean wireless_enabled;
gboolean wireless_hw_enabled;
......@@ -119,21 +120,21 @@ static guint signals[LAST_SIGNAL] = { 0 };
/*****************************************************************************/
typedef struct {
NMManager *manager;
GSimpleAsyncResult *simple;
char *path;
CList lst;
NMManager *self;
char *checkpoint_path;
GTask *task;
gulong cancelled_id;
} CheckpointInfo;
static CheckpointInfo *
find_checkpoint_info (NMManager *manager, const char *path)
_wait_for_checkpoint_find_info (NMManager *manager, const char *path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
CheckpointInfo *info;
GSList *iter;
for (iter = priv->added_checkpoints; iter; iter = g_slist_next (iter)) {
info = iter->data;
if (nm_streq0 (path, info->path))
c_list_for_each_entry (info, &priv->wait_for_checkpoint_lst_head, lst) {
if (nm_streq (path, info->checkpoint_path))
return info;
}
......@@ -141,28 +142,23 @@ find_checkpoint_info (NMManager *manager, const char *path)
}
static void
checkpoint_info_complete (NMManager *self,
CheckpointInfo *info,
NMCheckpoint *checkpoint,
GError *error)
_wait_for_checkpoint_complete (CheckpointInfo *info,
NMCheckpoint *checkpoint,
GError *error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
g_return_if_fail (info);
c_list_unlink_stale (&info->lst);
if (checkpoint) {
g_simple_async_result_set_op_res_gpointer (info->simple,
g_object_ref (checkpoint),
g_object_unref);
} else
g_simple_async_result_set_from_error (info->simple, error);
g_simple_async_result_complete (info->simple);
nm_clear_g_signal_handler (g_task_get_cancellable (info->task), &info->cancelled_id);
g_object_unref (info->simple);
priv->added_checkpoints = g_slist_remove (priv->added_checkpoints, info);
if (!checkpoint)
g_task_return_error (info->task, error);
else
g_task_return_pointer (info->task, g_object_ref (checkpoint), g_object_unref);
g_free (info->path);
g_slice_free (CheckpointInfo, info);
g_object_unref (info->task);
g_object_unref (info->self);
g_free (info->checkpoint_path);
nm_g_slice_free (info);
}
static void
......@@ -171,6 +167,7 @@ nm_manager_init (NMManager *manager)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
c_list_init (&priv->wait_for_active_connection_lst_head);
c_list_init (&priv->wait_for_checkpoint_lst_head);
priv->state = NM_STATE_UNKNOWN;
priv->connectivity = NM_CONNECTIVITY_UNKNOWN;
......@@ -250,12 +247,12 @@ object_creation_failed (NMObject *object, const char *failed_path)
CheckpointInfo *info;
GError *add_error;
info = find_checkpoint_info (self, failed_path);
info = _wait_for_checkpoint_find_info (self, failed_path);
if (info) {
add_error = g_error_new_literal (NM_CLIENT_ERROR,
NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
_("Checkpoint was removed before it was initialized"));
checkpoint_info_complete (self, info, NULL, add_error);
_wait_for_checkpoint_complete (info, NULL, add_error);
g_error_free (add_error);
}
}
......@@ -991,9 +988,9 @@ checkpoint_added (NMManager *manager, NMCheckpoint *checkpoint)
{
CheckpointInfo *info;
info = find_checkpoint_info (manager, nm_object_get_path (NM_OBJECT (checkpoint)));
info = _wait_for_checkpoint_find_info (manager, nm_object_get_path (NM_OBJECT (checkpoint)));
if (info)
checkpoint_info_complete (manager, info, checkpoint, NULL);
_wait_for_checkpoint_complete (info, checkpoint, NULL);
}
/*****************************************************************************/
......@@ -1016,21 +1013,6 @@ free_active_connections (NMManager *manager)
/*****************************************************************************/
static const char **
get_device_paths (const GPtrArray *devices)
{
const char **array;
guint i;
array = g_new (const char *, devices->len + 1);
for (i = 0; i < devices->len; i++)
array[i] = nm_object_get_path (NM_OBJECT (devices->pdata[i]));
array[i] = NULL;
return array;
}
const GPtrArray *
nm_manager_get_checkpoints (NMManager *manager)
{
......@@ -1040,81 +1022,58 @@ nm_manager_get_checkpoints (NMManager *manager)
}
static void
checkpoint_created_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
_wait_for_checkpoint_cancelled_cb (GCancellable *cancellable,
gpointer user_data)
{
CheckpointInfo *info = user_data;
NMManager *self = info->manager;
gs_free_error GError *error = NULL;
NMCheckpoint *checkpoint;
nmdbus_manager_call_checkpoint_create_finish (NMDBUS_MANAGER (object),
&info->path, result, &error);
if (error) {
g_dbus_error_strip_remote_error (error);
checkpoint_info_complete (self, info, NULL, error);
return;
}
checkpoint = get_checkpoint_by_path (self, info->path);
if (!checkpoint) {
/* this is really problematic. The async request returned, but
* we don't yet have a visible (fully initialized) NMCheckpoint instance
* to return. Wait longer for it to appear. However, it's ugly. */
if (!g_cancellable_set_error_if_cancelled (cancellable, &error))
return;
}
checkpoint_info_complete (self, info, checkpoint, NULL);
_wait_for_checkpoint_complete (info, NULL, g_steal_pointer (&error));
}
void
nm_manager_checkpoint_create (NMManager *manager,
const GPtrArray *devices,
guint32 rollback_timeout,
NMCheckpointCreateFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
nm_manager_wait_for_checkpoint (NMManager *self,
const char *checkpoint_path,
GTask *task_take)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
gs_free const char **paths = NULL;
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
gs_unref_object GTask *task = task_take;
CheckpointInfo *info;
GCancellable *cancellable;
NMCheckpoint *checkpoint;
g_return_if_fail (NM_IS_MANAGER (manager));
checkpoint = get_checkpoint_by_path (self, checkpoint_path);
if (checkpoint) {
g_task_return_pointer (task, g_object_ref (checkpoint), g_object_unref);
return;
}
info = g_slice_new0 (CheckpointInfo);
info->manager = manager;
info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_checkpoint_create);
if (cancellable)
g_simple_async_result_set_check_cancellable (info->simple, cancellable);
paths = get_device_paths (devices);
nmdbus_manager_call_checkpoint_create (NM_MANAGER_GET_PRIVATE (manager)->proxy,
paths,
rollback_timeout,
flags,
cancellable,
checkpoint_created_cb,
info);
priv->added_checkpoints = g_slist_append (priv->added_checkpoints, info);
}
NMCheckpoint *
nm_manager_checkpoint_create_finish (NMManager *manager,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
/* FIXME: there is no timeout for how long we wait. But this entire
* code will be reworked, also that we have a suitable GMainContext
* where we can schedule the timeout (we shouldn't use g_main_context_default()). */
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
info = g_slice_new (CheckpointInfo);
*info = (CheckpointInfo) {
.self = g_object_ref (self),
.task = g_steal_pointer (&task),
.checkpoint_path = g_strdup (checkpoint_path),
};
c_list_link_tail (&priv->wait_for_checkpoint_lst_head, &info->lst);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
cancellable = g_task_get_cancellable (info->task);
if (cancellable) {
info->cancelled_id = g_signal_connect (cancellable,
"cancelled",
G_CALLBACK (_wait_for_checkpoint_cancelled_cb),
info);
if (g_cancellable_is_cancelled (cancellable)) {
_wait_for_checkpoint_cancelled_cb (cancellable, info);
return;
}
}
}
static void
......@@ -1483,6 +1442,7 @@ dispose (GObject *object)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object);
nm_assert (c_list_is_empty (&priv->wait_for_active_connection_lst_head));
nm_assert (c_list_is_empty (&priv->wait_for_checkpoint_lst_head));
nm_clear_g_cancellable (&priv->perm_call_cancellable);
......
......@@ -142,16 +142,11 @@ void nm_manager_wait_for_active_connection (NMManager *self,
GTask *task_take);
const GPtrArray *nm_manager_get_checkpoints (NMManager *manager);
void nm_manager_checkpoint_create (NMManager *manager,
const GPtrArray *devices,
guint32 rollback_timeout,
NMCheckpointCreateFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
NMCheckpoint *nm_manager_checkpoint_create_finish (NMManager *manager,
GAsyncResult *result,
GError **error);
void nm_manager_wait_for_checkpoint (NMManager *self,
const char *checkpoint_path,
GTask *task_take);
void nm_manager_checkpoint_destroy (NMManager *manager,
const char *checkpoint_path,
GCancellable *cancellable,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment