/* * GConf BerkeleyDB back-end * * Copyright (C) 2000 Sun Microsystems Inc * Contributed to the GConf project. * * 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 #include #include #include #include "config.h" #include "bdb.h" #include "dir-utils.h" #include #include #include #include #include #include #include #include #include typedef struct _BDBSource BDBSource; struct _BDBSource { GConfSource source; /* inherit from GConfSource */ BDB_Store *bdb; gchar *root_dir; guint timeout_id; GConfLock *lock; }; /* *** { Forward declaration of all vtable functions */ static void vtable_bdb_shutdown (GError ** err); static GConfSource *vtable_bdb_resolve_address (const gchar * address, GError ** err); static void vtable_bdb_lock (GConfSource * source, GError ** err); static void vtable_bdb_unlock (GConfSource * source, GError ** err); static gboolean vtable_bdb_readable (GConfSource * source, const gchar * key, GError ** err); static gboolean vtable_bdb_writeable (GConfSource * source, const gchar * key, GError ** err); static GConfValue *vtable_bdb_query_value (GConfSource * source, const gchar * key, const gchar ** locales, gchar ** schema_name, GError ** err); static GConfMetaInfo *vtable_bdb_query_metainfo (GConfSource * source, const gchar * key, GError ** err); static void vtable_bdb_set_value (GConfSource * source, const gchar * key, GConfValue * value, GError ** err); static GSList *vtable_bdb_all_entries (GConfSource * source, const gchar * dir, const gchar ** locales, GError ** err); static GSList *vtable_bdb_all_subdirs (GConfSource * source, const gchar * dir, GError ** err); static void vtable_bdb_unset_value (GConfSource * source, const gchar * key, const gchar * locale, GError ** err); static gboolean vtable_bdb_dir_exists (GConfSource * source, const gchar * dir, GError ** err); static void vtable_bdb_remove_dir (GConfSource * source, const gchar * dir, GError ** err); static void vtable_bdb_set_schema (GConfSource * source, const gchar * key, const gchar * schema_key, GError ** err); static gboolean vtable_bdb_sync_all (GConfSource * source, GError ** err); static void vtable_bdb_destroy_source (GConfSource * source); static void vtable_bdb_clear_cache (GConfSource * source); /* *** } Forward declaration of all vtable functions */ static GConfBackendVTable _bdb_vtable = { vtable_bdb_shutdown, vtable_bdb_resolve_address, vtable_bdb_lock, vtable_bdb_unlock, vtable_bdb_readable, vtable_bdb_writeable, vtable_bdb_query_value, vtable_bdb_query_metainfo, vtable_bdb_set_value, vtable_bdb_all_entries, vtable_bdb_all_subdirs, vtable_bdb_unset_value, vtable_bdb_dir_exists, vtable_bdb_remove_dir, vtable_bdb_set_schema, vtable_bdb_sync_all, vtable_bdb_destroy_source, vtable_bdb_clear_cache }; /* *** { localised key utility functions */ const char LOCALISED_MARKER[] = "%locale%"; static char localised_buf[MAXPATHLEN]; gboolean bdb_is_localised (const gchar * key) { char *sflag_char = strchr (key, '%'); if (!sflag_char) return FALSE; if (strlen (sflag_char) > strlen (LOCALISED_MARKER)) { return memcmp (sflag_char, LOCALISED_MARKER, sizeof (LOCALISED_MARKER) - 1) == 0; } return FALSE; } static char * get_localised_key (const gchar * key, const gchar * locale) { size_t len = strlen (key) + strlen (LOCALISED_MARKER) + strlen (locale) + 2; char *lkey = localised_buf; char *s; if (len <= sizeof (localised_buf)) lkey = localised_buf; else lkey = malloc (len); strcpy (lkey, key); s = strrchr (lkey, '/'); sprintf (s, "%s%s/%s", LOCALISED_MARKER, locale, gconf_key_key (key)); return lkey; } static char * get_localised_dir (const gchar * dir, const gchar * locale) { size_t len = strlen (dir) + strlen (LOCALISED_MARKER) + strlen (locale) + 1; char *ldir = localised_buf; char *s; if (len <= sizeof (localised_buf)) ldir = localised_buf; else ldir = malloc (len); sprintf (ldir, "%s/%s%s", dir, LOCALISED_MARKER, locale); return ldir; } static void free_localised_buf (char *key) { if (key == localised_buf) return; free (key); } gboolean bdb_is_default_locale (const gchar * locale) { /* no locale - should be equivalent to C locale */ return ((*locale == '\0') || (strcmp (locale, "C") == 0)); } /* *** } localised key utility functions */ /* *** { BerkeleyDB backend methods */ static void vtable_bdb_shutdown (GError ** err) { gconf_log (GCL_DEBUG, _("Unloading BerkeleyDB (BDB) backend module.")); } /* vtable_bdb_resolve_address: * * Parameters: * address = store type and location of GConf database * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: */ static GConfSource * vtable_bdb_resolve_address (const gchar * address, GError ** err) { BDBSource *xsource = NULL; GConfSource *source; xsource = (BDBSource *) calloc (1, sizeof (BDBSource)); source = (GConfSource *) xsource; xsource->root_dir = _gconf_get_root_dir (address, &source->flags, "BerkeleyDB", err); xsource->bdb = bdb_new (xsource->root_dir, DB_CREATE); gconf_log (GCL_DEBUG, _("Opened BerkeleyDB source at root %s"), xsource->root_dir); return source; } static void vtable_bdb_lock (GConfSource * source, GError ** err) { /* TODO */ } static void vtable_bdb_unlock (GConfSource * source, GError ** err) { /* TODO */ } static gboolean vtable_bdb_readable (GConfSource * source, const gchar * key, GError ** err) { /* TODO: implement key-specific read/write control */ g_assert (source); return source->flags | GCONF_SOURCE_ALL_READABLE; } static gboolean vtable_bdb_writeable (GConfSource * source, const gchar * key, GError ** err) { /* TODO: implement key-specific read/write control */ g_assert (source); return source->flags | GCONF_SOURCE_ALL_WRITEABLE; } /* vtable_bdb_query_value: * * Parameters: * source = store to read * key = full-path key * locales = NULL-terminated list of preferred locales, preferred first * schema_name (returned if non-NULL) = schema key associated with 'key' * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns value associated with 'key', or the schema-information if no value * is stored. Uses 'locales' to identify preferred values. */ static GConfValue * vtable_bdb_query_value (GConfSource * source, const gchar * key, const gchar ** locales, gchar ** schema_name, GError ** err) { BDBSource *xs = (BDBSource *) source; GConfValue *value; const gchar *locale; if (!locales || (*locales == 0)) { return bdb_query_value (xs->bdb, key, schema_name, err); } while (locale = *locales++) { if (bdb_is_default_locale (locale)) { value = bdb_query_value (xs->bdb, key, schema_name, err); } else { char *localised_key = get_localised_key (key, locale); value = bdb_query_value (xs->bdb, localised_key, schema_name, err); free_localised_buf (localised_key); } if (value != NULL) return value; } return NULL; } /* vtable_bdb_query_metainfo: * * Parameters: * source = store to read * key = full-path key * err (returned if non-NULL) = error associated with schema-metainfo * retrieval (if any) * * Purpose: * Returns a GConfMetaInfo (containing schema-name, and last-modification info * for the schema setting) for a given key. */ static GConfMetaInfo * vtable_bdb_query_metainfo (GConfSource * source, const gchar * key, GError ** err) { BDBSource *xs = (BDBSource *) source; gchar *parent; parent = gconf_key_directory (key); if (parent != NULL) { /* TODO: return meta-info, if any */ } /* No metainfo found */ return NULL; } /* vtable_bdb_set_value: * * Parameters: * source = store to write * key = full-path key * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GConfMetaInfo (containing schema-name, and last-modification info * for the schema setting) for a given key. */ static void vtable_bdb_set_value (GConfSource * source, const gchar * key, GConfValue * value, GError ** err) { BDBSource *xs = (BDBSource *) source; g_return_if_fail (value != NULL); g_return_if_fail (source != NULL); bdb_put_value (xs->bdb, key, value, err); } /* vtable_bdb_all_entries: * * Parameters: * source = store to read * key = full-path key * locales = NULL-terminated list of preferred locales, preferred first * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns all entries in the key directory identified by the given 'key'. */ static GSList * vtable_bdb_all_entries (GConfSource * source, const gchar * dir, const gchar ** locales, GError ** err) { BDBSource *xs = (BDBSource *) source; GSList *list = NULL; const gchar *locale; if (!locales || (*locales == 0)) { /* didn't specify any locales */ return bdb_all_entries (xs->bdb, dir, NULL, err); } while (locale = *locales++) { char *localised_dir; if (bdb_is_default_locale (locale)) { list = bdb_all_entries (xs->bdb, dir, list, err); } else { localised_dir = get_localised_dir (dir, locale); list = bdb_all_entries (xs->bdb, localised_dir, list, err); free_localised_buf (localised_dir); } } return list; } /* vtable_bdb_all_subdirs: * * Parameters: * source = store to read * key = full-path key * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GSList containing all keys identifying sub-directories of * the given 'key'. */ static GSList * vtable_bdb_all_subdirs (GConfSource * source, const gchar * key, GError ** err) { BDBSource *xs = (BDBSource *) source; return bdb_all_subdirs (xs->bdb, key, err); } /* vtable_bdb_unset_value: * * Parameters: * source = store to read * key = full-path key * locale = identifies locale value to be unset * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GSList containing all keys identifying sub-directories of * the given 'key'. */ static void vtable_bdb_unset_value (GConfSource * source, const gchar * key, const gchar * locale, GError ** err) { BDBSource *xs = (BDBSource *) source; gconf_log (GCL_DEBUG, "BDB backend: unset value `%s'", key); bdb_unset_value (xs->bdb, key, locale, err); } /* vtable_bdb_dir_exists: * * Parameters: * source = store to read * key = full-path key * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GSList containing all keys identifying sub-directories of * the given 'key'. */ static gboolean vtable_bdb_dir_exists (GConfSource * source, const gchar * key, GError ** err) { BDBSource *xs = (BDBSource *) source; return bdb_dir_exists (xs->bdb, key, err); } /* vtable_bdb_remove_dir: * * Parameters: * source = store to read * key = full-path key * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GSList containing all keys identifying sub-directories of * the given 'key'. */ static void vtable_bdb_remove_dir (GConfSource * source, const gchar * key, GError ** err) { BDBSource *xs = (BDBSource *) source; g_assert (xs != 0); g_assert (key != 0); bdb_remove_dir (xs->bdb, key, err); } /* vtable_bdb_set_schema: * * Parameters: * source = store to read * key = full-path key * schema_key = full-path key * err (returned if non-NULL) = error associated with key or schema-retrieval (if any) * * Purpose: * Returns a GSList containing all keys identifying sub-directories of */ static void vtable_bdb_set_schema (GConfSource * source, const gchar * key, const gchar * schema_key, GError ** err) { BDBSource *xs = (BDBSource *) source; bdb_set_schema (xs->bdb, key, schema_key, err); } /* vtable_bdb_sync_all: * * Parameters: * source = store to write * err (returned if non-NULL) * * Purpose: * Flushes cached data to the database. */ static gboolean vtable_bdb_sync_all (GConfSource * source, GError ** err) { BDBSource *xs = (BDBSource *) source; /* TODO */ return TRUE; } /* vtable_bdb_destroy_source: * * Parameters: * source = store to write * * Purpose: * Destroys a GConfSource (like C++ object destructor). */ static void vtable_bdb_destroy_source (GConfSource * source) { BDBSource *xsource = (BDBSource *) source; g_assert (source); g_assert (xsource->bdb); bdb_close (xsource->bdb); free (xsource->root_dir); xsource->root_dir = 0; xsource->bdb = 0; } static void vtable_bdb_clear_cache (GConfSource * source) { BDBSource *xs = (BDBSource *) source; /* clean all entries older than 0 seconds */ /* TODO */ } /* *** } BerkeleyDB backend methods */ /* Initializer */ G_MODULE_EXPORT const gchar * g_module_check_init (GModule * module) { gconf_log (GCL_INFO, _("Initializing BDB backend module")); return NULL; } G_MODULE_EXPORT GConfBackendVTable * gconf_backend_get_vtable (void) { return &_bdb_vtable; }