diff options
author | Havoc Pennington <hp@src.gnome.org> | 1999-12-23 22:06:30 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 1999-12-23 22:06:30 +0000 |
commit | 38eb7950e7653b4704d465bf56fbd76cd00ac23b (patch) | |
tree | 949dc6d2cd365aa613c897c39bbc38377d2b30f4 /backends | |
parent | 811b3f1a8aba1902d3c0ca0ed041e4033c9a91e6 (diff) | |
download | gconf-38eb7950e7653b4704d465bf56fbd76cd00ac23b.tar.gz |
work on the XML backend cleanup
Diffstat (limited to 'backends')
-rw-r--r-- | backends/Makefile.am | 6 | ||||
-rw-r--r-- | backends/xml-cache.c | 488 | ||||
-rw-r--r-- | backends/xml-cache.h | 43 | ||||
-rw-r--r-- | backends/xml-dir.c | 219 | ||||
-rw-r--r-- | backends/xml-dir.h | 87 | ||||
-rw-r--r-- | backends/xml-entry.c | 64 |
6 files changed, 821 insertions, 86 deletions
diff --git a/backends/Makefile.am b/backends/Makefile.am index dd604582..f2d06618 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -5,6 +5,12 @@ backenddir = $(libdir)/gconf backend_LTLIBRARIES = libgconfbackend-xml.la libgconfbackend_xml_la_SOURCES = \ + xml-cache.h \ + xml-cache.c \ + xml-dir.h \ + xml-dir.c \ + xml-entry.h \ + xml-entry.c \ xml-backend.c libgconfbackend_xml_la_LDFLAGS = -avoid-version -module diff --git a/backends/xml-cache.c b/backends/xml-cache.c new file mode 100644 index 00000000..6ddfabe8 --- /dev/null +++ b/backends/xml-cache.c @@ -0,0 +1,488 @@ +/* GConf + * Copyright (C) 1999 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "xml-cache.h" +#include <gconf/gconf-internals.h> + +#include <time.h> + +/* Quick hack so I can mark strings */ + +#ifdef _ +#warning "_ already defined" +#else +#define _(x) x +#endif + +#ifdef N_ +#warning "N_ already defined" +#else +#define N_(x) x +#endif + + +/* This makes hash table safer when debugging */ +#ifndef GCONF_ENABLE_DEBUG +#define safe_g_hash_table_insert g_hash_table_insert +#else +static void +safe_g_hash_table_insert(GHashTable* ht, gpointer key, gpointer value) +{ + gpointer oldkey = NULL, oldval = NULL; + + if (g_hash_table_lookup_extended(ht, key, &oldkey, &oldval)) + { + gconf_log(GCL_WARNING, "Hash key `%s' is already in the table!", + (gchar*)key); + return; + } + else + { + g_hash_table_insert(ht, key, value); + } +} +#endif + +static gboolean +cache_is_nonexistent(Cache* cache, + const gchar* key); + +static void +cache_set_nonexistent (Cache* cache, + const gchar* key, + gboolean setting); + +static void +cache_insert (Cache* cache, + Dir* d); + +struct _Cache { + gchar* root_dir; + GHashTable* cache; + GHashTable* nonexistent_cache; + GSList* deleted; + /* + List of lists of dirs marked deleted, in the + proper order; should be synced by deleting each + list from front to end, starting with the first + list. + */ + +}; + +Cache* +cache_new (const gchar *root_dir) +{ + Cache* cache; + + cache = g_new(Cache, 1); + + cache->root_dir = g_strdup(root_dir); + + cache->cache = g_hash_table_new(g_str_hash, g_str_equal); + cache->nonexistent_cache = g_hash_table_new(g_str_hash, g_str_equal); + + cache->deleted = NULL; + + return cache; +} + +static void cache_destroy_foreach(const gchar* key, + Dir* dir, gpointer data); + +static void cache_destroy_nonexistent_foreach(gchar* key, + gpointer val, + gpointer data); + +void +cache_destroy (Cache *cache) +{ + GSList *iter; + + g_free(cache->root_dir); + g_hash_table_foreach(cache->cache, (GHFunc)cache_destroy_foreach, + NULL); + g_hash_table_foreach(cache->nonexistent_cache, + (GHFunc)cache_destroy_nonexistent_foreach, + NULL); + g_hash_table_destroy(cache->cache); + g_hash_table_destroy(cache->nonexistent_cache); + + if (cache->deleted != NULL) + gconf_log(GCL_WARNING, _("Unsynced directory deletions when shutting down XML backend")); + + iter = cache->deleted; + + while (iter != NULL) + { + g_slist_free(iter->data); + + iter = g_slist_next(iter); + } + g_slist_free(cache->deleted); + + g_free(cache); +} + + +typedef struct _SyncData SyncData; +struct _SyncData { + gboolean failed; + Cache* dc; +}; + +static void +cache_sync_foreach(const gchar* key, + Dir* dir, + SyncData* sd) +{ + GConfError* error = NULL; + + /* log errors but don't report the specific ones */ + if (!dir_sync(dir, &error)) + { + sd->failed = TRUE; + g_return_if_fail(error != NULL); + gconf_log(GCL_ERR, error->str); + gconf_error_destroy(error); + } + else + { + g_return_if_fail(error == NULL); + } +} + +gboolean +cache_sync (Cache *cache, + GConfError **err) +{ + SyncData sd = { FALSE, cache }; + GSList* delete_list; + + /* First delete pending directories */ + delete_list = cache->deleted; + + while (delete_list != NULL) + { + GSList* tmp; + + tmp = delete_list->data; + + while (tmp != NULL) + { + Dir* d = tmp->data; + + if (!dir_sync(d, NULL)) /* don't get errors, they'd pile up */ + sd.failed = TRUE; + + tmp = g_slist_next(tmp); + } + + g_slist_free(delete_list->data); + + delete_list = g_slist_next(delete_list); + } + + g_slist_free(cache->deleted); + cache->deleted = NULL; + + g_hash_table_foreach(cache->cache, (GHFunc)cache_sync_foreach, + &sd); + + return !sd.failed; +} + +typedef struct _CleanData CleanData; +struct _CleanData { + GTime now; + Cache* cache; + GTime length; +}; + +static gboolean +cache_clean_foreach(const gchar* key, + Dir* dir, CleanData* cd) +{ + GTime last_access = dir_get_last_access(dir); + + if ((cd->now - last_access) > cd->length) + { + dir_destroy(dir); + return TRUE; + } + else + return FALSE; +} + +void +cache_clean (Cache *cache, + GTime older_than) +{ + CleanData cd = { 0, cache, older_than }; + + cd.now = time(NULL); /* ha ha, it's an online store! */ + + g_hash_table_foreach_remove(cache->cache, (GHRFunc)cache_clean_foreach, + &cd); +} + +static void +cache_delete_dir_by_pointer(Cache* cache, + Dir * d, + GConfError** err); + +static void +cache_delete_recursive(Cache* cache, Dir* d, GSList** hit_list, GConfError** err) +{ + GSList* subdirs; + GSList* tmp; + gboolean failure = FALSE; + + subdirs = dir_all_subdirs(d, err); + + if (subdirs == NULL && err && *err != NULL) + failure = TRUE; + + tmp = subdirs; + while (tmp != NULL && !failure) + { + Dir* subd; + gchar* fullkey; + + fullkey = gconf_concat_key_and_dir(dir_get_name(d), (gchar*)tmp->data); + + subd = cache_lookup(cache, fullkey, FALSE, err); + + g_free(tmp->data); + g_free(fullkey); + + if (subd == NULL && err && *err) + failure = TRUE; + else if (subd != NULL && + !dir_is_deleted(subd)) + { + /* recurse, whee! (unless the subdir is already deleted) */ + cache_delete_dir_by_pointer(cache, subd, err); + + if (err && *err) + failure = TRUE; + } + + tmp = g_slist_next(tmp); + } + + g_slist_free(subdirs); + + /* The first directories to be deleted (fringes) go on the front + of the list. */ + *hit_list = g_slist_prepend(*hit_list, d); + + /* We go ahead and mark the dir deleted */ + dir_mark_deleted(d); + + /* be sure we set error if failure occurred */ + g_return_if_fail( (!failure) || (err == NULL) || (*err != NULL)); +} + + +static void +cache_delete_dir_by_pointer(Cache* cache, + Dir * d, + GConfError** err) +{ + GSList* hit_list = NULL; + + cache_delete_recursive(cache, d, &hit_list, err); + + /* If you first dir_cache_delete() a subdir, then dir_cache_delete() + its parent, without syncing, first the list generated by + the subdir delete then the list from the parent delete should + be nuked. If you first delete a parent, then its subdir, + really only the parent list should be nuked, but + in effect it's OK to nuke the parent first then + fail to nuke the subdir. So, if we prepend here, + then nuke the list in order, it will work fine. + */ + + cache->deleted = g_slist_prepend(cache->deleted, hit_list); +} + +void +cache_delete_dir (Cache *cache, + const gchar *key, + GConfError **err) +{ + Dir* d; + + d = cache_lookup(cache, key, FALSE, err); + + if (d != NULL) + { + g_assert(err == NULL || *err == NULL); + cache_delete_dir_by_pointer(cache, d, err); + } +} + +Dir* +cache_lookup (Cache *cache, + const gchar *key, + gboolean create_if_missing, + GConfError **err) +{ + Dir* dir; + + g_assert(key != NULL); + + /* Check cache */ + dir = g_hash_table_lookup(cache->cache, key); + + if (dir != NULL) + { + return dir; + } + else + { + /* Not in cache, check whether we already failed + to load it */ + if (cache_is_nonexistent(cache, key)) + { + if (!create_if_missing) + return NULL; + } + else + { + /* Didn't already fail to load, try to load */ + dir = dir_load(key, cache->root_dir, err); + + if (dir != NULL) + { + g_assert(err == NULL || *err == NULL); + + /* Cache it */ + cache_insert(cache, dir); + + return dir; + } + else + { + /* Remember that we failed to load it */ + if (!create_if_missing) + { + cache_set_nonexistent(cache, key, TRUE); + + return NULL; + } + else + { + if (err && *err) + { + gconf_error_destroy(*err); + *err = NULL; + } + } + } + } + } + + g_assert(dir == NULL); + g_assert(create_if_missing); + g_assert(err == NULL || *err == NULL); + + if (dir == NULL) + { + dir = dir_new(key, cache->root_dir); + + if (!dir_ensure_exists(dir, err)) + { + dir_destroy(dir); + + g_return_val_if_fail((err == NULL) || + (*err != NULL) , + NULL); + return NULL; + } + else + cache_insert(cache, dir); + } + + return dir; +} + +static gboolean +cache_is_nonexistent(Cache* cache, + const gchar* key) +{ + return GPOINTER_TO_INT(g_hash_table_lookup(cache->nonexistent_cache, + key)); +} + +static void +cache_set_nonexistent (Cache* cache, + const gchar* key, + gboolean setting) +{ + if (setting) + { + /* don't use safe_ here, doesn't matter */ + g_hash_table_insert(cache->nonexistent_cache, + g_strdup(key), + GINT_TO_POINTER(TRUE)); + } + else + { + gpointer origkey; + gpointer origval; + + if (g_hash_table_lookup_extended(cache->nonexistent_cache, + key, + &origkey, &origval)) + { + g_free(origkey); + g_hash_table_remove(cache->nonexistent_cache, + key); + } + } +} + +static void +cache_insert (Cache* cache, + Dir* d) +{ + g_return_if_fail(d != NULL); + safe_g_hash_table_insert(cache->cache, (gchar*)dir_get_name(d), d); +} + +static void +cache_destroy_foreach(const gchar* key, + Dir* dir, gpointer data) +{ + dir_destroy(dir); +} + +static void +cache_destroy_nonexistent_foreach(gchar* key, + gpointer val, + gpointer data) +{ + g_free(key); +} + + + + diff --git a/backends/xml-cache.h b/backends/xml-cache.h new file mode 100644 index 00000000..2191707e --- /dev/null +++ b/backends/xml-cache.h @@ -0,0 +1,43 @@ +/* GConf + * Copyright (C) 1999 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GCONF_XML_CACHE_H +#define GCONF_XML_CACHE_H + +#include <gconf/gconf.h> +#include <gnome-xml/tree.h> +#include "xml-dir.h" + +typedef struct _Cache Cache; + +Cache* cache_new (const gchar *root_dir); +void cache_destroy (Cache *cache); +gboolean cache_sync (Cache *cache, + GConfError **err); +void cache_clean (Cache *cache, + GTime older_than); +void cache_delete_dir (Cache *cache, + const gchar *key, + GConfError **err); +Dir* cache_lookup (Cache *cache, + const gchar *key, + gboolean create_if_missing, + GConfError **err); + +#endif diff --git a/backends/xml-dir.c b/backends/xml-dir.c index a44fecc9..9d2a98b0 100644 --- a/backends/xml-dir.c +++ b/backends/xml-dir.c @@ -20,7 +20,60 @@ #include "xml-dir.h" #include "xml-entry.h" -typedef struct _Dir Dir; +#include <gnome-xml/parser.h> + +#include <stdio.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <dirent.h> +#include <limits.h> + +#include <gconf/gconf-internals.h> +#include "xml-entry.h" + +/* Quick hack so I can mark strings */ + +#ifdef _ +#warning "_ already defined" +#else +#define _(x) x +#endif + +#ifdef N_ +#warning "N_ already defined" +#else +#define N_(x) x +#endif + +/* This makes hash table safer when debugging */ +#ifndef GCONF_ENABLE_DEBUG +#define safe_g_hash_table_insert g_hash_table_insert +#else +static void +safe_g_hash_table_insert(GHashTable* ht, gpointer key, gpointer value) +{ + gpointer oldkey = NULL, oldval = NULL; + + if (g_hash_table_lookup_extended(ht, key, &oldkey, &oldval)) + { + gconf_log(GCL_WARNING, "Hash key `%s' is already in the table!", + (gchar*)key); + return; + } + else + { + g_hash_table_insert(ht, key, value); + } +} +#endif + +static gchar* parent_dir(const gchar* dir); struct _Dir { gchar* key; @@ -42,19 +95,16 @@ static Entry* dir_make_new_entry(Dir* d, const gchar* relative_key); static gboolean dir_forget_entry_if_useless(Dir* d, Entry* e); -Dir* -dir_new(const gchar *keyname, - const gchar *xml_root_dir) +static Dir* +dir_blank(const gchar* key) { Dir* d; d = g_new0(Dir, 1); - - d->key = g_strdup(keyname); - d->fs_dirname = g_concat_key_and_dir(xml_root_dir, keyname); - d->xml_filename = g_strconcat(d->fs_dirname, "/%gconf.xml", NULL); - d->root_dir_len = strlen(xml_root_dir); + g_assert(gconf_valid_key(key, NULL)); + + d->key = g_strdup(key); d->last_access = time(NULL); d->doc = NULL; @@ -67,6 +117,70 @@ dir_new(const gchar *keyname, return d; } +Dir* +dir_new(const gchar *keyname, + const gchar *xml_root_dir) +{ + Dir* d; + + d = dir_blank(keyname); + + /* sync with dir_load() */ + d->fs_dirname = gconf_concat_key_and_dir(xml_root_dir, keyname); + d->xml_filename = g_strconcat(d->fs_dirname, "/%gconf.xml", NULL); + d->root_dir_len = strlen(xml_root_dir); + + return d; +} + +Dir* +dir_load (const gchar* xml_root_dir, const gchar* key, GConfError** err) +{ + Dir* d; + gchar* fs_dirname; + gchar* xml_filename; + + fs_dirname = gconf_concat_key_and_dir(xml_root_dir, key); + xml_filename = g_strconcat(fs_dirname, "/%gconf.xml", NULL); + + { + struct stat s; + gboolean error = FALSE; + + if (stat(xml_filename, &s) != 0) + { + gconf_set_error(err, GCONF_FAILED, + _("Could not stat `%s': %s"), + xml_filename, strerror(errno)); + error = TRUE; + } + else if (S_ISDIR(s.st_mode)) + { + gconf_set_error(err, GCONF_FAILED, + _("XML filename `%s' is a directory"), + xml_filename); + error = TRUE; + } + + if (error) + { + g_free(fs_dirname); + g_free(xml_filename); + return NULL; + } + } + + d = dir_blank(key); + + /* sync with dir_new() */ + d->fs_dirname = fs_dirname; + d->xml_filename = xml_filename; + d->root_dir_len = strlen(xml_root_dir); + + return d; +} + + static void entry_destroy_foreach(const gchar* name, Entry* e, gpointer data) { @@ -99,11 +213,11 @@ gboolean dir_ensure_exists (Dir* d, GConfError** err) { - if (!create_fs_dir(d->fs_dirname, d->xml_filename, err)) + if (!create_fs_dir(d->fs_dirname, d->xml_filename, d->root_dir_len, err)) { /* check that error is set */ - g_return_val_if_fail( (err == NULL) || (*err != NULL), NULL ); + g_return_val_if_fail( (err == NULL) || (*err != NULL), FALSE ); return FALSE; } @@ -114,7 +228,7 @@ dir_ensure_exists (Dir* d, static void entry_sync_foreach(const gchar* name, Entry* e, gpointer data) { - entry_sync(e); + entry_sync_to_node(e); } gboolean @@ -171,7 +285,7 @@ dir_sync (Dir* d, GConfError** err) /* Try to solve the problem by creating the FS dir */ if (!gconf_file_exists(d->fs_dirname)) { - if (create_fs_dir(d->fs_dirname, NULL, d->source->root_dir, err)) + if (create_fs_dir(d->fs_dirname, NULL, d->root_dir_len, err)) { if (xmlSaveFile(tmp_filename, d->doc) >= 0) recovered = TRUE; @@ -266,7 +380,7 @@ dir_set_value (Dir* d, const gchar* relative_key, if (e == NULL) e = dir_make_new_entry(d, relative_key); - entry_set(e, value); + entry_set_value(e, value); d->last_access = time(NULL); entry_set_mod_time(e, d->last_access); @@ -309,7 +423,7 @@ dir_get_value (Dir* d, g_assert(e != NULL); - val = entry_get_value(e, locales); + val = entry_get_value(e, locales, err); /* Fill schema name if value is NULL because we might be interested in the default value of the key in that case. */ @@ -326,10 +440,16 @@ dir_get_value (Dir* d, } } +const gchar* +dir_get_name (Dir *d) +{ + g_return_val_if_fail(d != NULL, NULL); + return d->key; +} + GConfMetaInfo* dir_get_metainfo(Dir* d, const gchar* relative_key, GConfError** err) { - GConfMetaInfo* gcmi; Entry* e; d->last_access = time(NULL); @@ -373,7 +493,7 @@ dir_unset_value (Dir* d, const gchar* relative_key, if (e == NULL) /* nothing to change */ return; - if (entry_unset(e, locale)) + if (entry_unset_value(e, locale)) { /* If entry_unset() returns TRUE then the entry was changed (not already unset) */ @@ -406,16 +526,24 @@ listify_foreach(const gchar* key, Entry* e, ListifyData* ld) { GConfValue* val; GConfEntry* entry; + GConfError* error = NULL; - val = entry_get_value(e, ld->locales); + val = entry_get_value(e, ld->locales, &error); + if (error != NULL) + { + g_assert(val == NULL); + gconf_error_destroy(error); + return; + } + entry = gconf_entry_new_nocopy(g_strdup(key), val ? gconf_value_copy(val) : NULL); if (val == NULL && - e->schema_name) + entry_get_schema_name(e)) { - gconf_entry_set_schema_name(entry, e->schema_name); + gconf_entry_set_schema_name(entry, entry_get_schema_name(e)); } ld->list = g_slist_prepend(ld->list, entry); @@ -582,7 +710,7 @@ dir_last_access (Dir* d) /* private Dir functions */ static void -dir_fill_cache_from_doc(Dir* d); +dir_fill_cache_from_doc(Dir* d); static void dir_load_doc(Dir* d, GConfError** err) @@ -700,8 +828,8 @@ dir_make_new_entry(Dir* d, const gchar* relative_key) entry_set_node(e, xmlNewChild(d->doc->root, NULL, "entry", NULL)); - safe_g_hash_table_insert(d->entry_cache, entry_get_name(e), e); - + safe_g_hash_table_insert(d->entry_cache, (gchar*)entry_get_name(e), e); + return e; } @@ -713,7 +841,7 @@ dir_forget_entry_if_useless(Dir* d, Entry* e) if (entry_get_schema_name(e) != NULL) return FALSE; - val = entry_get_value(e, NULL); + val = entry_get_value(e, NULL, NULL); if (val != NULL) return FALSE; /* not useless */ @@ -725,6 +853,14 @@ dir_forget_entry_if_useless(Dir* d, Entry* e) return TRUE; } +static void +dir_fill_cache_from_doc(Dir* d) +{ + + /* FIXME */ + +} + /* * Misc */ @@ -798,3 +934,38 @@ create_fs_dir(const gchar* dir, const gchar* xml_filename, return TRUE; } + +static gchar* +parent_dir(const gchar* dir) +{ + /* We assume the dir doesn't have a trailing slash, since that's our + standard canonicalization in GConf */ + gchar* parent; + gchar* last_slash; + + g_return_val_if_fail(*dir != '\0', NULL); + + if (dir[1] == '\0') + { + g_assert(dir[0] == '/'); + return NULL; + } + + parent = g_strdup(dir); + + last_slash = strrchr(parent, '/'); + + /* dir must have had at least the root slash in it */ + g_assert(last_slash != NULL); + + if (last_slash != parent) + *last_slash = '\0'; + else + { + ++last_slash; + *last_slash = '\0'; + } + + return parent; +} + diff --git a/backends/xml-dir.h b/backends/xml-dir.h index 6fde7fe9..630c91b8 100644 --- a/backends/xml-dir.h +++ b/backends/xml-dir.h @@ -26,58 +26,53 @@ /* Dir stores the information about a given directory */ typedef struct _Dir Dir; - -Dir* dir_new (const gchar *keyname, - const gchar *xml_root_dir); - -void dir_destroy (Dir *d); - -gboolean dir_ensure_exists (Dir *d, - GConfError **err); - -gboolean dir_sync (Dir *d, - GConfError **err); - +Dir* dir_new (const gchar *keyname, + const gchar *xml_root_dir); +Dir* dir_load (const gchar *key, + const gchar *xml_root_dir, + GConfError **err); +void dir_destroy (Dir *d); +gboolean dir_ensure_exists (Dir *d, + GConfError **err); +gboolean dir_sync (Dir *d, + GConfError **err); + +const gchar* dir_get_name (Dir *d); /* key should have no slashes in it */ -void dir_set_value (Dir *d, - const gchar *relative_key, - GConfValue *value, - GConfError **err); - -GConfValue* dir_get_value (Dir *d, - const gchar *relative_key, - const gchar **locales, - gchar **schema_name, - GConfError **err); +void dir_set_value (Dir *d, + const gchar *relative_key, + GConfValue *value, + GConfError **err); +GConfValue* dir_get_value (Dir *d, + const gchar *relative_key, + const gchar **locales, + gchar **schema_name, + GConfError **err); +GConfMetaInfo* dir_get_metainfo (Dir *d, + const gchar *relative_key, + GConfError **err); +void dir_unset_value (Dir *d, + const gchar *relative_key, + const gchar *locale, + GConfError **err); +GSList* dir_all_entries (Dir *d, + const gchar **locales, + GConfError **err); +GSList* dir_all_subdirs (Dir *d, + GConfError **err); +void dir_set_schema (Dir *d, + const gchar *relative_key, + const gchar *schema_key, + GConfError **err); +GTime dir_get_last_access (Dir *d); -GConfMetaInfo* dir_get_metainfo (Dir *d, - const gchar *relative_key, - GConfError **err); - -void dir_unset_value (Dir *d, - const gchar *relative_key, - const gchar *locale, - GConfError **err); - -GSList* dir_all_entries (Dir *d, - const gchar **locales, - GConfError **err); - -GSList* dir_all_subdirs (Dir *d, - GConfError **err); - -void dir_set_schema (Dir *d, - const gchar *relative_key, - const gchar *schema_key, - GConfError **err); - -GTime dir_get_last_access (Dir *d); /* Marks for deletion; dir cache really has to implement directory deletion, since it is recursive */ -void dir_mark_deleted (Dir *d); -gboolean dir_is_deleted (Dir *d); +void dir_mark_deleted (Dir *d); +gboolean dir_is_deleted (Dir *d); + #endif diff --git a/backends/xml-entry.c b/backends/xml-entry.c index df9be270..6e1d38c9 100644 --- a/backends/xml-entry.c +++ b/backends/xml-entry.c @@ -18,6 +18,23 @@ */ #include "xml-entry.h" +#include <gconf/gconf-internals.h> +#include <stdlib.h> + +/* Quick hack so I can mark strings */ + +#ifdef _ +#warning "_ already defined" +#else +#define _(x) x +#endif + +#ifdef N_ +#warning "N_ already defined" +#else +#define N_(x) x +#endif + struct _Entry { gchar* name; /* a relative key */ @@ -88,9 +105,10 @@ entry_get_node (Entry*e) GConfValue* entry_get_value(Entry* e, const gchar** locales, GConfError** err) { - g_return_if_fail(e != NULL); + g_return_val_if_fail(e != NULL, NULL); /* FIXME */ + return NULL; } void @@ -103,10 +121,10 @@ entry_set_value(Entry* e, GConfValue* value) } gboolean -entry_unset_value (Entry *entry, +entry_unset_value (Entry *e, const gchar *locale) { - g_return_if_fail(e != NULL); + g_return_val_if_fail(e != NULL, FALSE); /* FIXME */ e->dirty = TRUE; @@ -119,7 +137,7 @@ entry_get_metainfo(Entry* e) { GConfMetaInfo* gcmi; - g_return_if_fail(e != NULL); + g_return_val_if_fail(e != NULL, NULL); gcmi = gconf_meta_info_new(); @@ -180,16 +198,31 @@ entry_set_mod_user (Entry *e, * XML-related cruft */ -void my_xmlSetProp(xmlNodePtr node, - const gchar* name, - const gchar* str); +static void my_xmlSetProp(xmlNodePtr node, + const gchar* name, + const gchar* str); -char* my_xmlGetProp(xmlNodePtr node, - const gchar* name); +static char* my_xmlGetProp(xmlNodePtr node, + const gchar* name); static GConfValue* node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err); +static xmlNodePtr +find_schema_subnode_by_locale(xmlNodePtr node, const gchar* locale); + +static void +entry_sync_if_needed(Entry* e, GConfValue* val) +{ + if (!e->dirty) + return; + + if (e->cached_value && + e->cached_value->type == GCONF_VALUE_SCHEMA) + { + entry_sync_to_node(e); + } +} void entry_fill_from_node(Entry* e, const gchar* name) @@ -265,8 +298,8 @@ entry_fill_from_node(Entry* e, const gchar* name) if (e->cached_value != NULL) gconf_value_destroy(e->cached_value); - e->cached_value = xentry_extract_value(e->node, NULL, /* FIXME current locale as a guess */ - &error); + e->cached_value = node_extract_value(e->node, NULL, /* FIXME current locale as a guess */ + &error); if (e->cached_value) { @@ -856,7 +889,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err) /* What the hell is this? */ gconf_log(GCL_WARNING, _("Didn't understand XML node <%s> inside an XML list node"), - iter->name ? iter->name : "???"); + iter->name ? iter->name : (guchar*)"???"); } if (v != NULL) @@ -881,7 +914,6 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err) GConfValue* car = NULL; GConfValue* cdr = NULL; xmlNodePtr iter; - GSList* bad_nodes = NULL; iter = node->childs; @@ -939,7 +971,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err) /* What the hell is this? */ gconf_log(GCL_WARNING, _("Didn't understand XML node <%s> inside an XML pair node"), - iter->name ? iter->name : "???"); + iter->name ? (gchar*)iter->name : "???"); } } iter = iter->next; @@ -965,7 +997,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err) */ /* makes setting to NULL or empty string equal to unset */ -void +static void my_xmlSetProp(xmlNodePtr node, const gchar* name, const gchar* str) @@ -1001,7 +1033,7 @@ my_xmlSetProp(xmlNodePtr node, } /* Makes empty strings equal to "unset" */ -char* +static char* my_xmlGetProp(xmlNodePtr node, const gchar* name) { |