summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device.c2
-rw-r--r--src/main.c2
-rw-r--r--src/nm-active-connection.c2
-rw-r--r--src/nm-manager.c2
-rw-r--r--src/settings/nm-settings-connection.c293
-rw-r--r--src/settings/nm-settings-connection.h13
-rw-r--r--src/settings/nm-settings.c157
-rw-r--r--src/settings/nm-settings.h2
8 files changed, 266 insertions, 207 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 1a9a8a3745..bec6bb4c14 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -15118,7 +15118,7 @@ _set_state_full (NMDevice *self,
* and those we haven't tried yet (no timestamp).
*/
if (sett_conn && !nm_settings_connection_get_timestamp (sett_conn, NULL))
- nm_settings_connection_update_timestamp (sett_conn, (guint64) 0, TRUE);
+ nm_settings_connection_update_timestamp (sett_conn, (guint64) 0);
/* Schedule the transition to DISCONNECTED. The device can't transition
* immediately because we can't change states again from the state
diff --git a/src/main.c b/src/main.c
index 9f979cf4dc..02a4210532 100644
--- a/src/main.c
+++ b/src/main.c
@@ -458,6 +458,8 @@ done:
nm_dns_manager_stop (nm_dns_manager_get ());
+ nm_settings_kf_db_write (NM_SETTINGS_GET);
+
done_no_manager:
if (global_opt.pidfile && wrote_pidfile)
unlink (global_opt.pidfile);
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 17568c30b5..d28588c989 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -285,7 +285,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (priv->settings_connection.obj,
- (guint64) time (NULL), TRUE);
+ (guint64) time (NULL));
}
if (priv->device) {
diff --git a/src/nm-manager.c b/src/nm-manager.c
index c0cd15c0cd..3622a0a5ad 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -7313,7 +7313,7 @@ periodic_update_active_connection_timestamps (gpointer user_data)
c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) {
if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (nm_active_connection_get_settings_connection (ac),
- (guint64) time (NULL), FALSE);
+ (guint64) time (NULL));
}
}
return G_SOURCE_CONTINUE;
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 3fdaa59814..3bb30cbe57 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -25,6 +25,7 @@
#include "c-list/src/c-list.h"
+#include "nm-glib-aux/nm-keyfile-aux.h"
#include "nm-libnm-core-intern/nm-common-macros.h"
#include "nm-config.h"
#include "nm-config-data.h"
@@ -38,9 +39,6 @@
#include "nm-core-internal.h"
#include "nm-audit-manager.h"
-#define SETTINGS_TIMESTAMPS_FILE NMSTATEDIR "/timestamps"
-#define SETTINGS_SEEN_BSSIDS_FILE NMSTATEDIR "/seen-bssids"
-
#define AUTOCONNECT_RETRIES_UNSET -2
#define AUTOCONNECT_RETRIES_FOREVER -1
#define AUTOCONNECT_RESET_RETRIES_TIMER 300
@@ -86,6 +84,9 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _NMSettingsConnectionPrivate {
+ NMKeyFileDB *kf_db_timestamps;
+ NMKeyFileDB *kf_db_seen_bssids;
+
NMAgentManager *agent_mgr;
NMSessionMonitor *session_monitor;
gulong session_changed_id;
@@ -658,42 +659,6 @@ out:
return TRUE;
}
-static void
-remove_entry_from_db (NMSettingsConnection *self, const char* db_name)
-{
- GKeyFile *key_file;
- const char *db_file;
-
- if (strcmp (db_name, "timestamps") == 0)
- db_file = SETTINGS_TIMESTAMPS_FILE;
- else if (strcmp (db_name, "seen-bssids") == 0)
- db_file = SETTINGS_SEEN_BSSIDS_FILE;
- else
- return;
-
- key_file = g_key_file_new ();
- if (g_key_file_load_from_file (key_file, db_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
- const char *connection_uuid;
- char *data;
- gsize len;
- GError *error = NULL;
-
- connection_uuid = nm_settings_connection_get_uuid (self);
-
- g_key_file_remove_key (key_file, db_name, connection_uuid, NULL);
- data = g_key_file_to_data (key_file, &len, &error);
- if (data) {
- g_file_set_contents (db_file, data, len, &error);
- g_free (data);
- }
- if (error) {
- _LOGW ("error writing %s file '%s': %s", db_name, db_file, error->message);
- g_error_free (error);
- }
- }
- g_key_file_free (key_file);
-}
-
gboolean
nm_settings_connection_delete (NMSettingsConnection *self,
GError **error)
@@ -701,6 +666,7 @@ nm_settings_connection_delete (NMSettingsConnection *self,
gs_unref_object NMSettingsConnection *self_keep_alive = NULL;
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMConnection *for_agents;
+ const char *connection_uuid;
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE);
@@ -719,11 +685,13 @@ nm_settings_connection_delete (NMSettingsConnection *self,
for_agents);
g_object_unref (for_agents);
- /* Remove timestamp from timestamps database file */
- remove_entry_from_db (self, "timestamps");
+ connection_uuid = nm_settings_connection_get_uuid (self);
+
+ if (priv->kf_db_timestamps)
+ nm_key_file_db_remove_key (priv->kf_db_timestamps, connection_uuid);
- /* Remove connection from seen-bssids database file */
- remove_entry_from_db (self, "seen-bssids");
+ if (priv->kf_db_seen_bssids)
+ nm_key_file_db_remove_key (priv->kf_db_seen_bssids, connection_uuid);
nm_settings_connection_signal_remove (self);
return TRUE;
@@ -2338,11 +2306,13 @@ gboolean
nm_settings_connection_get_timestamp (NMSettingsConnection *self,
guint64 *out_timestamp)
{
+ NMSettingsConnectionPrivate *priv;
+
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE);
- if (out_timestamp)
- *out_timestamp = NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp;
- return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp_set;
+ priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
+ NM_SET_OUT (out_timestamp, priv->timestamp);
+ return priv->timestamp_set;
}
/**
@@ -2350,56 +2320,31 @@ nm_settings_connection_get_timestamp (NMSettingsConnection *self,
* @self: the #NMSettingsConnection
* @timestamp: timestamp to set into the connection and to store into
* the timestamps database
- * @flush_to_disk: if %TRUE, commit timestamp update to persistent storage
*
* Updates the connection and timestamps database with the provided timestamp.
**/
void
nm_settings_connection_update_timestamp (NMSettingsConnection *self,
- guint64 timestamp,
- gboolean flush_to_disk)
+ guint64 timestamp)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
const char *connection_uuid;
- GKeyFile *timestamps_file;
- char *data, *tmp;
- gsize len;
- GError *error = NULL;
+ char sbuf[60];
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self));
- /* Update timestamp in private storage */
priv->timestamp = timestamp;
priv->timestamp_set = TRUE;
- if (flush_to_disk == FALSE)
- return;
- if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD)
+ if (!priv->kf_db_timestamps)
return;
- /* Save timestamp to timestamps database file */
- timestamps_file = g_key_file_new ();
- if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- _LOGW ("error parsing timestamps file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message);
- g_clear_error (&error);
- }
-
connection_uuid = nm_settings_connection_get_uuid (self);
- tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
- g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp);
- g_free (tmp);
-
- data = g_key_file_to_data (timestamps_file, &len, &error);
- if (data) {
- g_file_set_contents (SETTINGS_TIMESTAMPS_FILE, data, len, &error);
- g_free (data);
+ if (connection_uuid) {
+ nm_key_file_db_set_value (priv->kf_db_timestamps,
+ connection_uuid,
+ nm_sprintf_buf (sbuf, "%" G_GUINT64_FORMAT, timestamp));
}
- if (error) {
- _LOGW ("error saving timestamp to file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message);
- g_error_free (error);
- }
- g_key_file_free (timestamps_file);
}
/**
@@ -2410,38 +2355,79 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *self,
* stores it into the connection private data.
**/
void
-nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self)
+nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
+ NMKeyFileDB *kf_db_timestamps,
+ NMKeyFileDB *kf_db_seen_bssids)
{
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- gs_unref_keyfile GKeyFile *timestamps_file = NULL;
- gs_free_error GError *error = NULL;
- gs_free char *tmp_str = NULL;
+ NMSettingsConnectionPrivate *priv;
const char *connection_uuid;
- gint64 timestamp;
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self));
+ g_return_if_fail (kf_db_timestamps);
+ g_return_if_fail (kf_db_seen_bssids);
- timestamps_file = g_key_file_new ();
- if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- _LOGD ("failed to read connection timestamp: %s", error->message);
- return;
- }
+ priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
connection_uuid = nm_settings_connection_get_uuid (self);
- tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &error);
- if (!tmp_str) {
- _LOGD ("failed to read connection timestamp: %s", error->message);
- return;
- }
- timestamp = _nm_utils_ascii_str_to_int64 (tmp_str, 10, 0, G_MAXINT64, -1);
- if (timestamp < 0) {
- _LOGD ("failed to read connection timestamp: %s", "invalid number");
- return;
+ if (priv->kf_db_timestamps != kf_db_timestamps) {
+ gs_free char *tmp_str = NULL;
+ guint64 timestamp;
+
+ nm_key_file_db_unref (priv->kf_db_timestamps);
+ priv->kf_db_timestamps = nm_key_file_db_ref (kf_db_timestamps);
+
+ tmp_str = nm_key_file_db_get_value (priv->kf_db_timestamps, connection_uuid);
+
+ timestamp = _nm_utils_ascii_str_to_uint64 (tmp_str, 10, 0, G_MAXUINT64, G_MAXUINT64);
+ if (timestamp != G_MAXUINT64) {
+ priv->timestamp = timestamp;
+ priv->timestamp_set = TRUE;
+ _LOGT ("read timestamp %"G_GUINT64_FORMAT" from keyfile database \"%s\"",
+ timestamp, nm_key_file_db_get_filename (priv->kf_db_timestamps));
+ } else
+ _LOGT ("no timestamp from keyfile database \"%s\"",
+ nm_key_file_db_get_filename (priv->kf_db_timestamps));
}
- priv->timestamp = timestamp;
- priv->timestamp_set = TRUE;
+ if (priv->kf_db_seen_bssids != kf_db_seen_bssids) {
+ gs_strfreev char **tmp_strv = NULL;
+ gsize i, len;
+
+ nm_key_file_db_unref (priv->kf_db_seen_bssids);
+ priv->kf_db_seen_bssids = nm_key_file_db_ref (kf_db_seen_bssids);
+
+ tmp_strv = nm_key_file_db_get_string_list (priv->kf_db_seen_bssids, connection_uuid, &len);
+
+ if (tmp_strv) {
+ _LOGT ("read %zu seen-bssids from keyfile database \"%s\"",
+ NM_PTRARRAY_LEN (tmp_strv),
+ nm_key_file_db_get_filename (priv->kf_db_seen_bssids));
+ g_hash_table_remove_all (priv->seen_bssids);
+ for (i = len; i > 0; )
+ g_hash_table_add (priv->seen_bssids, g_steal_pointer (&tmp_strv[--i]));
+ } else {
+ NMSettingWireless *s_wifi;
+
+ _LOGT ("no seen-bssids from keyfile database \"%s\"",
+ nm_key_file_db_get_filename (priv->kf_db_seen_bssids));
+
+ /* If this connection didn't have an entry in the seen-bssids database,
+ * maybe this is the first time we've read it in, so populate the
+ * seen-bssids list from the deprecated seen-bssids property of the
+ * wifi setting.
+ */
+ s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (self));
+ if (s_wifi) {
+ len = nm_setting_wireless_get_num_seen_bssids (s_wifi);
+ for (i = 0; i < len; i++) {
+ const char *bssid = nm_setting_wireless_get_seen_bssid (s_wifi, i);
+
+ g_hash_table_add (priv->seen_bssids, g_strdup (bssid));
+ }
+ }
+ }
+ }
}
/**
@@ -2504,108 +2490,26 @@ nm_settings_connection_add_seen_bssid (NMSettingsConnection *self,
const char *seen_bssid)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
+ gs_free const char **strv = NULL;
const char *connection_uuid;
- GKeyFile *seen_bssids_file;
- char *data, *bssid_str;
- const char **list;
- gsize len;
- GError *error = NULL;
- GHashTableIter iter;
- guint n;
g_return_if_fail (seen_bssid != NULL);
- if (g_hash_table_lookup (priv->seen_bssids, seen_bssid))
- return; /* Already in the list */
-
- /* Add the new BSSID; let the hash take ownership of the allocated BSSID string */
- bssid_str = g_strdup (seen_bssid);
- g_hash_table_insert (priv->seen_bssids, bssid_str, bssid_str);
+ g_hash_table_add (priv->seen_bssids, g_strdup (seen_bssid));
- /* Build up a list of all the BSSIDs in string form */
- n = 0;
- list = g_malloc0 (g_hash_table_size (priv->seen_bssids) * sizeof (char *));
- g_hash_table_iter_init (&iter, priv->seen_bssids);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &bssid_str))
- list[n++] = bssid_str;
-
- /* Save BSSID to seen-bssids file */
- seen_bssids_file = g_key_file_new ();
- g_key_file_set_list_separator (seen_bssids_file, ',');
- if (!g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
- _LOGW ("error parsing seen-bssids file '%s': %s",
- SETTINGS_SEEN_BSSIDS_FILE, error->message);
- }
- g_clear_error (&error);
- }
+ if (!priv->kf_db_seen_bssids)
+ return;
connection_uuid = nm_settings_connection_get_uuid (self);
- g_key_file_set_string_list (seen_bssids_file, "seen-bssids", connection_uuid, list, n);
- g_free (list);
+ if (!connection_uuid)
+ return;
- data = g_key_file_to_data (seen_bssids_file, &len, &error);
- if (data) {
- g_file_set_contents (SETTINGS_SEEN_BSSIDS_FILE, data, len, &error);
- g_free (data);
- }
- g_key_file_free (seen_bssids_file);
+ strv = nm_utils_strdict_get_keys (priv->seen_bssids, TRUE, NULL);
- if (error) {
- _LOGW ("error saving seen-bssids to file '%s': %s",
- SETTINGS_SEEN_BSSIDS_FILE, error->message);
- g_error_free (error);
- }
-}
-
-/**
- * nm_settings_connection_read_and_fill_seen_bssids:
- * @self: the #NMSettingsConnection
- *
- * Retrieves seen BSSIDs of the connection from database file and stores then into the
- * connection private data.
- **/
-void
-nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self)
-{
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- const char *connection_uuid;
- GKeyFile *seen_bssids_file;
- char **tmp_strv = NULL;
- gsize i, len = 0;
- NMSettingWireless *s_wifi;
-
- /* Get seen BSSIDs from database file */
- seen_bssids_file = g_key_file_new ();
- g_key_file_set_list_separator (seen_bssids_file, ',');
- if (g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
- connection_uuid = nm_settings_connection_get_uuid (self);
- tmp_strv = g_key_file_get_string_list (seen_bssids_file, "seen-bssids", connection_uuid, &len, NULL);
- }
- g_key_file_free (seen_bssids_file);
-
- /* Update connection's seen-bssids */
- if (tmp_strv) {
- g_hash_table_remove_all (priv->seen_bssids);
- for (i = 0; i < len; i++)
- g_hash_table_insert (priv->seen_bssids, tmp_strv[i], tmp_strv[i]);
- g_free (tmp_strv);
- } else {
- /* If this connection didn't have an entry in the seen-bssids database,
- * maybe this is the first time we've read it in, so populate the
- * seen-bssids list from the deprecated seen-bssids property of the
- * wifi setting.
- */
- s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (self));
- if (s_wifi) {
- len = nm_setting_wireless_get_num_seen_bssids (s_wifi);
- for (i = 0; i < len; i++) {
- char *bssid_dup = g_strdup (nm_setting_wireless_get_seen_bssid (s_wifi, i));
-
- g_hash_table_insert (priv->seen_bssids, bssid_dup, bssid_dup);
- }
- }
- }
+ nm_key_file_db_set_string_list (priv->kf_db_seen_bssids,
+ connection_uuid,
+ strv ?: NM_PTRARRAY_EMPTY (const char *),
+ -1);
}
/*****************************************************************************/
@@ -2932,6 +2836,9 @@ dispose (GObject *object)
g_clear_pointer (&priv->filename, g_free);
+ g_clear_pointer (&priv->kf_db_timestamps, nm_key_file_db_unref);
+ g_clear_pointer (&priv->kf_db_seen_bssids, nm_key_file_db_unref);
+
G_OBJECT_CLASS (nm_settings_connection_parent_class)->dispose (object);
}
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index e796b71645..c23f68fcdc 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -220,14 +220,17 @@ int nm_settings_connection_cmp_timestamp_p_with_data (gconstpointer pa, gconstpo
int nm_settings_connection_cmp_autoconnect_priority (NMSettingsConnection *a, NMSettingsConnection *b);
int nm_settings_connection_cmp_autoconnect_priority_p_with_data (gconstpointer pa, gconstpointer pb, gpointer user_data);
+struct _NMKeyFileDB;
+
+void nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
+ struct _NMKeyFileDB *kf_db_timestamps,
+ struct _NMKeyFileDB *kf_db_seen_bssids);
+
gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *self,
guint64 *out_timestamp);
void nm_settings_connection_update_timestamp (NMSettingsConnection *self,
- guint64 timestamp,
- gboolean flush_to_disk);
-
-void nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self);
+ guint64 timestamp);
char **nm_settings_connection_get_seen_bssids (NMSettingsConnection *self);
@@ -237,8 +240,6 @@ gboolean nm_settings_connection_has_seen_bssid (NMSettingsConnection *self,
void nm_settings_connection_add_seen_bssid (NMSettingsConnection *self,
const char *seen_bssid);
-void nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self);
-
int nm_settings_connection_autoconnect_retries_get (NMSettingsConnection *self);
void nm_settings_connection_autoconnect_retries_set (NMSettingsConnection *self,
int retries);
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 8e18a33e0d..18907a9965 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -37,6 +37,7 @@
#endif
#include "nm-libnm-core-intern/nm-common-macros.h"
+#include "nm-glib-aux/nm-keyfile-aux.h"
#include "nm-dbus-interface.h"
#include "nm-connection.h"
#include "nm-setting-8021x.h"
@@ -119,6 +120,9 @@ typedef struct {
GSList *plugins;
+ NMKeyFileDB *kf_db_timestamps;
+ NMKeyFileDB *kf_db_seen_bssids;
+
CList connections_lst_head;
NMSettingsConnection **connections_cached_list;
@@ -131,6 +135,9 @@ typedef struct {
guint connections_len;
+ guint kf_db_flush_idle_id_timestamps;
+ guint kf_db_flush_idle_id_seen_bssids;
+
bool started:1;
bool startup_complete:1;
bool connections_loaded:1;
@@ -935,11 +942,9 @@ claim_connection (NMSettings *self, NMSettingsConnection *sett_conn)
return;
}
- /* Read timestamp from look-aside file and put it into the connection's data */
- nm_settings_connection_read_and_fill_timestamp (sett_conn);
-
- /* Read seen-bssids from look-aside file and put it into the connection's data */
- nm_settings_connection_read_and_fill_seen_bssids (sett_conn);
+ nm_settings_connection_register_kf_dbs (sett_conn,
+ priv->kf_db_timestamps,
+ priv->kf_db_seen_bssids);
/* Ensure its initial visibility is up-to-date */
nm_settings_connection_recheck_visibility (sett_conn);
@@ -1764,6 +1769,128 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quittin
/*****************************************************************************/
+G_GNUC_PRINTF (4, 5)
+static void
+_kf_db_log_fcn (NMKeyFileDB *kf_db,
+ int syslog_level,
+ gpointer user_data,
+ const char *fmt,
+ ...)
+{
+ NMSettings *self = user_data;
+ NMLogLevel level = nm_log_level_from_syslog (syslog_level);
+
+ if (_NMLOG_ENABLED (level)) {
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ gs_free char *msg = NULL;
+ va_list ap;
+ const char *prefix;
+
+ va_start (ap, fmt);
+ msg = g_strdup_vprintf (fmt, ap);
+ va_end (ap);
+
+ if (priv->kf_db_timestamps == kf_db)
+ prefix = "timestamps";
+ else if (priv->kf_db_seen_bssids == kf_db)
+ prefix = "seen-bssids";
+ else {
+ nm_assert_not_reached ();
+ prefix = "???";
+ }
+
+ _NMLOG (level, "[%s-keyfile]: %s", prefix, msg);
+ }
+}
+
+static gboolean
+_kf_db_got_dirty_flush (NMSettings *self,
+ gboolean is_timestamps)
+{
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ const char *prefix;
+ NMKeyFileDB *kf_db;
+
+ if (is_timestamps) {
+ prefix = "timestamps";
+ kf_db = priv->kf_db_timestamps;
+ priv->kf_db_flush_idle_id_timestamps = 0;
+ } else {
+ prefix = "seen-bssids";
+ kf_db = priv->kf_db_seen_bssids;
+ priv->kf_db_flush_idle_id_seen_bssids = 0;
+ }
+
+ if (nm_key_file_db_is_dirty (kf_db))
+ nm_key_file_db_to_file (kf_db, FALSE);
+ else {
+ _LOGT ("[%s-keyfile]: skip saving changes to \"%s\"",
+ prefix,
+ nm_key_file_db_get_filename (kf_db));
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+_kf_db_got_dirty_flush_timestamps_cb (gpointer user_data)
+{
+ return _kf_db_got_dirty_flush (user_data,
+ TRUE);
+}
+
+static gboolean
+_kf_db_got_dirty_flush_seen_bssids_cb (gpointer user_data)
+{
+ return _kf_db_got_dirty_flush (user_data,
+ FALSE);
+}
+
+static void
+_kf_db_got_dirty_fcn (NMKeyFileDB *kf_db,
+ gpointer user_data)
+{
+ NMSettings *self = user_data;
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ GSourceFunc idle_func;
+ guint *p_id;
+ const char *prefix;
+
+ if (priv->kf_db_timestamps == kf_db) {
+ prefix = "timestamps";
+ p_id = &priv->kf_db_flush_idle_id_timestamps;
+ idle_func = _kf_db_got_dirty_flush_timestamps_cb;
+ } else if (priv->kf_db_seen_bssids == kf_db) {
+ prefix = "seen-bssids";
+ p_id = &priv->kf_db_flush_idle_id_seen_bssids;
+ idle_func = _kf_db_got_dirty_flush_seen_bssids_cb;
+ } else {
+ nm_assert_not_reached ();
+ return;
+ }
+
+ if (*p_id != 0)
+ return;
+ _LOGT ("[%s-keyfile]: schedule flushing changes to disk", prefix);
+ *p_id = g_idle_add_full (G_PRIORITY_LOW, idle_func, self, NULL);
+}
+
+void
+nm_settings_kf_db_write (NMSettings *self)
+{
+ NMSettingsPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTINGS (self));
+
+ priv = NM_SETTINGS_GET_PRIVATE (self);
+ if (priv->kf_db_timestamps)
+ nm_key_file_db_to_file (priv->kf_db_timestamps, TRUE);
+ if (priv->kf_db_seen_bssids)
+ nm_key_file_db_to_file (priv->kf_db_seen_bssids, TRUE);
+}
+
+/*****************************************************************************/
+
const char *
nm_settings_get_startup_complete_blocked_reason (NMSettings *self)
{
@@ -1797,6 +1924,19 @@ nm_settings_start (NMSettings *self, GError **error)
priv = NM_SETTINGS_GET_PRIVATE (self);
+ priv->kf_db_timestamps = nm_key_file_db_new (NMSTATEDIR "/timestamps",
+ "timestamps",
+ _kf_db_log_fcn,
+ _kf_db_got_dirty_fcn,
+ self);
+ priv->kf_db_seen_bssids = nm_key_file_db_new (NMSTATEDIR "/seen-bssids",
+ "seen-bssids",
+ _kf_db_log_fcn,
+ _kf_db_got_dirty_fcn,
+ self);
+ nm_key_file_db_start (priv->kf_db_timestamps);
+ nm_key_file_db_start (priv->kf_db_seen_bssids);
+
/* Load the plugins; fail if a plugin is not found. */
plugins = nm_config_data_get_plugins (nm_config_get_data_orig (priv->config), TRUE);
@@ -1933,6 +2073,13 @@ finalize (GObject *object)
g_clear_object (&priv->config);
+ nm_clear_g_source (&priv->kf_db_flush_idle_id_timestamps);
+ nm_clear_g_source (&priv->kf_db_flush_idle_id_seen_bssids);
+ nm_key_file_db_to_file (priv->kf_db_timestamps, FALSE);
+ nm_key_file_db_to_file (priv->kf_db_seen_bssids, FALSE);
+ nm_key_file_db_destroy (priv->kf_db_timestamps);
+ nm_key_file_db_destroy (priv->kf_db_seen_bssids);
+
G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object);
}
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index eb74c09c4a..a3bd26a938 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -114,4 +114,6 @@ void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean qu
const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self);
+void nm_settings_kf_db_write (NMSettings *settings);
+
#endif /* __NM_SETTINGS_H__ */