persistent property store - first try

Kay Sievers kay.sievers at vrfy.org
Thu Jun 10 17:21:22 PDT 2004


On Thu, Jun 10, 2004 at 06:29:55PM -0400, Joe Shaw wrote:
> On Fri, 2004-06-11 at 00:06 +0200, Kay Sievers wrote:

> > +hal_pstore_close (HalPStore *pstore)
> > +{
> > +	g_free (pstore->path);
> > +	g_free (pstore->uuid);
> > +	g_free (pstore);
> > +}
> 
> Are you sure you want to free pstore->uuid here?  If you do, pstore_uuid
> will be garbage if you try to call hal_pstore_open() without first
> calling hal_pstore_init().  You probably want to either g_strdup() it in
> hal_store_open() or not free it at all (and declare it const in the
> struct definition).

Excellent eyes! :) Yeah, it was a leftover from the first version
without the global uuid.

> On a related note, you might want to check in hal_pstore_open() that
> hal_pstore_init() is called first.  Or just make hal_pstore_init()
> static and have hal_pstore_open() lazily call it.

Hmm, with the explicit init we can read the stored uuid from any location,
but I don't know if we ever need this?


thanks,
Kay
-------------- next part --------------
--- hal/hal/hald/Makefile.am	2004-06-05 02:58:50.000000000 +0200
+++ hal.kay/hal/hald/Makefile.am	2004-06-10 14:23:39.087721792 +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/hald.h	2004-04-03 09:46:33.000000000 +0200
+++ hal.kay/hal/hald/hald.h	2004-06-10 14:23:39.089721488 +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-11 01:51:51.894261024 +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,15 @@
 	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 +285,9 @@
 
 	loop = g_main_loop_new (NULL, FALSE);
 
+	/* initialize persitent property store, read uuid from path */
+	hal_pstore_init (HAL_PSTORE_SYSTEM_PATH "/uuid");
+
 	/* initialize operating system specific parts */
 	osspec_init (dbus_connection);
 	/* and detect devices */
--- hal/hal/hald/device.h	2004-04-26 22:08:58.000000000 +0200
+++ hal.kay/hal/hald/device.h	2004-06-10 20:57:47.734581008 +0200
@@ -150,4 +150,8 @@
 
 void          hal_device_callouts_finished    (HalDevice    *device);
 
+gboolean      hal_device_property_set_persistence (HalDevice *device,
+						   const char *key,
+						   gboolean persistence);
+
 #endif /* DEVICE_H */
--- hal/hal/hald/device.c	2004-04-26 22:08:58.000000000 +0200
+++ hal.kay/hal/hald/device.c	2004-06-10 22:38:15.740184864 +0200
@@ -31,7 +31,9 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "hald.h"
 #include "device.h"
+#include "pstore.h"
 #include "hald_marshal.h"
 #include "logger.h"
 
@@ -603,6 +605,9 @@
 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 			       key, FALSE, FALSE);
 
+		if (hal_property_get_persistence (prop))
+			hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 		return TRUE;
 	}
 
@@ -613,6 +618,9 @@
 	g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 		       key, FALSE, TRUE);
 
+	if (hal_property_get_persistence (prop))
+		hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 	return TRUE;
 }
 
@@ -638,6 +646,9 @@
 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 			       key, FALSE, FALSE);
 
+		if (hal_property_get_persistence (prop))
+			hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 		return TRUE;
 	}
 
@@ -648,6 +659,9 @@
 	g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 		       key, FALSE, TRUE);
 
+	if (hal_property_get_persistence (prop))
+		hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 	return TRUE;
 }
 
@@ -673,6 +687,9 @@
 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 			       key, FALSE, FALSE);
 
+		if (hal_property_get_persistence (prop))
+			hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 		return TRUE;
 	}
 
@@ -683,6 +700,9 @@
 	g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 		       key, FALSE, TRUE);
 
+	if (hal_property_get_persistence (prop))
+		hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 	return TRUE;
 }
 
@@ -708,6 +728,9 @@
 		g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 			       key, FALSE, FALSE);
 
+		if (hal_property_get_persistence (prop))
+			hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 		return TRUE;
 	}
 
@@ -718,6 +741,9 @@
 	g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
 		       key, FALSE, TRUE);
 
+	if (hal_property_get_persistence (prop))
+		hal_pstore_save_property (hald_get_pstore_sys (), device, prop); 
+
 	return TRUE;
 }
 
@@ -731,6 +757,9 @@
 	if (prop == NULL)
 		return FALSE;
 
+	if (hal_property_get_persistence (prop))
+		hal_pstore_delete_property (hald_get_pstore_sys (), device, prop); 
+
 	device->properties = g_slist_remove (device->properties, prop);
 
 	hal_property_free (prop);
@@ -741,6 +770,29 @@
 	return TRUE;
 }
 
+gboolean
+hal_device_property_set_persistence (HalDevice *device,
+				     const char *key,
+				     gboolean persistence)
+{
+	HalProperty *prop;
+
+	prop = hal_device_property_find (device, key);
+
+	if (prop == NULL)
+		return FALSE;
+
+	hal_property_set_persistence (prop, persistence);
+
+	/* Write it to disk, or delete it */
+	if (hal_property_get_persistence (prop) == TRUE)
+		hal_pstore_save_property (hald_get_pstore_sys (), device, prop);
+	else
+		hal_pstore_delete_property (hald_get_pstore_sys (), device, prop);
+
+	return TRUE;
+}
+
 void
 hal_device_print (HalDevice *device)
 {
--- hal/hal/hald/property.h	2004-04-20 22:54:15.000000000 +0200
+++ hal.kay/hal/hald/property.h	2004-06-10 20:51:24.043910856 +0200
@@ -59,5 +59,8 @@
 					  dbus_bool_t   value);
 void          hal_property_set_double    (HalProperty  *prop,
 					  double        value);
+void          hal_property_set_persistence (HalProperty *prop,
+					    gboolean persistence);
+gboolean      hal_property_get_persistence (HalProperty *prop);
 
 #endif /* PROPERTY_H */
--- hal/hal/hald/property.c	2004-04-20 22:54:15.000000000 +0200
+++ hal.kay/hal/hald/property.c	2004-06-10 22:28:08.578487472 +0200
@@ -42,13 +42,14 @@
 		dbus_bool_t bool_value;
 		double double_value;
 	};
+	gboolean persistence;
 };
 
 void
 hal_property_free (HalProperty *prop)
 {
 	g_free (prop->key);
-	
+
 	if (prop->type == DBUS_TYPE_STRING)
 		g_free (prop->str_value);
 
@@ -226,3 +227,20 @@
 	prop->type = DBUS_TYPE_DOUBLE;
 	prop->double_value = value;
 }
+
+void
+hal_property_set_persistence (HalProperty *prop, gboolean persistence)
+{
+	g_return_if_fail (prop != NULL);
+
+	prop->persistence = persistence;
+}
+
+gboolean
+hal_property_get_persistence (HalProperty *prop)
+{
+	g_return_val_if_fail (prop != NULL, -1);
+
+	return prop->persistence;
+}
+
--- hal/hal/hald/hald_dbus.c	2004-05-04 18:05:35.000000000 +0200
+++ hal.kay/hal/hald/hald_dbus.c	2004-06-10 22:55:36.500965176 +0200
@@ -872,6 +872,7 @@
 
 	type = dbus_message_iter_get_arg_type (&iter);
 	rc = FALSE;
+
 	switch (type) {
 	case DBUS_TYPE_STRING:
 		rc = hal_device_property_set_string (device, key,
@@ -899,6 +900,10 @@
 		break;
 	}
 
+	/* FIXME: temporary hack to test pstore; makes all D-BUS properties persistent */
+	hal_device_property_set_persistence (device, key, TRUE);
+	HAL_WARNING (("FIXME: persistence set for all D-BUS props; udi=%s, key=%s", udi, key));
+
 	if (!rc) {
 		raise_property_type_error (connection, message, udi, key);
 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
--- hal/hal/hald/linux/common.c	2004-04-26 22:42:13.000000000 +0200
+++ hal.kay/hal/hald/linux/common.c	2004-06-10 14:23:39.091721184 +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 14:23:39.091721184 +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-11 01:59:58.257322600 +0200
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * 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;
+	const 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;
+}
+
+/** Init pstore system by reading or generating our uuid.
+ *
+ */
+void
+hal_pstore_init (const char *uuid_file)
+{
+	char *uuid;
+	char hostname[HOST_NAME_MAX];
+	char *p;
+	GIOChannel *io;
+	GError *error = NULL;
+	int written;
+
+	g_file_get_contents (uuid_file, &uuid, NULL, NULL);
+
+	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_path_get_dirname (uuid_file);
+		create_path(p);
+		g_free(p);
+
+		io = g_io_channel_new_file (uuid_file, "w", &error);
+		if (error != NULL) {
+			HAL_WARNING (("error creating file %s", error->message));
+			g_error_free (error);
+			return;
+		}
+		g_io_channel_write_chars (io, uuid, -1, &written, &error);
+		g_io_channel_shutdown (io, TRUE, NULL);
+		if (error != NULL) {
+			HAL_WARNING (("error writing to file %s", error->message));
+			g_error_free (error);
+			return;
+		}
+	}
+
+	HAL_DEBUG (("uuid is %s", uuid));
+	pstore_uuid = uuid;
+}
+
+
+/** Open pstore on the given location.
+ *
+ */
+HalPStore
+*hal_pstore_open (const char *path)
+{
+	HalPStore *pstore;
+	char *p;
+
+	if (pstore_uuid == NULL)
+	    return NULL;
+
+	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);
+}
+
+/** 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 *id;
+	char *value;
+	char *buf;
+	int written;
+
+	switch (hal_property_get_type (prop)) {
+	case DBUS_TYPE_STRING:
+		id = PSTR;
+		break;
+	case DBUS_TYPE_INT32:
+		id = PINT32;
+		break;
+	case DBUS_TYPE_BOOLEAN:
+		id = PBOOL;
+		break;
+	case DBUS_TYPE_DOUBLE:
+		id = PDOUBLE;
+		break;
+	default:
+		HAL_WARNING (("unknown property type %s",
+			   hal_property_get_key (prop)));
+		return;
+	}
+
+	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 != NULL) {
+		HAL_WARNING (("error creating file %s (%s)", file, error->message));
+		g_error_free (error);
+		g_free (file);
+		return;
+	}
+
+	value = hal_property_to_string (prop);
+
+	buf = g_strconcat (id, value, NULL);
+	g_free (value);
+
+	HAL_DEBUG (("write %s to disk", hal_property_get_key (prop)));
+
+	g_io_channel_write_chars (io, buf, -1, &written, &error);
+	if (error != NULL) {
+		HAL_WARNING (("error writing to file %s (%s)", file, error->message));
+		g_error_free (error);
+	}
+
+	g_io_channel_shutdown (io, TRUE, NULL);
+	g_free (buf);
+	g_free (file);
+}
+
+/** 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);
+
+	g_file_get_contents (file, &buf, NULL, NULL);
+	g_free (file);
+	if (buf == NULL) {
+		HAL_DEBUG (("error reading file %s", file));
+		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_WARNING (("error determining pstore property type %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