diff options
author | Thomas Haller <thaller@redhat.com> | 2018-03-28 08:09:56 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-04-04 14:02:13 +0200 |
commit | f67303221bdc8098cb3b6203ec777b294e412971 (patch) | |
tree | c084b9d71667d8bdb8617e36cc965ee437ee751f /src/nm-checkpoint.c | |
parent | ab8312a18e8b281a62f39ce59a077fda77943187 (diff) | |
download | NetworkManager-f67303221bdc8098cb3b6203ec777b294e412971.tar.gz |
checkpoint: allow resetting the rollback timeout via D-Bus
This allows to adjust the timeout of an existing checkpoint.
The main usecase of checkpoints, is to have a fail-safe when
configuring the network remotely. By allowing to reset the timeout,
the user can perform a series of actions, and keep bumping the
timeout. That way, the entire series is still guarded by the same
checkpoint, but the user can start with short timeout, and
re-adjust the timeout as he goes along.
The libnm API only implements the async form (at least for now).
Sync methods are fundamentally wrong with D-Bus, and it's probably
not needed. Also, follow glib convenction, where the async form
doesn't have the _async name suffix. Also, accept a D-Bus path
as argument, not a NMCheckpoint instance. The libnm API should
not be more restricted than the underlying D-Bus API. It would
be cumbersome to require the user to lookup the NMCheckpoint
instance first, especially since libnm doesn't provide an efficient
or convenient lookup-by-path method. On the other hand, retrieving
the path from a NMCheckpoint instance is always possible.
Diffstat (limited to 'src/nm-checkpoint.c')
-rw-r--r-- | src/nm-checkpoint.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index 29e748bb39..f7e857c558 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -48,7 +48,7 @@ typedef struct { NMUnmanFlagOp unmanaged_explicit; } DeviceCheckpoint; -NM_GOBJECT_PROPERTIES_DEFINE_BASE ( +NM_GOBJECT_PROPERTIES_DEFINE (NMCheckpoint, PROP_DEVICES, PROP_CREATED, PROP_ROLLBACK_TIMEOUT, @@ -474,6 +474,42 @@ _timeout_cb (gpointer user_data) return G_SOURCE_REMOVE; } +void +nm_checkpoint_adjust_rollback_timeout (NMCheckpoint *self, guint32 add_timeout) +{ + guint32 rollback_timeout_s; + gint64 now_ms, add_timeout_ms, rollback_timeout_ms; + + NMCheckpointPrivate *priv = NM_CHECKPOINT_GET_PRIVATE (self); + + nm_clear_g_source (&priv->timeout_id); + + if (add_timeout == 0) + rollback_timeout_s = 0; + else { + now_ms = nm_utils_get_monotonic_timestamp_ms (); + add_timeout_ms = ((gint64) add_timeout) * 1000; + rollback_timeout_ms = (now_ms - priv->created_at_ms) + add_timeout_ms; + + /* round to nearest integer second. Since NM_CHECKPOINT_ROLLBACK_TIMEOUT is + * in units seconds, it will be able to exactly express the timeout. */ + rollback_timeout_s = NM_MIN ((rollback_timeout_ms + 500) / 1000, (gint64) G_MAXUINT32); + + /* we expect the timeout to be positive, because add_timeout_ms is positive. + * We cannot accept a zero, because it means "infinity". */ + nm_assert (rollback_timeout_s > 0); + + priv->timeout_id = g_timeout_add (NM_MIN (add_timeout_ms, (gint64) G_MAXUINT32), + _timeout_cb, + self); + } + + if (rollback_timeout_s != priv->rollback_timeout_s) { + priv->rollback_timeout_s = rollback_timeout_s; + _notify (self, PROP_ROLLBACK_TIMEOUT); + } +} + /*****************************************************************************/ static void |