persistent property store - first try
Kay Sievers
kay.sievers at vrfy.org
Thu Jun 10 05:14:27 PDT 2004
On Wed, Jun 09, 2004 at 03:57:58AM +0200, Kay Sievers wrote:
Here is a new version which creates, saves and reads the uuid for store.
The uuid is handled by calling hal_pstore_init("/var/lib/hal") as the
very first action. So every call to hal_pstore_open(<path>) will create
a new store with the uuid as the last directory (e.g. for storing per box
data in the users $HOME).
The "/org/freedesktop/HAL" is now stripped from the udi, one saved
property in the store looks like this now:
[root at pim root]# tree /var/lib/hal/
/var/lib/hal/
|-- pim-40c84c4e
| `-- devices
| `-- usb_46d_c00e_1100_-1_noserial
| `-- save.key
`-- uuid
The save action is still only triggered (by the dirty hack) if the
property name begins with "save*". You can watch it by doing:
hal-set-property --udi /org/freedesktop/Hal/devices/usb_46d_c00e_1100_-1_noserial --string yeah2 --key save.key
Hmm, we may add a "persistent" attribute to "struct _HalProperty" and a
look at this attribute if hal_device_property_set_<type>() is called?
So we can set this attribute if persistence is wanted.
thanks,
Kay
> here is a first try to store properties on disk. Please have a look, if
> we can do it this way. The properties are stored in a directory
> with the udi as the name. HAL creates a uuid starting with the hostname
> to be able to store user properies in a .hal/ directory home, so every box
> can have its own data in the users $HOME.
>
> [kay at pim kay]$ tree /var/lib/hal/
> /var/lib/hal/
> `-- pim-95a478b32fa0
> `-- org
> `-- freedesktop
> `-- Hal
> `-- devices
> |-- pci_8086_3340
> | `-- save.key
> `-- usb_46d_c00e_1100_-1_noserial
> |-- flag
> |-- flag.true
> |-- number
> |-- save.key
> |-- save.key2
> `-- save.key3
>
> [kay at pim usb_46d_c00e_1100_-1_noserial]$ cat save.key
> String:yeah
>
>
> Just open a store with:
> hal_pstore_open("/var/lib/hal");
>
> and save a property with:
> hal_pstore_save_property(store, device, property);
> (A directory will be created and the value is saved to the file)
>
> to read one attribute back, call:
> hal_pstore_load_property(store, device, "info.test")
>
> to read all saved attributed for a device, call:
> hal_pstore_load_device(store, device);
>
>
> I've hooked it into the current code:
> The saved properties are loaded after the device's fdi parsing.
> The property are only saved if the key starts with "save". This is
> just to be able to play around with it. We need to decide, which
> properties we want to live on disk and when the save should be triggered.
>
>
> To play around, just set a property, starting with "save*" and look at "/var/lib/hal/":
> hal-set-property --udi /org/freedesktop/Hal/devices/pci_8086_3340 --string yeah --key save.test
>
> The uuid must be saved on disk and loaded on the store's init, it's just
> a static string for now. Only the system_store is active now.
-------------- next part --------------
--- hal/hal/hald/Makefile.am 2004-06-05 02:58:50.000000000 +0200
+++ hal.kay/hal/hald/Makefile.am 2004-06-08 23:59:01.000000000 +0200
@@ -25,6 +25,7 @@
logger.h logger.c \
osspec.h \
property.h property.c \
+ pstore.h pstore.c \
hald_conf.h hald_conf.c
hald_SOURCES += \
--- hal/hal/hald/device.c 2004-04-26 22:08:58.000000000 +0200
+++ hal.kay/hal/hald/device.c 2004-06-10 11:27:44.041332744 +0200
@@ -32,6 +32,7 @@
#include <string.h>
#include "device.h"
+#include "pstore.h"
#include "hald_marshal.h"
#include "logger.h"
@@ -603,6 +604,9 @@
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
+ if (strncmp (key, "save", 4) == 0 )
+ hal_pstore_save_property (hald_get_pstore_sys (), device, prop);
+
return TRUE;
}
@@ -613,6 +617,9 @@
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
+ if (strncmp (key, "save", 4) == 0 )
+ hal_pstore_save_property (hald_get_pstore_sys (), device, prop);
+
return TRUE;
}
--- hal/hal/hald/hald.h 2004-04-03 09:46:33.000000000 +0200
+++ hal.kay/hal/hald/hald.h 2004-06-08 23:59:01.000000000 +0200
@@ -31,6 +31,7 @@
#include <dbus/dbus.h>
#include "device_store.h"
+#include "pstore.h"
/**
* @addtogroup HalDaemon
@@ -40,6 +41,7 @@
HalDeviceStore *hald_get_gdl (void);
HalDeviceStore *hald_get_tdl (void);
+HalPStore *hald_get_pstore_sys (void);
void property_atomic_update_begin ();
void property_atomic_update_end ();
--- hal/hal/hald/hald.c 2004-06-05 02:58:50.000000000 +0200
+++ hal.kay/hal/hald/hald.c 2004-06-10 10:44:10.388668344 +0200
@@ -46,6 +46,7 @@
#include "logger.h"
#include "hald.h"
#include "device_store.h"
+#include "pstore.h"
#include "device_info.h"
#include "osspec.h"
#include "hald_dbus.h"
@@ -61,6 +62,8 @@
static HalDeviceStore *temporary_device_list = NULL;
+static HalPStore *pstore_sys = NULL;
+
static void
gdl_store_changed (HalDeviceStore *store, HalDevice *device,
gboolean is_added, gpointer user_data)
@@ -131,6 +134,17 @@
return temporary_device_list;
}
+HalPStore *
+hald_get_pstore_sys (void)
+{
+ if (pstore_sys == NULL) {
+ pstore_sys = hal_pstore_open (HAL_PSTORE_SYSTEM_PATH);
+
+ }
+
+ return pstore_sys;
+}
+
/**
* @defgroup MainDaemon Basic functions
* @ingroup HalDaemon
@@ -273,6 +287,9 @@
loop = g_main_loop_new (NULL, FALSE);
+ /* initialize persitent property store, read uuid from path */
+ hal_pstore_init (HAL_PSTORE_SYSTEM_PATH);
+
/* initialize operating system specific parts */
osspec_init (dbus_connection);
/* and detect devices */
--- hal/hal/hald/linux/common.c 2004-04-26 22:42:13.000000000 +0200
+++ hal.kay/hal/hald/linux/common.c 2004-06-10 13:46:51.102386584 +0200
@@ -44,6 +44,7 @@
#include "../logger.h"
#include "../device_store.h"
+#include "../pstore.h"
#include "../device_info.h"
#include "../hald.h"
#include "common.h"
@@ -512,6 +513,8 @@
HAL_INFO (("Found a .fdi file for %s", d->udi));
}
+ /* add possible saved properties for this udi from disk*/
+ hal_pstore_load_device (hald_get_pstore_sys (), d);
}
return computed_udi;
--- /dev/null 2004-02-23 22:02:56.000000000 +0100
+++ hal.kay/hal/hald/pstore.h 2004-06-10 10:25:09.838058392 +0200
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * CVSID: $Id: $
+ *
+ * pstore.h : persistent property store on disk
+ *
+ * Copyright (C) 2004 Kay Sievers, <kay.sievers at vrfy.org>
+ *
+ * Licensed under the Academic Free License version 2.0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ **************************************************************************/
+
+#ifndef PSTORE_H
+#define PSTORE_H
+
+#define HAL_PSTORE_SYSTEM_PATH "/var/lib/hal"
+
+#include "device.h"
+#include "property.h"
+
+typedef struct _HalPStore HalPStore;
+
+void hal_pstore_init (const char *path);
+
+HalPStore *hal_pstore_open (const char *path);
+
+void hal_pstore_close (HalPStore *pstore);
+
+void hal_pstore_save_property (HalPStore *pstore,
+ HalDevice *device,
+ HalProperty *prop);
+
+void hal_pstore_load_property (HalPStore *pstore,
+ HalDevice *device,
+ const char *key);
+
+void hal_pstore_delete_property (HalPStore *pstore,
+ HalDevice *device,
+ HalProperty *prop);
+
+void hal_pstore_load_device (HalPStore *pstore,
+ HalDevice *device);
+
+
+#endif /* PSTORE_H */
--- /dev/null 2004-02-23 22:02:56.000000000 +0100
+++ hal.kay/hal/hald/pstore.c 2004-06-10 13:23:35.585537392 +0200
@@ -0,0 +1,369 @@
+/***************************************************************************
+ * CVSID: $Id: $
+ *
+ * pstore.c : persistent property store on disk
+ *
+ * Copyright (C) 2004 Kay Sievers, <kay.sievers at vrfy.org>
+ *
+ * Licensed under the Academic Free License version 2.0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <glib.h>
+
+#include "logger.h"
+#include "pstore.h"
+
+#define PSTR "String:"
+#define PINT32 "Int32:"
+#define PBOOL "Bool:"
+#define PDOUBLE "Double:"
+#define UDI_STRIP "/org/freedesktop/Hal"
+
+static char *pstore_uuid = NULL;
+
+struct _HalPStore {
+ char *path;
+ char *uuid;
+};
+
+/** Create relative or absolute path.
+ *
+ */
+static int
+create_path(const char *path)
+{
+ char *p;
+ char *pos;
+ struct stat stats;
+
+ if (stat (path, &stats) == 0)
+ return 0;
+
+ p = g_strdup (path);
+ pos = strrchr (p, '/');
+ if (pos != NULL && pos != p) {
+ pos[0] = '\0';
+ create_path (p);
+ }
+ g_free (p);
+
+ return mkdir(path, 0755);
+}
+
+/** Return absolute filename with simplified udi string.
+ *
+ */
+static char
+*build_path (HalPStore *pstore,
+ const char *udi, const char *file)
+{
+ char *path;
+ const char *udi_s;
+
+ udi_s = udi;
+ /* strip namespace part of udi string */
+ if (udi != NULL &&
+ g_ascii_strncasecmp(udi, UDI_STRIP, sizeof(UDI_STRIP)-1) == 0)
+ udi_s = &udi[sizeof(UDI_STRIP)-1];
+
+ path = g_build_filename (G_DIR_SEPARATOR_S,
+ pstore->path, pstore->uuid,
+ udi_s, file, NULL);
+
+ return path;
+}
+
+/** Return whole file content.
+ *
+ */
+static char
+*read_file (const char *file)
+{
+ GIOChannel *io;
+ GError *error = NULL;
+ char *buf;
+ int buf_len;
+
+ HAL_DEBUG (("reading %s", file));
+ io = g_io_channel_new_file (file, "r", &error);
+ if (error) {
+ HAL_INFO (("couldn't open %s", file));
+ return NULL;
+ }
+
+ g_io_channel_read_to_end (io, &buf, &buf_len, &error);
+ g_io_channel_shutdown (io, TRUE, &error);
+ if (error)
+ return NULL;
+
+ return buf;
+}
+
+/** Init pstore system by reading or generating our uuid.
+ *
+ */
+void
+hal_pstore_init (const char *path)
+{
+ char *file;
+ char *uuid;
+ char hostname[HOST_NAME_MAX];
+ char *p;
+ GIOChannel *io;
+ GError *error = NULL;
+ int written;
+
+ file = g_build_filename (G_DIR_SEPARATOR_S,
+ path, "uuid", NULL);
+ uuid = read_file(file);
+
+ if (uuid == NULL) {
+ /* create new uuid and save it to disk */
+ gethostname (hostname, HOST_NAME_MAX);
+ uuid = g_strdup_printf ("%s-%lx", hostname, time(NULL));
+
+ p = g_build_path (G_DIR_SEPARATOR_S,
+ path, NULL);
+ create_path(p);
+ g_free(p);
+
+ io = g_io_channel_new_file (file, "w", &error);
+ g_io_channel_write_chars (io, uuid, -1, &written, &error);
+ g_io_channel_shutdown (io, TRUE, &error);
+ }
+
+ HAL_DEBUG (("uuid is %s", uuid));
+ pstore_uuid = uuid;
+
+ g_free (file);
+}
+
+
+/** Open pstore on the given location.
+ *
+ */
+HalPStore
+*hal_pstore_open (const char *path)
+{
+ HalPStore *pstore;
+ char *p;
+
+ pstore = g_new0 (HalPStore, 1);
+
+ pstore->path = g_strdup (path);
+
+ pstore->uuid = pstore_uuid;
+
+ p = g_build_path (G_DIR_SEPARATOR_S,
+ pstore->path, pstore->uuid, NULL);
+ create_path(p);
+ g_free(p);
+
+ HAL_DEBUG (("opened pstore at %s/%s/", pstore->path, pstore->uuid));
+
+ return pstore;
+}
+
+/** Turn around the OPEN sign, in the store's entrance :)
+ *
+ */
+void
+hal_pstore_close (HalPStore *pstore)
+{
+ g_free (pstore->path);
+ g_free (pstore->uuid);
+ g_free (pstore);
+}
+
+/** Save a property value to the disk.
+ *
+ */
+void
+hal_pstore_save_property (HalPStore *pstore,
+ HalDevice *device, HalProperty *prop)
+{
+ char *path;
+ char *file;
+ GIOChannel *io;
+ GError *error = NULL;
+ char *str;
+ int written;
+
+ path = build_path (pstore, hal_device_get_udi (device), NULL);
+ create_path(path);
+ g_free(path);
+
+ file = build_path (pstore,
+ hal_device_get_udi (device),
+ hal_property_get_key (prop));
+
+ io = g_io_channel_new_file (file, "w", &error);
+ if (error) {
+ HAL_INFO (("couldn't open %s for writing", file));
+ g_free (file);
+ return;
+ }
+
+ HAL_INFO (("write %s to disk", hal_property_get_key (prop)));
+
+ switch (hal_property_get_type (prop)) {
+ case DBUS_TYPE_STRING:
+ g_io_channel_write_chars (io, PSTR, -1, &written, &error);
+ break;
+ case DBUS_TYPE_INT32:
+ g_io_channel_write_chars (io, PINT32, -1, &written, &error);
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ g_io_channel_write_chars (io, PBOOL, -1, &written, &error);
+ break;
+ case DBUS_TYPE_DOUBLE:
+ g_io_channel_write_chars (io, PDOUBLE, -1, &written, &error);
+ break;
+ default:
+ HAL_INFO (("unknown property type %s",
+ hal_property_get_key (prop)));
+ }
+
+ str = hal_property_to_string (prop);
+ g_io_channel_write_chars (io, str, -1, &written, &error);
+
+ g_free (file);
+ g_free (str);
+ g_io_channel_shutdown (io, TRUE, &error);
+}
+
+/** Load a stored property value from the disk.
+ *
+ */
+void
+hal_pstore_load_property (HalPStore *pstore,
+ HalDevice *device, const char *key)
+{
+ char *file;
+ char *buf;
+ char *str;
+ int i;
+ double d;
+
+ file = build_path (pstore, hal_device_get_udi (device), key);
+
+ buf = read_file (file);
+ g_free (file);
+ if (buf == NULL)
+ return;
+
+ if (g_ascii_strncasecmp (buf, PSTR, sizeof (PSTR)-1) == 0) {
+ str = &buf[sizeof (PSTR)-1];
+ hal_device_property_set_string (device, key, str);
+ HAL_INFO (("STRING %s read for %s", str, key));
+ goto exit;
+ }
+
+ if (g_ascii_strncasecmp (buf, PINT32, sizeof (PINT32)-1) == 0) {
+ str = &buf[sizeof (PINT32)-1];
+ i = strtol (str, NULL, 10);
+ hal_device_property_set_int (device, key, i);
+ goto exit;
+ }
+
+ if (g_ascii_strncasecmp (buf, PBOOL, sizeof (PBOOL)-1) == 0) {
+ str = &buf[sizeof (PBOOL)-1];
+ if (g_ascii_strcasecmp (str, "true") == 0)
+ i = TRUE;
+ else
+ i = FALSE;
+ hal_device_property_set_bool (device, key, i);
+ goto exit;
+ }
+
+ if (g_ascii_strncasecmp (buf, PDOUBLE, sizeof (PDOUBLE)-1) == 0) {
+ str = &buf[sizeof (PDOUBLE)-1];
+ d = atof (str);
+ hal_device_property_set_double (device, key, d);
+ goto exit;
+ }
+
+ HAL_INFO (("error reading pstore property %s", key));
+
+exit:
+ g_free (buf);
+}
+
+/** Delete a stored property from the disk.
+ *
+ */
+void
+hal_pstore_delete_property (HalPStore *pstore,
+ HalDevice *device, HalProperty *prop)
+{
+ char *file;
+
+ file = build_path (pstore,
+ hal_device_get_udi (device),
+ hal_property_get_key (prop));
+
+ HAL_DEBUG (("unlinking %s", file));
+
+ unlink(file);
+ g_free(file);
+}
+
+/** Load all stored properties of a device from the disk.
+ *
+ */
+void
+hal_pstore_load_device (HalPStore *pstore,
+ HalDevice *device)
+{
+ GDir *dir;
+ GError *error = NULL;
+ const char *dirname;
+ char *path;
+
+ path = build_path (pstore,
+ hal_device_get_udi (device),
+ NULL);
+
+ HAL_DEBUG (("reading directory %s", path));
+
+ dir = g_dir_open (path, 0, &error);
+ if (error)
+ goto exit;
+
+ while (1) {
+ dirname = g_dir_read_name (dir);
+ if (dirname == NULL)
+ break;
+
+ hal_pstore_load_property (pstore, device, dirname);
+ }
+
+ g_dir_close (dir);
+
+exit:
+ g_free (path);
+}
-------------- next part --------------
_______________________________________________
hal mailing list
hal at freedesktop.org
http://freedesktop.org/mailman/listinfo/hal
More information about the Hal
mailing list