1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* 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.
*/
/*
* Overview
*
* A GConf back-end is a storage implementation for the GConf API. Different
* back-ends or "drivers" are integrated into GConf using a struct
* GConfBackendVTable containing function pointers, simulating a C++
* virtual function pointer table (vtable).
*
* This back-end uses the BerkeleyDB database toolkit from Sleepycat
* software (www.sleepycat.com). BerkeleyDB is not a relational database,
* but is highly suited to GConf as it simply stores key-value pairs and
* is relatively efficient.
*
* The storage model if implemented in a relational database would
* use two tables:
*
* Directory structure table: { directory_path, id, parent_directory_id }
* Keyname/Value table: { key_name, directory_id, value }
*
* A keyname is the last element in the hierarchical key; a directory path
* is required to form the complete key - this composition of directory path
* and keyname is called a keypath.
*
* Because a BerkeleyDB database can only store a single key+value pair,
* this program splits these tables into four databases:
*
* Table: Key | Value: Data?
* ----- ----------- ----
* BDB_DIR directory_path | directory_id Yes
* BDB_HIERARCHY directory_id | child_directory_name No
* BDB_KEY directory_id | keyname No
* BDB_VALUE keypath | value Yes
* BDB_SCHEMA keypath | schema-key Yes
* BDB_SCHKEY directory_id | schema-key-name No
*
* A Data table is one that may not have records with identical keys. Other
* tables may not contain identical key-value pairs (i.e. two records
* could have the same key but must have different values).
*
* Note that an important goal is that all tables could be
* reconstructed from the BDB_VALUE table and the BDB_SCHEMA table. This
* is possible because the BDB_VALUE table contains the full key-name (the
* keypath) and the value, similar to the BDB_SCHEMA table; the other
* tables permit the database to be traversed hierarchically instead of
* linearly.
*
* Locales
*
* Locale data is stored in a subdirectory of the regular key directory for each
* locale; e.g. the Spanish locale data for a key /gnome/desktop/logo is
* /gnome/desktop/%locale%es/logo. This allows locale data to be found
* efficiently, e.g. the all_entries() backend method accepts a list of
* locales to be searched. If the list contains, { "es", "en", "C" }
* then the directories searched are /gnome/desktop/, /gnome/desktop/%locale%es,
* /gnome/desktop/%locale%en, and /gnome/desktop/%locale%C.
*
* Schemas
*
* Schemas are stored with regular keys in the BDB_VALUE database, but it
* is necessary to search for them specifically. This requires two databases,
* BDB_SCHEMA to store the "applyto" key (see the GConf docs) and the schema
* key under which the schema can be found. The BDB_SCHKEY is similar to the
* BDB_KEY database as it records the keys in each directory for which a
* schema value may be found.
*
* Locking
*
* GConf doesn't specify any locking functionality at the API level.
* Currently locking is a requirement, because workgroups and ultimately
* enterprises will require large central GConf databases to store
* common settings and defaults for users, although these users will
* also require separate writable stores for their personal preferences.
* For now, no locking functionality is implemented, but later locking may
* be required for individual key-value pairs and for hierarchies. The
* BDB_DIR database is locked when updating the highest integer id value
* assigned to a directory.
*
* Caching
*
* Ideally caching should be independent of any back-end, which can only
* be achieved by layering the cache on top of the back-ends rather than
* within each one, though this is not always practical/efficient. This
* implementation includes minimal caching for database structure, not
* for values. Even this caching should be above the back-ends, as it
* is time-consuming to find a key and to decide where it should be
* stored; if each store in GConf has a base path, then no queries are
* needed at run-time to locate keys for read or write.
*
* Atomic Saving
*
* BerkeleyDB transactions are used to do grouped writes.
*/
#ifndef BDB_H
#ifdef HAVE_DB3_DB_H
#include <db3/db.h>
#else
#include <db.h>
#endif
#include <glib.h>
#include <gconf/gconf.h>
#define DBD_DIR "dir.db"
#define DBD_HIERARCHY "hierarchy.db"
#define DBD_KEY "key.db"
#define DBD_VALUE "value.db"
#define DBD_SCHEMA "schema.db"
#define DBD_SCHKEY "schkey.db"
struct _BDB_Store;
typedef struct _BDB_Store
{
DB *dbdirp;
DB *dbhierp;
DB *dbkeyp;
DB *dbvalp;
DB *dbschp;
DB *dbschkeyp;
DBC *keycp;
DBC *schkeycp;
}
BDB_Store;
int bdb_create (BDB_Store * bdb, const char *dbname);
BDB_Store *bdb_new (const char *dir, int flags);
#define CLEAR_STRUCT(x) (memset(&x, 0, sizeof(x)))
extern DBT *temp_string_key (const char *key);
extern DBT *temp_int_key (int akey);
extern guint32 get_dir_id (BDB_Store * bdb, const char *dir);
extern void add_key (BDB_Store * bdb, const char *dir, const char *keypath);
extern void bdb_set_sysname (const char *name);
extern guint32 get_or_create_dir (BDB_Store * bdb, const char *dir);
int bdb_create (BDB_Store * bdb, const char *dir);
int bdb_open (BDB_Store * bdb, const char *dir, int flags);
void bdb_close (BDB_Store * bdb);
extern GConfValue *bdb_query_value (BDB_Store * bdb, const char *key,
char **schema_name, GError ** err);
extern GSList *bdb_all_dirs (BDB_Store * bdb, const char *dirname,
GError ** err);
extern GSList *bdb_all_entries (BDB_Store * bdb, const char *dirpath,
GSList * inlist, GError ** err);
extern void bdb_put_value (BDB_Store * bdb, const char *key, GConfValue * val,
GError ** err);
extern GSList *bdb_all_subdirs (BDB_Store * bdb, const char *dirname,
GError ** err);
extern void bdb_unset_value (BDB_Store * bdb, const char *keypath,
const char *locale, GError ** err);
extern void bdb_remove_dir (BDB_Store * bdb, const char *dirname,
GError ** err);
extern void bdb_set_schema (BDB_Store * bdb, const char *key,
const char *schema_key, GError ** err);
extern gboolean bdb_is_localised (const gchar * key);
#define struct_dup(x) g_memdup(&x, sizeof(x))
#endif /* BDB_H */
|