Send connman mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."
Today's Topics:
1. [PATCH] storage: write to settings file only when there is a
change. (Feng Wang)
2. [PATCH] stats: add "StatsDir" configuration to define the
directory of stats file. (Feng Wang)
3. Re: [PATCH] storage: write to settings file only when there
is a change. (Feng Wang)
----------------------------------------------------------------------
Message: 1
Date: Wed, 1 Jun 2016 16:51:01 -0700
From: Feng Wang <[email protected]>
To: [email protected]
Subject: [PATCH] storage: write to settings file only when there is a
change.
Message-ID: <[email protected]>
Minimize writes to the settings file such that there is only a write
when the data to br written has changed relative to the existed file.
---
src/storage.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 72 insertions(+), 5 deletions(-)
diff --git a/src/storage.c b/src/storage.c
index 7d03130..d78a045 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -58,6 +58,71 @@ static GKeyFile *storage_load(const char *pathname)
return keyfile;
}
+static bool storage_changed(GKeyFile *keyfile, char *pathname, gchar *data,
int length)
+{
+ GKeyFile *oldkeyfile = NULL;
+ gchar *olddata = NULL;
+ gsize oldlen = 0;
+ char id[100];
+ char *str, **strlist;
+ bool changed = false;
+
+ /* Get the service identifier pathname = "STORAGEDIR/id/settings" */
+ strcpy(id, pathname + strlen(STORAGEDIR) + 1);
+ str = strstr(id, SETTINGS);
+ if (str)
+ *(str-1) = 0;
+
+ /* Get existed configuration data on the disk */
+ oldkeyfile = storage_load(pathname);
+ if (oldkeyfile) {
+ /* Don't compare Domains if it is not in the current
configuration */
+ str = g_key_file_get_string(keyfile, id, "Domains", NULL);
+ if (!str)
+ g_key_file_remove_key(oldkeyfile, id, "Domains", NULL);
+ else
+ g_free(str);
+
+ /* Set old Modified time same as current modified time */
+ str = g_key_file_get_string(keyfile, id, "Modified", NULL);
+ if (str) {
+ g_key_file_set_string(oldkeyfile, id, "Modified", str);
+ g_free(str);
+ } else
+ g_key_file_remove_key(oldkeyfile, id, "Modified", NULL);
+
+ /* Don't compare DHCP configurations if not in the current
configuration */
+ str = g_key_file_get_string(keyfile, id,
"IPv4.DHCP.LastAddress", NULL);
+ if (!str)
+ g_key_file_remove_key(oldkeyfile, id,
"IPv4.DHCP.LastAddress", NULL);
+ else
+ g_free(str);
+
+ str = g_key_file_get_string(keyfile, id,
"IPv6.DHCP.LastAddress", NULL);
+ if (!str)
+ g_key_file_remove_key(oldkeyfile, id,
"IPv6.DHCP.LastAddress", NULL);
+ else
+ g_free(str);
+
+ strlist = g_key_file_get_string_list(keyfile, id,
"IPv6.DHCP.LastPrefixes",
+ &oldlen, NULL);
+ if (!strlist)
+ g_key_file_remove_key(oldkeyfile, id,
"IPv6.DHCP.LastPrefixes", NULL);
+ else
+ g_strfreev(strlist);
+
+ olddata = g_key_file_to_data(oldkeyfile, &oldlen, NULL);
+ g_key_file_free(oldkeyfile);
+ }
+
+ if (oldlen != length || memcmp(data, olddata, length))
+ changed = true;
+
+ g_free(olddata);
+
+ return changed;
+}
+
static int storage_save(GKeyFile *keyfile, char *pathname)
{
gchar *data = NULL;
@@ -66,11 +131,13 @@ static int storage_save(GKeyFile *keyfile, char *pathname)
int ret = 0;
data = g_key_file_to_data(keyfile, &length, NULL);
-
- if (!g_file_set_contents(pathname, data, length, &error)) {
- DBG("Failed to store information: %s", error->message);
- g_error_free(error);
- ret = -EIO;
+ if (storage_changed(keyfile, pathname, data, length)) {
+ connman_info("storage_save file %s len %d", pathname, length);
+ if (!g_file_set_contents(pathname, data, length, &error)) {
+ DBG("Failed to store information: %s", error->message);
+ g_error_free(error);
+ ret = -EIO;
+ }
}
g_free(data);
--
2.8.0.rc3.226.g39d4020
------------------------------
Message: 2
Date: Wed, 1 Jun 2016 16:51:59 -0700
From: Feng Wang <[email protected]>
To: [email protected]
Subject: [PATCH] stats: add "StatsDir" configuration to define the
directory of stats file.
Message-ID: <[email protected]>
user can put stats files in volatile memory(RAM) and STORAGEDIR in
non-volatile memory(FLASH) to prevent the flash wear-out because
of too many writes. If "StatsDir" is not defined, the default value
is STORAGEDIR.
---
include/setting.h | 1 +
src/main.c | 22 ++++++++++++++++++++++
src/stats.c | 9 +++++----
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/include/setting.h b/include/setting.h
index a882021..f492373 100644
--- a/include/setting.h
+++ b/include/setting.h
@@ -31,6 +31,7 @@ extern "C" {
bool connman_setting_get_bool(const char *key);
char **connman_setting_get_string_list(const char *key);
unsigned int *connman_setting_get_uint_list(const char *key);
+char *connman_setting_get_string(const char *key);
unsigned int connman_timeout_input_request(void);
unsigned int connman_timeout_browser_launch(void);
diff --git a/src/main.c b/src/main.c
index f44a2ed..62e3837 100644
--- a/src/main.c
+++ b/src/main.c
@@ -76,6 +76,7 @@ static struct {
char **tethering_technologies;
bool persistent_tethering_mode;
bool enable_6to4;
+ char *statsdir;
} connman_settings = {
.bg_scan = true,
.pref_timeservers = NULL,
@@ -90,6 +91,7 @@ static struct {
.tethering_technologies = NULL,
.persistent_tethering_mode = false,
.enable_6to4 = false,
+ .statsdir = NULL,
};
#define CONF_BG_SCAN "BackgroundScanning"
@@ -105,6 +107,7 @@ static struct {
#define CONF_TETHERING_TECHNOLOGIES "TetheringTechnologies"
#define CONF_PERSISTENT_TETHERING_MODE "PersistentTetheringMode"
#define CONF_ENABLE_6TO4 "Enable6to4"
+#define CONF_STATS_DIR "StatsDir"
static const char *supported_options[] = {
CONF_BG_SCAN,
@@ -120,6 +123,7 @@ static const char *supported_options[] = {
CONF_TETHERING_TECHNOLOGIES,
CONF_PERSISTENT_TETHERING_MODE,
CONF_ENABLE_6TO4,
+ CONF_STATS_DIR,
NULL
};
@@ -244,6 +248,7 @@ static void parse_config(GKeyFile *config)
char **tethering;
gsize len;
int timeout;
+ char *statsdir;
if (!config) {
connman_settings.auto_connect =
@@ -367,6 +372,15 @@ static void parse_config(GKeyFile *config)
connman_settings.enable_6to4 = boolean;
g_clear_error(&error);
+
+ statsdir = __connman_config_get_string(config, "General",
+ CONF_STATS_DIR, &error);
+ if (!error)
+ connman_settings.statsdir = statsdir;
+ else
+ connman_settings.statsdir = g_strdup(STORAGEDIR);
+
+ g_clear_error(&error);
}
static int config_init(const char *file)
@@ -564,6 +578,14 @@ char **connman_setting_get_string_list(const char *key)
return NULL;
}
+char *connman_setting_get_string(const char *key)
+{
+ if (g_str_equal(key, CONF_STATS_DIR))
+ return connman_settings.statsdir;
+
+ return NULL;
+}
+
unsigned int *connman_setting_get_uint_list(const char *key)
{
if (g_str_equal(key, CONF_AUTO_CONNECT))
diff --git a/src/stats.c b/src/stats.c
index 26343b1..3958e17 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -350,7 +350,7 @@ static int stats_open(struct stats_file *file,
static int stats_open_temp(struct stats_file *file)
{
file->name = g_strdup_printf("%s/stats.XXXXXX.tmp",
- STORAGEDIR);
+ connman_setting_get_string("StatsDir"));
file->fd = g_mkstemp_full(file->name, O_RDWR | O_CREAT, 0644);
if (file->fd < 0) {
connman_error("create tempory file error %s for %s",
@@ -687,7 +687,7 @@ int __connman_stats_service_register(struct connman_service
*service)
return -EALREADY;
}
- dir = g_strdup_printf("%s/%s", STORAGEDIR,
+ dir = g_strdup_printf("%s/%s", connman_setting_get_string("StatsDir"),
__connman_service_get_ident(service));
/* If the dir doesn't exist, create it */
@@ -704,9 +704,10 @@ int __connman_stats_service_register(struct
connman_service *service)
g_free(dir);
- name = g_strdup_printf("%s/%s/data", STORAGEDIR,
+ name = g_strdup_printf("%s/%s/data",
connman_setting_get_string("StatsDir"),
__connman_service_get_ident(service));
- file->history_name = g_strdup_printf("%s/%s/history", STORAGEDIR,
+ file->history_name = g_strdup_printf("%s/%s/history",
+ connman_setting_get_string("StatsDir"),
__connman_service_get_ident(service));
/* TODO: Use a global config file instead of hard coded value. */
--
2.8.0.rc3.226.g39d4020
------------------------------
Message: 3
Date: Wed, 1 Jun 2016 17:14:45 -0700
From: Feng Wang <[email protected]>
To: [email protected]
Subject: Re: [PATCH] storage: write to settings file only when there
is a change.
Message-ID:
<cag09-dlrgmid_f0orrapspxkr3ikwzwb2dbatzgkpopj2ue...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
More explanations about this patch and the other patch about "stats: add
"StatsDir" configuration to define the directory of stats file."
The STORAGEDIR (defined as /var/lib/connman) includes xxx.config, settings
and wifi_xxxx directories. Normally it is put to non-volatile memory(i.e
NAND flash). The "settings" and "data" file under wifi_xxx directory are
updated frequently. Whenever the connection goes to READY state, both
files are updated. And there are other situation of updating the
"data" files too. This will cause the flash wear-out quickly. Normally the
flash has 100,000 program/erase cycle. If a unit kept disconnecting and
reconnecting, it is very bad for the flash.
So the fix is to write the settings file only when there are some changes.
If a device connected to the same AP and there is no change in the AP, the
settings file will never be written again after it got connected ok once.
The other fix about the stats is to allow user to put the "data" and
"history" files to a non-volatile memory(RAM) to protect the flash.
On Wed, Jun 1, 2016 at 4:51 PM, Feng Wang <[email protected]> wrote:
> Minimize writes to the settings file such that there is only a write
> when the data to br written has changed relative to the existed file.
> ---
> src/storage.c | 77
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 72 insertions(+), 5 deletions(-)
>
> diff --git a/src/storage.c b/src/storage.c
> index 7d03130..d78a045 100644
> --- a/src/storage.c
> +++ b/src/storage.c
> @@ -58,6 +58,71 @@ static GKeyFile *storage_load(const char *pathname)
> return keyfile;
> }
>
> +static bool storage_changed(GKeyFile *keyfile, char *pathname, gchar
> *data, int length)
> +{
> + GKeyFile *oldkeyfile = NULL;
> + gchar *olddata = NULL;
> + gsize oldlen = 0;
> + char id[100];
> + char *str, **strlist;
> + bool changed = false;
> +
> + /* Get the service identifier pathname = "STORAGEDIR/id/settings"
> */
> + strcpy(id, pathname + strlen(STORAGEDIR) + 1);
> + str = strstr(id, SETTINGS);
> + if (str)
> + *(str-1) = 0;
> +
> + /* Get existed configuration data on the disk */
> + oldkeyfile = storage_load(pathname);
> + if (oldkeyfile) {
> + /* Don't compare Domains if it is not in the current
> configuration */
> + str = g_key_file_get_string(keyfile, id, "Domains", NULL);
> + if (!str)
> + g_key_file_remove_key(oldkeyfile, id, "Domains",
> NULL);
> + else
> + g_free(str);
> +
> + /* Set old Modified time same as current modified time */
> + str = g_key_file_get_string(keyfile, id, "Modified", NULL);
> + if (str) {
> + g_key_file_set_string(oldkeyfile, id, "Modified",
> str);
> + g_free(str);
> + } else
> + g_key_file_remove_key(oldkeyfile, id, "Modified",
> NULL);
> +
> + /* Don't compare DHCP configurations if not in the current
> configuration */
> + str = g_key_file_get_string(keyfile, id,
> "IPv4.DHCP.LastAddress", NULL);
> + if (!str)
> + g_key_file_remove_key(oldkeyfile, id,
> "IPv4.DHCP.LastAddress", NULL);
> + else
> + g_free(str);
> +
> + str = g_key_file_get_string(keyfile, id,
> "IPv6.DHCP.LastAddress", NULL);
> + if (!str)
> + g_key_file_remove_key(oldkeyfile, id,
> "IPv6.DHCP.LastAddress", NULL);
> + else
> + g_free(str);
> +
> + strlist = g_key_file_get_string_list(keyfile, id,
> "IPv6.DHCP.LastPrefixes",
> + &oldlen, NULL);
> + if (!strlist)
> + g_key_file_remove_key(oldkeyfile, id,
> "IPv6.DHCP.LastPrefixes", NULL);
> + else
> + g_strfreev(strlist);
> +
> + olddata = g_key_file_to_data(oldkeyfile, &oldlen, NULL);
> + g_key_file_free(oldkeyfile);
> + }
> +
> + if (oldlen != length || memcmp(data, olddata, length))
> + changed = true;
> +
> + g_free(olddata);
> +
> + return changed;
> +}
> +
> static int storage_save(GKeyFile *keyfile, char *pathname)
> {
> gchar *data = NULL;
> @@ -66,11 +131,13 @@ static int storage_save(GKeyFile *keyfile, char
> *pathname)
> int ret = 0;
>
> data = g_key_file_to_data(keyfile, &length, NULL);
> -
> - if (!g_file_set_contents(pathname, data, length, &error)) {
> - DBG("Failed to store information: %s", error->message);
> - g_error_free(error);
> - ret = -EIO;
> + if (storage_changed(keyfile, pathname, data, length)) {
> + connman_info("storage_save file %s len %d", pathname,
> length);
> + if (!g_file_set_contents(pathname, data, length, &error)) {
> + DBG("Failed to store information: %s",
> error->message);
> + g_error_free(error);
> + ret = -EIO;
> + }
> }
>
> g_free(data);
> --
> 2.8.0.rc3.226.g39d4020
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.01.org/pipermail/connman/attachments/20160601/c62bd57f/attachment.html>
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman
------------------------------
End of connman Digest, Vol 8, Issue 2
*************************************