persistent property store - first try

Kay Sievers kay.sievers at vrfy.org
Tue Jun 8 18:57:58 PDT 2004


Hi,
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.

Please share your thoughts.

thanks,
Kay
-------------- next part --------------
Index: hald/Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/Makefile.am,v
retrieving revision 1.26
diff -u -r1.26 Makefile.am
--- a/hald/Makefile.am	1 Jun 2004 21:10:02 -0000	1.26
+++ b/hald/Makefile.am	9 Jun 2004 01:11:26 -0000
@@ -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 +=	\
Index: hald/device.c
===================================================================
RCS file: /cvs/hal/hal/hald/device.c,v
retrieving revision 1.6
diff -u -r1.6 device.c
--- a/hald/device.c	26 Apr 2004 20:08:58 -0000	1.6
+++ b/hald/device.c	9 Jun 2004 01:11:26 -0000
@@ -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;
 }
 
Index: hald/hald.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald.c,v
retrieving revision 1.8
diff -u -r1.8 hald.c
--- a/hald/hald.c	1 Jun 2004 21:10:02 -0000	1.8
+++ b/hald/hald.c	9 Jun 2004 01:11:26 -0000
@@ -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
Index: hald/hald.h
===================================================================
RCS file: /cvs/hal/hal/hald/hald.h,v
retrieving revision 1.4
diff -u -r1.4 hald.h
--- a/hald/hald.h	3 Apr 2004 07:46:33 -0000	1.4
+++ b/hald/hald.h	9 Jun 2004 01:11:26 -0000
@@ -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 ();
Index: hald/linux/common.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/common.c,v
retrieving revision 1.7
diff -u -r1.7 common.c
--- a/hald/linux/common.c	26 Apr 2004 20:42:13 -0000	1.7
+++ b/hald/linux/common.c	9 Jun 2004 01:11:27 -0000
@@ -44,6 +44,7 @@
 
 #include "../logger.h"
 #include "../device_store.h"
+#include "../pstore.h"
 #include "../device_info.h"
 #include "../hald.h"
 #include "common.h"
@@ -511,7 +512,9 @@
 		if (di_search_and_merge (d)) {
 			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
+++ b/hald/pstore.c	2004-06-09 03:01:12.991488760 +0200
@@ -0,0 +1,305 @@
+/***************************************************************************
+ * 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 <sys/stat.h>
+#include <glib.h>
+
+#include "logger.h"
+#include "pstore.h"
+
+#define PSTR		"String:"
+#define PINT32		"Int32:"
+#define PBOOL		"Bool:"
+#define PDOUBLE		"Double:"
+
+struct _HalPStore {
+	char *path;
+	char *uuid;
+};
+
+static int create_abs_path(const char *path)
+{
+	char *p;
+	char *pos;
+	struct stat stats;
+	
+	p = g_strconcat (path, "/", NULL);
+	pos = p;
+	while (1) {
+		pos = strchr(&pos[1], '/');
+		if (pos == NULL)
+			break;
+
+		pos[0] = '\0';
+
+		if (stat (p, &stats) != 0) {
+			if (mkdir(p, 0755) != 0) {
+				HAL_DEBUG (("mkdir failed for %s", p));
+				return -1;
+			}
+		}
+		pos[0] = '/';
+	}
+	return 0;
+}
+
+/** Initializes the persistent store by reading/generating
+ *  our uuid to store properties in a directoy named after it.
+ *
+ */
+HalPStore
+*hal_pstore_open (const char *path)
+{
+	HalPStore *pstore;
+	char hostname[HOST_NAME_MAX];
+	char *p;
+
+	pstore = g_new0 (HalPStore, 1);
+
+	pstore->path = g_strdup (path);
+
+	/* FIXME: read already computed uuid from store, or
+	 *        if it's the first open, compute one and save it
+	 */
+
+	gethostname (hostname, HOST_NAME_MAX);
+	pstore->uuid = g_strjoin ("-", hostname, "95a478b32fa0", NULL);
+	HAL_DEBUG (("uuid is %s", pstore->uuid));
+
+	p = g_build_path (G_DIR_SEPARATOR_S,
+			  path, pstore->uuid, NULL);
+	create_abs_path(p);
+	HAL_DEBUG (("opened pstore at %s", p));
+	g_free(p);
+
+	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 = g_build_path (G_DIR_SEPARATOR_S,
+			     pstore->path, pstore->uuid,
+			     hal_device_get_udi (device), NULL);
+	create_abs_path(path);
+	g_free(path);
+
+	file = g_build_filename (G_DIR_SEPARATOR_S,
+				 pstore->path, pstore->uuid,
+				 hal_device_get_udi (device),
+				 hal_property_get_key (prop), NULL);
+
+	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;
+	GIOChannel *io;
+	GError *error = NULL;
+	char *buf;
+	int buf_len;
+	char *str;
+	int i;
+	double d;
+
+	file = g_build_filename (G_DIR_SEPARATOR_S,
+				 pstore->path, pstore->uuid,
+				 hal_device_get_udi (device),
+				 key, NULL);
+
+	HAL_DEBUG (("reading %s", file));
+	io = g_io_channel_new_file (file, "r", &error);
+	g_free (file);
+	if (error) {
+		HAL_INFO (("Couldn't open %s", file));
+		return;
+	}
+
+	g_io_channel_read_to_end (io, &buf, &buf_len, &error);
+	g_io_channel_shutdown (io, TRUE, &error);
+	if (error)
+		goto exit;
+
+	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 = 1;
+		else
+		    i = 0;
+		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 = g_build_filename (G_DIR_SEPARATOR_S,
+				 pstore->path, pstore->uuid,
+				 hal_device_get_udi (device),
+				 hal_property_get_key (prop),
+				 NULL);
+
+	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 = g_build_path (G_DIR_SEPARATOR_S,
+			     pstore->path, pstore->uuid,
+			     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);
+}
--- /dev/null	2004-02-23 22:02:56.000000000 +0100
+++ b/hald/pstore.h	2004-06-08 23:58:35.826231072 +0200
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * 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;
+
+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 */
-------------- next part --------------
_______________________________________________
hal mailing list
hal at freedesktop.org
http://freedesktop.org/mailman/listinfo/hal


More information about the Hal mailing list