[PATCH 1/1] core: add nm_device_add_pending_action_with_timeout()
- From: Thomas Haller <thaller redhat com>
- To: networkmanager-list gnome org
- Subject: [PATCH 1/1] core: add nm_device_add_pending_action_with_timeout()
- Date: Fri, 2 May 2014 21:03:48 +0200
Signed-off-by: Thomas Haller <thaller redhat com>
---
This patch was part of branch th/rh1086906_start_complete_for_dynamic_ip,
which was merged with:
http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=f5b82f49ddfb2ecbf2e865b914d639ddca5a28c8
It applies on current master
http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=9ef23947cc8f074767bd63b984b73740766377b0
This functionality was not needed, so the patch is obsolete. It may be useful
in the future, so I park it on the mailing list.
No action required!! :)
Thomas
src/devices/nm-device.c | 142 ++++++++++++++++++++++++++++++++++++++++++------
src/devices/nm-device.h | 2 +
2 files changed, 127 insertions(+), 17 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 384460e..0af565d 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -7684,6 +7684,52 @@ nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
return success;
}
+typedef gboolean (*PendingActionTimeoutCb) (NMDevice *device, const char *action, gboolean is_timeout,
gpointer user_data);
+
+typedef struct pending_action_data
+{
+ NMDevice *device;
+ PendingActionTimeoutCb handler;
+ gpointer user_data;
+ guint timeout_id;
+ char action[1];
+} PendingActionData;
+
+static PendingActionData *
+pending_action_data_new (NMDevice *device, const char *action, PendingActionTimeoutCb timeout_handler,
gpointer user_data)
+{
+ PendingActionData *data;
+ gsize len;
+
+ len = strlen (action);
+ data = g_malloc (sizeof (PendingActionData) - 1 + len + 1);
+
+ data->device = device;
+ data->handler = timeout_handler;
+ data->user_data = user_data;
+ data->timeout_id = 0;
+ memcpy (&data->action[0], action, len + 1);
+
+ return data;
+}
+
+static gboolean
+pending_action_timeout_cb (gpointer user_data)
+{
+ PendingActionData *data = user_data;
+
+ nm_log_dbg (LOGD_DEVICE, "(%s): timeout_pending_action: '%s' (timeout=%u)",
+ nm_device_get_iface (data->device),
+ data->action,
+ data->timeout_id);
+ data->timeout_id = 0;
+ if (data->handler (data->device, data->action, TRUE, data->user_data) &&
+ g_slist_find (NM_DEVICE_GET_PRIVATE (data->device)->pending_actions, data) != NULL)
+ nm_device_remove_pending_action (data->device, data->action, TRUE);
+
+ return G_SOURCE_REMOVE;
+}
+
/**
* nm_device_add_pending_action():
* @device: the #NMDevice to add the pending action to
@@ -7691,24 +7737,65 @@ nm_device_set_hw_addr (NMDevice *device, const guint8 *addr,
* @assert_not_yet_pending: if %TRUE, assert that the @action is currently not yet pending.
* Otherwise, ignore duplicate scheduling of the same action silently.
*
- * Adds a pending action to the device.
+ * Adds a pending action to the device without timeout. This is a shorthand for
+ * nm_device_add_pending_action_with_timeout().
+ *
+ * Returns: %TRUE if the action was added (and not already added before). %FALSE
+ * if the same action is already scheduled.
+ **/
+gboolean
+nm_device_add_pending_action (NMDevice *device, const char *action, gboolean assert_not_yet_pending)
+{
+ return nm_device_add_pending_action_with_timeout (device, action, assert_not_yet_pending, 0, NULL,
NULL);
+}
+
+/**
+ * nm_device_add_pending_action_with_timeout():
+ * @device: the #NMDevice to add the pending action to
+ * @action: a static string that identifies the action
+ * @assert_not_yet_pending: if %TRUE, assert that the @action is currently not yet pending.
+ * Otherwise, ignore duplicate scheduling of the same action silently.
+ * @timeout_ms: schedule a callback in @timeout_ms milliseconds. Set to 0 for no timeout.
+ * @timeout_handler: call this function after timeout or when removing the action.
+ * @user_data: argument for @timeout_handler.
+ *
+ * Adds a pending action to the device. If such an action is already pending, this call
+ * does nothing. Especially, it does not cancel any pending timeout or schedule a further one.
+ * If the action is not yet pending it will be added and the timeout started.
+ *
+ * The @timeout_handler will be called exactly once, either when removing the action or on timeout.
+ *
+ * When the action is removed, it calls the handler after the action is removed (with argument
+ * @is_timeout==%FALSE) but before notify::NM_DEVICE_HAS_PENDING_ACTION. In this case, the return
+ * value of @timeout_handler will be ignored.
+ *
+ * If the timeout hits first, @timeout_handler will be called, with the pending action still pending (the
+ * handler is allowed to call nm_device_remove_pending_action() -- which will not call @timeout_handler
+ * again). If the callback returns %TRUE and the very same action is still pending, it will call
+ * nm_device_remove_pending_action() to remove the action. Otherwise, the pending action will not
+ * be removed.
*
* Returns: %TRUE if the action was added (and not already added before). %FALSE
* if the same action is already scheduled. In the latter case, the action was not scheduled
* a second time.
- */
+ **/
gboolean
-nm_device_add_pending_action (NMDevice *device, const char *action, gboolean assert_not_yet_pending)
+nm_device_add_pending_action_with_timeout (NMDevice *device, const char *action, gboolean
assert_not_yet_pending,
+ guint32 timeout_ms, PendingActionTimeoutCb timeout_handler,
gpointer user_data)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
GSList *iter;
guint count = 0;
+ PendingActionData *data;
g_return_val_if_fail (action, FALSE);
+ g_return_val_if_fail ((!timeout_ms && !timeout_handler && !user_data) || (timeout_ms &&
timeout_handler), FALSE);
/* Check if the action is already pending. Cannot add duplicate actions */
for (iter = priv->pending_actions; iter; iter = iter->next) {
- if (!strcmp (action, iter->data)) {
+ data = iter->data;
+
+ if (!strcmp (action, data->action)) {
if (assert_not_yet_pending) {
nm_log_warn (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' already
pending",
nm_device_get_iface (device),
@@ -7726,13 +7813,22 @@ nm_device_add_pending_action (NMDevice *device, const char *action, gboolean ass
count++;
}
- priv->pending_actions = g_slist_append (priv->pending_actions, g_strdup (action));
+ data = pending_action_data_new (device, action, timeout_handler, user_data);
+ priv->pending_actions = g_slist_append (priv->pending_actions, data);
count++;
-
- nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s'",
- nm_device_get_iface (device),
- count,
- action);
+ if (timeout_ms) {
+ data->timeout_id = g_timeout_add (timeout_ms, pending_action_timeout_cb, data);
+ nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s' (timeout=%u, %lu msec)",
+ nm_device_get_iface (device),
+ count,
+ action,
+ data->timeout_id, (long unsigned) timeout_ms);
+ } else {
+ nm_log_dbg (LOGD_DEVICE, "(%s): add_pending_action (%d): '%s'",
+ nm_device_get_iface (device),
+ count,
+ action);
+ }
if (count == 1)
g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
@@ -7758,18 +7854,30 @@ nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
GSList *iter;
guint count = 0;
+ PendingActionData *data;
g_return_val_if_fail (action, FALSE);
for (iter = priv->pending_actions; iter; iter = iter->next) {
- if (!strcmp (action, iter->data)) {
- g_free (iter->data);
- priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
- nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'",
- nm_device_get_iface (device),
- count + g_slist_length (iter),
- action);
+ data = iter->data;
+ if (!strcmp (action, data->action)) {
+ priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
+ if (data->timeout_id) {
+ g_source_remove (data->timeout_id);
+ nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'
(timeout=%u)",
+ nm_device_get_iface (device),
+ count + g_slist_length (iter),
+ action,
+ data->timeout_id);
+ data->handler (device, action, FALSE, data->user_data);
+ } else {
+ nm_log_dbg (LOGD_DEVICE, "(%s): remove_pending_action (%d): '%s'",
+ nm_device_get_iface (device),
+ count + g_slist_length (iter),
+ action);
+ }
+ g_free (data);
if (priv->pending_actions == NULL)
g_object_notify (G_OBJECT (device), NM_DEVICE_HAS_PENDING_ACTION);
return TRUE;
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index d70af3b..9b61f9f 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -351,7 +351,9 @@ void nm_device_queue_activation (NMDevice *device, NMActRequest *req);
gboolean nm_device_supports_vlans (NMDevice *device);
+typedef gboolean (*PendingActionTimeoutCb) (NMDevice *device, const char *action, gboolean is_timeout,
gpointer user_data);
gboolean nm_device_add_pending_action (NMDevice *device, const char *action, gboolean
assert_not_yet_pending);
+gboolean nm_device_add_pending_action_with_timeout (NMDevice *device, const char *action, gboolean
assert_not_yet_pending, guint32 timeout_ms, PendingActionTimeoutCb timeout_handler, gpointer user_data);
gboolean nm_device_remove_pending_action (NMDevice *device, const char *action, gboolean assert_is_pending);
gboolean nm_device_has_pending_action (NMDevice *device);
--
1.9.0
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]