[glib/gsettings] GSettingsSchema: support for uncached schemas
- From: Ryan Lortie <ryanl src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [glib/gsettings] GSettingsSchema: support for uncached schemas
- Date: Fri, 2 Oct 2009 20:45:18 +0000 (UTC)
commit c08f3a5bcdfb41db831ca23892007b8ef1941a43
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Oct 2 16:44:02 2009 -0400
GSettingsSchema: support for uncached schemas
gio/gsettingsschema.c | 161 +++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 143 insertions(+), 18 deletions(-)
---
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 02c1c04..5131fdd 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -10,6 +10,7 @@
#include "gsettingsschema.h"
+#include <sys/stat.h>
#include <string.h>
#include "gioalias.h"
@@ -25,38 +26,152 @@ struct _GSettingsSchemaPrivate
GVariant *children;
};
+gint g_settings_schema_n_dirs;
+GVariant **g_settings_schema_caches;
+gchar **g_settings_schema_dirs;
+
static void
-g_settings_schema_init (GSettingsSchema *schema)
+g_settings_schema_initialise_directories (void)
{
- schema->priv = G_TYPE_INSTANCE_GET_PRIVATE (schema,
- G_TYPE_SETTINGS_SCHEMA,
- GSettingsSchemaPrivate);
+ const GVariantType *cache_type;
+ const char * const *data_dirs;
+ GVariant **caches;
+ gchar **dirs;
+ gint i, n;
+
+ /* we want to do the following:
+ *
+ * - set g_settings_schema_n_dirs to the number of valid schema dirs
+ *
+ * - set g_settings_schema_caches to an array with 'n_dirs'
+ * elements. if a given element is non-NULL then it points to the
+ * GVariant for that schema directory's cache. if NULL, the cache
+ * is invalid.
+ *
+ * - set g_settings_schema_dirs to an array of size n where n is one
+ * more than the largest index in g_settings_schema_caches that
+ * contains NULL. for every NULL in g_setings_schema_caches, the
+ * entry of the same index in this array will contain the
+ * path of a schema directory to check for uncached schemas.
+ */
+
+ cache_type = G_VARIANT_TYPE ("a{s(asmsa{s(sv)}a{ss})}");
+ data_dirs = g_get_system_data_dirs ();
+
+ caches = NULL;
+ dirs = NULL;
+
+ for (n = i = 0; data_dirs[i]; i++)
+ {
+ struct stat dirbuf, cachebuf;
+ gchar *path, *cachepath;
+
+ path = g_strdup_printf ("%s/%s", data_dirs[i], "gsettings/schemas");
+ if (stat (path, &dirbuf) || !S_ISDIR (dirbuf.st_mode) < 0)
+ {
+ g_free (path);
+ continue;
+ }
+
+ cachepath = g_strdup_printf ("%s/schemas-cache", path);
+ if (stat (cachepath, &cachebuf) < 0)
+ {
+ g_free (cachepath);
+ cachepath = NULL;
+ }
+ else
+ {
+ if (cachebuf.st_mtime < dirbuf.st_mtime)
+ {
+ g_free (cachepath);
+ cachepath = NULL;
+ }
+ }
+
+ caches = g_renew (GVariant *, caches, n + 1);
+ caches[n] = cachepath ?
+ g_variant_from_file (cache_type, cachepath, 0, NULL) :
+ NULL;
+ g_free (cachepath);
+
+ if (caches[n] == NULL)
+ {
+ dirs = g_renew (gchar *, dirs, i + 1);
+ dirs[n] = path;
+ }
+ else
+ g_free (path);
+
+ n++;
+ }
+ g_settings_schema_n_dirs = n;
+ g_settings_schema_caches = caches;
+ g_settings_schema_dirs = dirs;
}
-GSettingsSchema *
-g_settings_schema_new (const gchar *schema_name)
+static GVariant *
+g_settings_schema_compile (const gchar *filename)
{
- static GVariant *schemas;
- GSettingsSchema *schema;
+ g_print ("compiling %s\n", filename);
+ return NULL;
+}
+
+static GVariant *
+g_settings_schema_scan_dir (const gchar *directory,
+ const gchar *schema_name)
+{
+ gint directory_length;
+ gint name_length;
GVariant *value;
+ gchar *path;
+ gint end;
+
+ directory_length = strlen (directory);
+ name_length = strlen (schema_name);
- if G_UNLIKELY (g_once_init_enter ((gsize *) &schemas))
+ path = g_malloc (directory_length + 1 + name_length + 1 + 7 + 1);
+ /* directory / schema_name . schemas \0 */
+ memcpy (path, directory, directory_length);
+ path[directory_length] = '/';
+ memcpy (path + directory_length + 1, schema_name, name_length);
+ end = directory_length + 1 + name_length;
+
+ while (value == NULL)
{
- GError *error = NULL;
- GVariant *tmp;
+ strcpy (path + end, ".schemas");
- tmp = g_variant_from_file (G_VARIANT_TYPE ("a{s(asmsa{s(sv)}a{ss})}"),
- GSETTINGS_SCHEMAS_DIR "/schemas-cache", 0,
- &error);
+ while (path[--end] != '.' && end > directory_length + 1);
- if G_UNLIKELY (tmp == NULL)
- g_error ("open schema file: %s\n", error->message);
+ /* don't allow looking for TLD-named files (like 'org.schemas') */
+ if (path[end] != '.')
+ break;
- g_once_init_leave ((gsize *) &schemas, (gsize) tmp);
+ value = g_settings_schema_compile (path);
}
+ g_free (path);
+
+ return value;
+}
+
+GSettingsSchema *
+g_settings_schema_new (const gchar *schema_name)
+{
+ GSettingsSchema *schema;
+ GVariant *value = NULL;
+ gint i;
+
schema = g_object_new (G_TYPE_SETTINGS_SCHEMA, NULL);
- value = g_variant_lookup_value (schemas, schema_name);
+
+ for (i = 0; value == NULL && i < g_settings_schema_n_dirs; i++)
+ {
+ if (g_settings_schema_caches[i] != NULL)
+ value = g_variant_lookup_value (g_settings_schema_caches[i],
+ schema_name);
+ else
+ value = g_settings_schema_scan_dir (g_settings_schema_dirs[i],
+ schema_name);
+ }
if (value == NULL)
g_error ("Invalid schema name '%s'", schema_name);
@@ -79,12 +194,22 @@ g_settings_schema_finalize (GObject *object)
}
static void
+g_settings_schema_init (GSettingsSchema *schema)
+{
+ schema->priv = G_TYPE_INSTANCE_GET_PRIVATE (schema,
+ G_TYPE_SETTINGS_SCHEMA,
+ GSettingsSchemaPrivate);
+}
+
+static void
g_settings_schema_class_init (GSettingsSchemaClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
g_type_class_add_private (class, sizeof (GSettingsSchemaPrivate));
+ g_settings_schema_initialise_directories ();
+
object_class->finalize = g_settings_schema_finalize;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]