1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * JP Rosevear (jpr@ximian.com)
6 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
11 * @short_description: Simple DB-based hash table for strings
13 * An #EDbHash is a simple hash table of strings backed by a Berkeley DB
14 * file for permanent storage.
25 struct _EDbHashPrivate {
31 * @filename: path to a Berkeley DB file
33 * Creates a new #EDbHash structure and opens the given Berkeley DB file,
34 * creating the DB file if necessary.
36 * Returns: a new #EDbHash
39 e_dbhash_new (const gchar *filename)
45 /* Attempt to open the database */
46 rv = db_create (&db, NULL, 0);
51 rv = (*db->open) (db, NULL, filename, NULL, DB_HASH, 0, 0666);
53 /* Close and re-create the db handle to avoid memory leak */
55 rv = db_create (&db, NULL, 0);
61 db, NULL, filename, NULL, DB_HASH, DB_CREATE, 0666);
69 edbh = g_new (EDbHash, 1);
70 edbh->priv = g_new (EDbHashPrivate, 1);
77 string_to_dbt (const gchar *str,
80 memset (dbt, 0, sizeof (DBT));
81 dbt->data = (gpointer) str;
82 dbt->size = strlen (str) + 1;
86 md5_to_dbt (const guint8 str[16],
89 memset (dbt, 0, sizeof (DBT));
90 dbt->data = (gpointer) str;
97 * @key: a database key
98 * @data: a database object for @key
100 * Adds a database object for @key.
103 e_dbhash_add (EDbHash *edbh,
114 g_return_if_fail (edbh != NULL);
115 g_return_if_fail (edbh->priv != NULL);
116 g_return_if_fail (edbh->priv->db != NULL);
117 g_return_if_fail (key != NULL);
118 g_return_if_fail (data != NULL);
120 length = g_checksum_type_get_length (G_CHECKSUM_MD5);
121 digest = g_alloca (length);
126 string_to_dbt (key, &dkey);
128 /* Compute MD5 checksum */
129 checksum = g_checksum_new (G_CHECKSUM_MD5);
130 g_checksum_update (checksum, (guchar *) data, -1);
131 g_checksum_get_digest (checksum, digest, &length);
132 g_checksum_free (checksum);
135 md5_to_dbt (digest, &ddata);
137 /* Add to database */
138 db->put (db, NULL, &dkey, &ddata, 0);
144 * @key: a database key
146 * Removes the database object corresponding to @key.
149 e_dbhash_remove (EDbHash *edbh,
155 g_return_if_fail (edbh != NULL);
156 g_return_if_fail (edbh->priv != NULL);
157 g_return_if_fail (key != NULL);
162 string_to_dbt (key, &dkey);
164 /* Remove from database */
165 db->del (db, NULL, &dkey, 0);
169 * e_dbhash_foreach_key:
171 * @func: a callback function
172 * @user_data: data to pass to @func
174 * Calls @func for each database object.
177 e_dbhash_foreach_key (EDbHash *edbh,
187 g_return_if_fail (edbh != NULL);
188 g_return_if_fail (edbh->priv != NULL);
189 g_return_if_fail (func != NULL);
193 db_error = db->cursor (db, NULL, &dbc, 0);
199 memset (&dkey, 0, sizeof (DBT));
200 memset (&ddata, 0, sizeof (DBT));
201 db_error = dbc->c_get (dbc, &dkey, &ddata, DB_FIRST);
203 while (db_error == 0) {
204 (*func) ((const gchar *) dkey.data, user_data);
206 db_error = dbc->c_get (dbc, &dkey, &ddata, DB_NEXT);
214 * @key: a database key
215 * @compare_data: data to compare against the database
217 * Compares @compare_data to the database object corresponding to
218 * @key using an MD5 checksum. Returns #E_DBHASH_STATUS_SAME if the
219 * checksums match, #E_DBHASH_STATUS_DIFFERENT if the checksums differ,
220 * or #E_DBHASH_STATUS_NOT_FOUND if @key is not present in the database.
222 * Returns: a checksum comparison status
225 e_dbhash_compare (EDbHash *edbh,
227 const gchar *compare_data)
232 guint8 compare_hash[16];
233 gsize length = sizeof (compare_hash);
235 g_return_val_if_fail (edbh != NULL, FALSE);
236 g_return_val_if_fail (edbh->priv != NULL, FALSE);
237 g_return_val_if_fail (key != NULL, FALSE);
238 g_return_val_if_fail (compare_hash != NULL, FALSE);
243 string_to_dbt (key, &dkey);
245 /* Lookup in database */
246 memset (&ddata, 0, sizeof (DBT));
247 db->get (db, NULL, &dkey, &ddata, 0);
253 checksum = g_checksum_new (G_CHECKSUM_MD5);
254 g_checksum_update (checksum, (guchar *) compare_data, -1);
255 g_checksum_get_digest (checksum, compare_hash, &length);
256 g_checksum_free (checksum);
258 if (memcmp (ddata.data, compare_hash, sizeof (guchar) * 16))
259 return E_DBHASH_STATUS_DIFFERENT;
261 return E_DBHASH_STATUS_NOT_FOUND;
264 return E_DBHASH_STATUS_SAME;
271 * Flushes database changes to disk.
274 e_dbhash_write (EDbHash *edbh)
278 g_return_if_fail (edbh != NULL);
279 g_return_if_fail (edbh->priv != NULL);
283 /* Flush database to disk */
291 * Closes the database file and frees the #EDbHash.
294 e_dbhash_destroy (EDbHash *edbh)
298 g_return_if_fail (edbh != NULL);
299 g_return_if_fail (edbh->priv != NULL);