Commit 79458a55 authored by Thomas Haller's avatar Thomas Haller

checkpoint: don't explicitly track checkpoints in a GHashTable

We already have a GHashTable for exported objects. We can use
that if we want to look up by path efficiently.
parent 63e3bff9
......@@ -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 (nm_dbus_object_is_exported (NM_DBUS_OBJECT (checkpoint)));
nm_assert (c_list_contains (&self->checkpoints_lst_head, &checkpoint->checkpoints_lst));
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);
......@@ -214,31 +212,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
......@@ -246,25 +238,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
......@@ -280,7 +275,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);
......@@ -288,31 +283,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;
}
......@@ -334,11 +342,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;
}
......@@ -348,8 +353,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);
}
......@@ -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__ */
......@@ -6471,7 +6471,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;
......@@ -6578,10 +6577,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);
......@@ -6664,10 +6664,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,
......
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