summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nm-checkpoint-manager.c124
-rw-r--r--src/nm-checkpoint-manager.h9
-rw-r--r--src/nm-manager.c15
3 files changed, 76 insertions, 72 deletions
diff --git a/src/nm-checkpoint-manager.c b/src/nm-checkpoint-manager.c
index d4b165cd81..5f749b15eb 100644
--- a/src/nm-checkpoint-manager.c
+++ b/src/nm-checkpoint-manager.c
@@ -35,7 +35,6 @@
struct _NMCheckpointManager {
NMManager *_manager;
GParamSpec *property_spec;
- GHashTable *checkpoints;
CList checkpoints_lst_head;
guint rollback_timeout_id;
};
@@ -60,6 +59,8 @@ struct _NMCheckpointManager {
static void update_rollback_timeout (NMCheckpointManager *self);
+/*****************************************************************************/
+
static void
notify_checkpoints (NMCheckpointManager *self) {
g_object_notify_by_pspec ((GObject *) GET_MANAGER (self),
@@ -67,11 +68,16 @@ notify_checkpoints (NMCheckpointManager *self) {
}
static void
-item_destroy (gpointer data)
+destroy_checkpoint (NMCheckpointManager *self, NMCheckpoint *checkpoint)
{
- NMCheckpoint *checkpoint = data;
+ nm_assert (NM_IS_CHECKPOINT (checkpoint));
+ nm_assert (c_list_is_empty (&checkpoint->checkpoints_lst));
+ nm_assert (nm_dbus_object_is_exported (NM_DBUS_OBJECT (checkpoint)));
c_list_unlink (&checkpoint->checkpoints_lst);
+
+ notify_checkpoints (self);
+
nm_dbus_object_unexport (NM_DBUS_OBJECT (checkpoint));
g_object_unref (checkpoint);
}
@@ -82,8 +88,8 @@ rollback_timeout_cb (NMCheckpointManager *self)
NMCheckpoint *checkpoint, *checkpoint_safe;
GVariant *result;
gint64 ts, now;
- const char *path;
- gboolean removed = FALSE;
+
+ self->rollback_timeout_id = 0;
now = nm_utils_get_monotonic_timestamp_ms ();
@@ -93,19 +99,12 @@ rollback_timeout_cb (NMCheckpointManager *self)
result = nm_checkpoint_rollback (checkpoint);
if (result)
g_variant_unref (result);
- path = nm_dbus_object_get_path (NM_DBUS_OBJECT (checkpoint));
- if (!g_hash_table_remove (self->checkpoints, path))
- nm_assert_not_reached();
- removed = TRUE;
+ destroy_checkpoint (self, checkpoint);
}
}
- self->rollback_timeout_id = 0;
update_rollback_timeout (self);
- if (removed)
- notify_checkpoints (self);
-
return G_SOURCE_REMOVE;
}
@@ -156,7 +155,6 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
NMCheckpoint *checkpoint;
gs_unref_ptrarray GPtrArray *devices = NULL;
NMDevice *device;
- const char *path;
guint i;
g_return_val_if_fail (self, FALSE);
@@ -215,31 +213,25 @@ nm_checkpoint_manager_create (NMCheckpointManager *self,
return NULL;
if (NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DESTROY_ALL))
- g_hash_table_remove_all (self->checkpoints);
+ nm_checkpoint_manager_destroy_all (self);
- path = nm_dbus_object_export (NM_DBUS_OBJECT (checkpoint));
+ nm_dbus_object_export (NM_DBUS_OBJECT (checkpoint));
c_list_link_tail (&self->checkpoints_lst_head, &checkpoint->checkpoints_lst);
-
- if (!g_hash_table_insert (self->checkpoints, (gpointer) path, checkpoint))
- g_return_val_if_reached (NULL);
-
notify_checkpoints (self);
update_rollback_timeout (self);
-
return checkpoint;
}
-gboolean
-nm_checkpoint_manager_destroy_all (NMCheckpointManager *self,
- GError **error)
+void
+nm_checkpoint_manager_destroy_all (NMCheckpointManager *self)
{
- g_return_val_if_fail (self, FALSE);
+ NMCheckpoint *checkpoint;
- g_hash_table_remove_all (self->checkpoints);
- notify_checkpoints (self);
+ g_return_if_fail (self);
- return TRUE;
+ while ((checkpoint = c_list_first_entry (&self->checkpoints_lst_head, NMCheckpoint, checkpoints_lst)))
+ destroy_checkpoint (self, checkpoint);
}
gboolean
@@ -247,25 +239,28 @@ nm_checkpoint_manager_destroy (NMCheckpointManager *self,
const char *path,
GError **error)
{
- gboolean ret;
+ NMCheckpoint *checkpoint;
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (path && path[0] == '/', FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
if (!nm_streq (path, "/")) {
- ret = g_hash_table_remove (self->checkpoints, path);
- if (ret) {
- notify_checkpoints (self);
- } else {
- g_set_error (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_INVALID_ARGUMENTS,
- "checkpoint %s does not exist", path);
- }
- return ret;
- } else
- return nm_checkpoint_manager_destroy_all (self, error);
+ nm_checkpoint_manager_destroy_all (self);
+ return TRUE;
+ }
+
+ checkpoint = nm_checkpoint_manager_lookup_by_path (self, path);
+ if (!checkpoint) {
+ g_set_error (error,
+ NM_MANAGER_ERROR,
+ NM_MANAGER_ERROR_INVALID_ARGUMENTS,
+ "checkpoint %s does not exist", path);
+ return FALSE;
+ }
+
+ destroy_checkpoint (self, checkpoint);
+ return TRUE;
}
gboolean
@@ -281,7 +276,7 @@ nm_checkpoint_manager_rollback (NMCheckpointManager *self,
g_return_val_if_fail (results, FALSE);
g_return_val_if_fail (!error || !*error, FALSE);
- checkpoint = g_hash_table_lookup (self->checkpoints, path);
+ checkpoint = nm_checkpoint_manager_lookup_by_path (self, path);
if (!checkpoint) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
"checkpoint %s does not exist", path);
@@ -289,31 +284,44 @@ nm_checkpoint_manager_rollback (NMCheckpointManager *self,
}
*results = nm_checkpoint_rollback (checkpoint);
- g_hash_table_remove (self->checkpoints, path);
- notify_checkpoints (self);
-
+ destroy_checkpoint (self, checkpoint);
return TRUE;
}
-char **
-nm_checkpoint_manager_get_checkpoint_paths (NMCheckpointManager *self)
+NMCheckpoint *
+nm_checkpoint_manager_lookup_by_path (NMCheckpointManager *self, const char *path)
+{
+ NMCheckpoint *checkpoint;
+
+ g_return_val_if_fail (self, NULL);
+
+ checkpoint = (NMCheckpoint *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (GET_MANAGER (self))),
+ path);
+ if ( !checkpoint
+ || !NM_IS_CHECKPOINT (checkpoint))
+ return NULL;
+
+ nm_assert (c_list_contains (&self->checkpoints_lst_head, &checkpoint->checkpoints_lst));
+ return checkpoint;
+}
+
+const char **
+nm_checkpoint_manager_get_checkpoint_paths (NMCheckpointManager *self, guint *out_length)
{
NMCheckpoint *checkpoint;
- char **strv;
+ const char **strv;
guint num, i = 0;
- num = g_hash_table_size (self->checkpoints);
- if (!num) {
- nm_assert (c_list_is_empty (&self->checkpoints_lst_head));
+ num = c_list_length (&self->checkpoints_lst_head);
+ NM_SET_OUT (out_length, num);
+ if (!num)
return NULL;
- }
- strv = g_new (char *, num + 1);
+ strv = g_new (const char *, num + 1);
c_list_for_each_entry (checkpoint, &self->checkpoints_lst_head, checkpoints_lst)
- strv[i++] = g_strdup (nm_dbus_object_get_path (NM_DBUS_OBJECT (checkpoint)));
+ strv[i++] = nm_dbus_object_get_path (NM_DBUS_OBJECT (checkpoint));
nm_assert (i == num);
strv[i] = NULL;
-
return strv;
}
@@ -335,11 +343,8 @@ nm_checkpoint_manager_new (NMManager *manager, GParamSpec *spec)
* of NMManager shall surpass the lifetime of the NMCheckpointManager
* instance. */
self->_manager = manager;
- self->checkpoints = g_hash_table_new_full (nm_str_hash, g_str_equal,
- NULL, item_destroy);
self->property_spec = spec;
c_list_init (&self->checkpoints_lst_head);
-
return self;
}
@@ -349,8 +354,7 @@ nm_checkpoint_manager_free (NMCheckpointManager *self)
if (!self)
return;
+ nm_checkpoint_manager_destroy_all (self);
nm_clear_g_source (&self->rollback_timeout_id);
- g_hash_table_destroy (self->checkpoints);
-
g_slice_free (NMCheckpointManager, self);
}
diff --git a/src/nm-checkpoint-manager.h b/src/nm-checkpoint-manager.h
index 812c1a0060..bcdf0d3602 100644
--- a/src/nm-checkpoint-manager.h
+++ b/src/nm-checkpoint-manager.h
@@ -31,14 +31,16 @@ NMCheckpointManager *nm_checkpoint_manager_new (NMManager *manager, GParamSpec *
void nm_checkpoint_manager_free (NMCheckpointManager *self);
+NMCheckpoint *nm_checkpoint_manager_lookup_by_path (NMCheckpointManager *self,
+ const char *path);
+
NMCheckpoint *nm_checkpoint_manager_create (NMCheckpointManager *self,
const char *const*device_names,
guint32 rollback_timeout,
NMCheckpointCreateFlags flags,
GError **error);
-gboolean nm_checkpoint_manager_destroy_all (NMCheckpointManager *self,
- GError **error);
+void nm_checkpoint_manager_destroy_all (NMCheckpointManager *self);
gboolean nm_checkpoint_manager_destroy (NMCheckpointManager *self,
const char *path,
@@ -48,6 +50,7 @@ gboolean nm_checkpoint_manager_rollback (NMCheckpointManager *self,
GVariant **results,
GError **error);
-char **nm_checkpoint_manager_get_checkpoint_paths (NMCheckpointManager *self);
+const char **nm_checkpoint_manager_get_checkpoint_paths (NMCheckpointManager *self,
+ guint *out_length);
#endif /* __NM_CHECKPOINT_MANAGER_H__ */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 20db36417a..b4ea40b3ec 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -6496,7 +6496,6 @@ get_property (GObject *object, guint prop_id,
NMConfigData *config_data;
const NMGlobalDnsConfig *dns_config;
const char *type;
- char **strv;
const char *path;
NMActiveConnection *ac;
GPtrArray *ptrarr;
@@ -6603,10 +6602,11 @@ get_property (GObject *object, guint prop_id,
TRUE)));
break;
case PROP_CHECKPOINTS:
- strv = NULL;
- if (priv->checkpoint_mgr)
- strv = nm_checkpoint_manager_get_checkpoint_paths (priv->checkpoint_mgr);
- g_value_take_boxed (value, strv);
+ g_value_take_boxed (value,
+ priv->checkpoint_mgr
+ ? nm_utils_strv_make_deep_copied (nm_checkpoint_manager_get_checkpoint_paths (priv->checkpoint_mgr,
+ NULL))
+ : NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -6689,10 +6689,7 @@ dispose (GObject *object)
nm_clear_g_source (&priv->devices_inited_id);
- if (priv->checkpoint_mgr) {
- nm_checkpoint_manager_destroy_all (priv->checkpoint_mgr, NULL);
- g_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_free);
- }
+ g_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_free);
if (priv->auth_mgr) {
g_signal_handlers_disconnect_by_func (priv->auth_mgr,