mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 18:40:09 +01:00
core/ovs: allow ovsdb calls to be cancelled
In general, providing an async API also requires the ability to cancel requests. It's not yet used, but add a way to handle a GCancellable.
This commit is contained in:
parent
8b4d77a453
commit
c44c8e7fbc
1 changed files with 74 additions and 6 deletions
|
|
@ -90,8 +90,11 @@ typedef struct {
|
|||
guint64 call_id;
|
||||
OvsdbCommand command;
|
||||
OvsdbMethodCallback callback;
|
||||
GCancellable * cancellable;
|
||||
gpointer user_data;
|
||||
OvsdbMethodPayload payload;
|
||||
gulong cancellable_id;
|
||||
guint timeout_id;
|
||||
} OvsdbMethodCall;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -238,6 +241,9 @@ _call_complete(OvsdbMethodCall *call, json_t *response, GError *error)
|
|||
{
|
||||
c_list_unlink_stale(&call->calls_lst);
|
||||
|
||||
nm_clear_g_signal_handler(call->cancellable, &call->cancellable_id);
|
||||
g_clear_object(&call->cancellable);
|
||||
|
||||
if (call->callback)
|
||||
call->callback(call->self, response, error, call->user_data);
|
||||
|
||||
|
|
@ -330,6 +336,49 @@ _signal_emit_interface_failed(NMOvsdb * self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_method_call_cancelled_on_idle_cb(gpointer user_data)
|
||||
{
|
||||
OvsdbMethodCall *call = user_data;
|
||||
gs_unref_object NMOvsdb *self = call->self;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
call->timeout_id = 0;
|
||||
_LOGT_call("cancelled (run on idle)", call, NULL);
|
||||
nm_utils_error_set_cancelled(&error, FALSE, "NMOvsdb");
|
||||
_call_complete(call, NULL, error);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
_method_call_cancelled_cb(gpointer user_data)
|
||||
{
|
||||
OvsdbMethodCall *call = user_data;
|
||||
NMOvsdb * self = call->self;
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
nm_assert(NM_IS_OVSDB(self));
|
||||
|
||||
if (call->cancellable_id == 0) {
|
||||
/* We are invoked synchronously by g_cancellable_connection().
|
||||
* Let's consistently emit the completion callback asynchronously,
|
||||
* hence schedule it on an idle handler. */
|
||||
c_list_unlink(&call->calls_lst);
|
||||
g_object_ref(self);
|
||||
nm_clear_g_source(&call->timeout_id);
|
||||
_LOGT_call("cancelled (schedule on idle)", call, NULL);
|
||||
call->timeout_id = g_idle_add(_method_call_cancelled_on_idle_cb, call);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_utils_error_set_cancelled(&error, FALSE, "NMOvsdb");
|
||||
_call_complete(call, NULL, error);
|
||||
|
||||
_LOGT_call("cancelled", call, NULL);
|
||||
|
||||
ovsdb_next_command(self);
|
||||
}
|
||||
|
||||
/**
|
||||
* ovsdb_call_method:
|
||||
*
|
||||
|
|
@ -340,6 +389,7 @@ static void
|
|||
ovsdb_call_method(NMOvsdb * self,
|
||||
OvsdbMethodCallback callback,
|
||||
gpointer user_data,
|
||||
GCancellable * cancellable,
|
||||
gboolean add_first,
|
||||
OvsdbCommand command,
|
||||
const OvsdbMethodPayload *payload)
|
||||
|
|
@ -352,11 +402,12 @@ ovsdb_call_method(NMOvsdb * self,
|
|||
|
||||
call = g_slice_new(OvsdbMethodCall);
|
||||
*call = (OvsdbMethodCall){
|
||||
.self = self,
|
||||
.call_id = CALL_ID_UNSPEC,
|
||||
.command = command,
|
||||
.callback = callback,
|
||||
.user_data = user_data,
|
||||
.self = self,
|
||||
.call_id = CALL_ID_UNSPEC,
|
||||
.command = command,
|
||||
.callback = callback,
|
||||
.user_data = user_data,
|
||||
.cancellable = nm_g_object_ref(cancellable),
|
||||
};
|
||||
|
||||
if (add_first)
|
||||
|
|
@ -364,7 +415,7 @@ ovsdb_call_method(NMOvsdb * self,
|
|||
else
|
||||
c_list_link_tail(&priv->calls_lst_head, &call->calls_lst);
|
||||
|
||||
/* Mmigrate the arguments from @payload to @call->payload. Technically,
|
||||
/* Migrate the arguments from @payload to @call->payload. Technically,
|
||||
* this is not a plain copy, because
|
||||
* - call->payload is not initialized (thus no need to free the previous data).
|
||||
* - payload does not own the data. It is merely initialized using the
|
||||
|
|
@ -397,6 +448,19 @@ ovsdb_call_method(NMOvsdb * self,
|
|||
|
||||
_LOGT_call("enqueue", call, NULL);
|
||||
|
||||
if (call->cancellable) {
|
||||
gulong id;
|
||||
|
||||
id = g_cancellable_connect(call->cancellable,
|
||||
G_CALLBACK(_method_call_cancelled_cb),
|
||||
call,
|
||||
NULL);
|
||||
if (id == 0)
|
||||
return;
|
||||
|
||||
call->cancellable_id = id;
|
||||
}
|
||||
|
||||
ovsdb_next_command(self);
|
||||
}
|
||||
|
||||
|
|
@ -2131,6 +2195,7 @@ ovsdb_try_connect(NMOvsdb *self)
|
|||
ovsdb_call_method(self,
|
||||
_monitor_bridges_cb,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
OVSDB_MONITOR,
|
||||
OVSDB_METHOD_PAYLOAD_MONITOR());
|
||||
|
|
@ -2201,6 +2266,7 @@ nm_ovsdb_add_interface(NMOvsdb * self,
|
|||
ovsdb_call_method(self,
|
||||
_transact_cb,
|
||||
ovsdb_call_new(callback, user_data),
|
||||
NULL,
|
||||
FALSE,
|
||||
OVSDB_ADD_INTERFACE,
|
||||
OVSDB_METHOD_PAYLOAD_ADD_INTERFACE(bridge,
|
||||
|
|
@ -2219,6 +2285,7 @@ nm_ovsdb_del_interface(NMOvsdb * self,
|
|||
ovsdb_call_method(self,
|
||||
_transact_cb,
|
||||
ovsdb_call_new(callback, user_data),
|
||||
NULL,
|
||||
FALSE,
|
||||
OVSDB_DEL_INTERFACE,
|
||||
OVSDB_METHOD_PAYLOAD_DEL_INTERFACE(ifname));
|
||||
|
|
@ -2234,6 +2301,7 @@ nm_ovsdb_set_interface_mtu(NMOvsdb * self,
|
|||
ovsdb_call_method(self,
|
||||
_transact_cb,
|
||||
ovsdb_call_new(callback, user_data),
|
||||
NULL,
|
||||
FALSE,
|
||||
OVSDB_SET_INTERFACE_MTU,
|
||||
OVSDB_METHOD_PAYLOAD_SET_INTERFACE_MTU(ifname, mtu));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue