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