aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-04-11 19:54:43 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-04-11 19:54:43 +0000
commit06b8dd13216d028e7aa8a4bc028cac74532bd44c (patch)
tree3677a716519a1ae5fc6cbff0958dbfff1a645b00
parenta69565ae52c8e67f42149a1209eefb7ffb7aa568 (diff)
downloadmailfromd-06b8dd13216d028e7aa8a4bc028cac74532bd44c.tar.gz
mailfromd-06b8dd13216d028e7aa8a4bc028cac74532bd44c.tar.bz2
Rewrite mu_dbm functions; [WITH_BDB]: Use Concurrent Data Store approach.
git-svn-id: file:///svnroot/mailfromd/branches/release_3_1_patches@1349 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog14
-rw-r--r--doc/mailfromd.texi2
-rw-r--r--etc/mailfromd.rc1
-rw-r--r--src/bi_db.m418
-rw-r--r--src/cache.c4
-rw-r--r--src/db.c46
-rw-r--r--src/dnscache.c6
-rw-r--r--src/engine.c9
-rw-r--r--src/mu_dbm.c256
-rw-r--r--src/mu_dbm.h7
-rw-r--r--src/rate.c4
11 files changed, 253 insertions, 114 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b7aa617..b1c7bf77 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-04-11 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/mu_dbm.c, src/mu_dbm.h (mu_dbm_finish, mu_dbm_strerror): New
+ functions
+ (mu_dbm_firstkey, mu_dbm_nextkey): Change signature
+ [WITH_BDB]: Use Concurrent Data Store approach.
+ (all functions): Return a meaningful unambiguous code.
+ * src/cache.c, src/dnscache.c, src/db.c, src/rate.c,
+ src/bi_db.m4: Update for new mu_dbm interface.
+ * doc/mailfromd.texi: Bug fix.
+ * src/engine.c (child_finish): New function
+
+ * etc/mailfromd.rc: Remove obsolete option `retry'.
+
2007-04-06 Sergey Poznyakoff <gray@gnu.org.ua>
* src/symtab.c (db_format_install): Allocate .dbname
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 89630c63..0b7ec459 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -577,7 +577,7 @@ default, its full name is @file{@var{localstatedir}/mailfromd}. You
can change it by setting @code{DEFAULT_STATE_DIR} configuration
variable. This value can be changed at run-time using @code{#pragma
option state-directory} statement
-(@pxref{ANCHOR-PR-state-directory}).
+(@pxref{pragma state-directory}).
@item Select default communication socket.
@cindex default communication socket
diff --git a/etc/mailfromd.rc b/etc/mailfromd.rc
index 1b43e01f..69f58bd7 100644
--- a/etc/mailfromd.rc
+++ b/etc/mailfromd.rc
@@ -19,7 +19,6 @@
#pragma option relay "/etc/mail/sendmail.cw"
#pragma option relay "/etc/mail/relay-domains"
#pragma option timeout 33
-#pragma option retry 3
#pragma option mailfrom ""
#pragma option ehlo "your.domain"
#pragma regex +extended +icase
diff --git a/src/bi_db.m4 b/src/bi_db.m4
index 37a2f402..43318f2b 100644
--- a/src/bi_db.m4
+++ b/src/bi_db.m4
@@ -35,7 +35,7 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr,
mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
@@ -93,7 +93,7 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value,
MF_CATCH(mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = keystr;
MU_DATUM_SIZE(key) = strlen(keystr);
@@ -108,10 +108,11 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value,
mu_dbm_close(&db);
MF_ASSERT(rc == 0,
mf_dbfailure,
- "failed to insert data to %s: %s %s",
+ "failed to insert data to %s: (%s, %s): %s",
dbname,
key,
- value);
+ value,
+ mu_dbm_strerror());
}
END
@@ -124,7 +125,7 @@ MF_DEFUN(dbdel, VOID, STRING dbname, STRING keystr, OPTIONAL, NUMBER null)
MF_CATCH(mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = keystr;
MU_DATUM_SIZE(key) = strlen(keystr);
@@ -187,7 +188,7 @@ MF_DEFUN(greylist, NUMBER, STRING email, NUMBER interval)
rc = mu_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600,
&readonly);
MF_ASSERT(rc == 0, mf_dbfailure, "mu_dbm_open(%s) failed: %s",
- greylist_format->dbname, mu_strerror(errno));
+ greylist_format->dbname, mu_dbm_strerror());
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
@@ -252,8 +253,9 @@ MF_DEFUN(greylist, NUMBER, STRING email, NUMBER interval)
MU_DATUM_SIZE(contents) = sizeof now;
if (mu_dbm_insert(&db, key, contents, 1))
mu_error("Cannot insert datum in greylist "
- "database %s",
- greylist_format->dbname);
+ "database %s: %s",
+ greylist_format->dbname,
+ mu_dbm_strerror());
rc = 1;
} else
rc = 0;
diff --git a/src/cache.c b/src/cache.c
index 9175c47d..9316ce04 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -45,7 +45,7 @@ cache_get(char *email)
if (mu_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600,
&readonly)) {
mu_error("mu_dbm_open(%s) failed: %s", cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return mf_failure;
}
if (readonly)
@@ -102,7 +102,7 @@ cache_insert(char *email, mf_status rc)
mailfromd_timestr(res.timestamp, timebuf, sizeof timebuf));
if (mu_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return;
}
diff --git a/src/db.c b/src/db.c
index fc497458..f6cdff4a 100644
--- a/src/db.c
+++ b/src/db.c
@@ -38,7 +38,7 @@ db_list_item(char *dbname, char *email, db_item_printer_t fun)
if (mu_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
memset (&contents, 0, sizeof contents);
@@ -61,14 +61,15 @@ db_list(char *dbname, db_item_printer_t fun)
DBM_FILE db;
DBM_DATUM key, contents;
int rc = 0;
+ int res;
if (mu_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- for (key = mu_dbm_firstkey (&db); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&db, key)) {
+ for (res = mu_dbm_firstkey (&db, &key); res == 0;
+ res = mu_dbm_nextkey (&db, key, &key)) {
memset (&contents, 0, sizeof contents);
if (mu_dbm_fetch (&db, key, &contents) == 0) {
fun(MU_DATUM_PTR(key),
@@ -81,6 +82,7 @@ db_list(char *dbname, db_item_printer_t fun)
rc = 1;
}
}
+ /* FIXME: if res != MU_ERR_NOENT */
mu_dbm_close(&db);
return 1;
}
@@ -95,17 +97,18 @@ db_expire(char *dbname, db_expire_t fun)
char *base, *p;
size_t i, key_count = 0;
int rc = 0;
+ int res;
if (mu_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
obstack_init(&stk);
debug1(1, "Expiring %s: mark phase", dbname);
- for (key = mu_dbm_firstkey (&db); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&db, key)) {
+ for (res = mu_dbm_firstkey (&db, &key); res == 0;
+ res = mu_dbm_nextkey (&db, key, &key)) {
memset (&contents, 0, sizeof contents);
if (mu_dbm_fetch (&db, key, &contents) == 0) {
if (fun(MU_DATUM_PTR(contents))) {
@@ -122,6 +125,8 @@ db_expire(char *dbname, db_expire_t fun)
}
mu_dbm_datum_free (&contents);
}
+ /* FIXME: if res != MU_ERR_NOENT */
+
size = 0;
obstack_grow(&stk, &size, sizeof size);
@@ -162,14 +167,15 @@ db_delete(char *dbname, char *id)
if (mu_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = id;
MU_DATUM_SIZE(key) = strlen (id) + 1;
if (mu_dbm_delete(&db, key)) {
- mu_error("Cannot remove record for %s", id);
+ mu_error("Cannot remove record for %s: %s", id,
+ mu_dbm_strerror());
rc = 1;
} else
rc = 0;
@@ -207,6 +213,7 @@ db_compact(char *dbname, db_expire_t fun)
DBM_FILE odb, ndb;
int rc = 0;
char *tmpname;
+ int res;
debug1(1, "Compacting database `%s'", dbname);
@@ -214,23 +221,24 @@ db_compact(char *dbname, db_expire_t fun)
if (mu_dbm_open(dbname, &odb, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
if (mu_dbm_open(tmpname, &ndb, MU_STREAM_CREAT, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", tmpname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- for (key = mu_dbm_firstkey (&odb); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&odb, key)) {
+ for (res = mu_dbm_firstkey (&odb, &key); res == 0;
+ res = mu_dbm_nextkey (&odb, key, &key)) {
memset (&contents, 0, sizeof contents);
if (mu_dbm_fetch (&odb, key, &contents)) {
rc = !ignore_failed_reads_option;
- mu_error("Cannot fetch data for %*.*s",
+ mu_error("Cannot fetch data for %*.*s: %s",
MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
- MU_DATUM_PTR(key));
+ MU_DATUM_PTR(key),
+ mu_dbm_strerror());
continue;
}
if (!fun || fun(MU_DATUM_PTR(contents)) == 0) {
@@ -254,17 +262,21 @@ db_compact(char *dbname, db_expire_t fun)
MU_DATUM_SIZE(newkey) = size+1;
MU_DATUM_PTR(newkey) = p;
if (mu_dbm_insert(&ndb, newkey, contents, 1)) {
- mu_error ("Cannot insert datum");
+ mu_error ("Cannot insert datum: %s",
+ mu_dbm_strerror());
rc = 1;
}
free(p);
} else if (mu_dbm_insert(&ndb, key, contents, 1)) {
- mu_error ("Cannot insert datum");
+ mu_error ("Cannot insert datum: %s",
+ mu_dbm_strerror());
rc = 1;
}
}
mu_dbm_datum_free (&contents);
}
+ /* FIXME: if res != MU_ERR_NOENT */
+
mu_dbm_close(&ndb);
mu_dbm_close(&odb);
diff --git a/src/dnscache.c b/src/dnscache.c
index d8410de1..bb4bd2d4 100644
--- a/src/dnscache.c
+++ b/src/dnscache.c
@@ -117,7 +117,7 @@ dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
NULL)) {
mu_error("mu_dbm_open(%s) failed: %s",
dns_cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
dns_free_key(&key);
return mf_failure;
}
@@ -165,7 +165,7 @@ dns_cache_put(int type, const char *keystr, time_t ttl,
0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s",
dns_cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
dns_free_key(&key);
return;
}
@@ -193,7 +193,7 @@ dns_cache_put(int type, const char *keystr, time_t ttl,
MU_DATUM_PTR(contents) = p;
MU_DATUM_SIZE(contents) = blen + 1 + len + 1;
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error("Cannot insert datum");
+ mu_error("Cannot insert datum: %s", mu_dbm_strerror());
free(p);
}
mu_dbm_close(&db);
diff --git a/src/engine.c b/src/engine.c
index 5548dd87..ff62333a 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1098,6 +1098,13 @@ child_start()
return 0;
}
+static int
+child_finish()
+{
+ mu_dbm_finish();
+ return 0;
+}
+
struct smfiDesc smfilter =
{
"MailfromFilter",
@@ -1117,7 +1124,7 @@ struct smfiDesc smfilter =
NULL, /* unknown command handler */
NULL, /* data handler */
child_start, /* child start */
- NULL, /* child finish */
+ child_finish, /* child finish */
NULL /* idle callback */
#endif
};
diff --git a/src/mu_dbm.c b/src/mu_dbm.c
index f8069107..699dd609 100644
--- a/src/mu_dbm.c
+++ b/src/mu_dbm.c
@@ -78,6 +78,11 @@ mu_check_perm (const char *name, int mode)
#if defined(WITH_GDBM)
+void
+mu_dbm_finish ()
+{
+}
+
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
{
@@ -87,7 +92,7 @@ mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
GDBM_FILE gdbm;
if (mu_check_perm (name, mode))
- return -1;
+ return MU_ERR_UNSAFE_PERMS;
if (ro)
*ro = 0;
@@ -96,35 +101,39 @@ mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
case MU_STREAM_CREAT:
f = GDBM_NEWDB;
break;
+
case MU_STREAM_READ:
f = GDBM_READER;
break;
+
case MU_STREAM_RDWR:
f = GDBM_WRCREAT;
break;
+
default:
errno = EINVAL;
return 1;
}
- for (i = 0; i < lock_retry_count_option; i++) {
- gdbm = gdbm_open(name, 512, f, mode, NULL);
- if (gdbm || errno != EAGAIN)
- break;
- sleep(lock_retry_timeout_option);
- }
+ for (i = 0; i < lock_retry_count_option; i++)
+ {
+ gdbm = gdbm_open (name, 512, f, mode, NULL);
+ if (gdbm || errno != EAGAIN)
+ break;
+ sleep (lock_retry_timeout_option);
+ }
if (!gdbm)
{
if (ro)
{
- gdbm = gdbm_open(name, 512, GDBM_READER, mode, NULL);
+ gdbm = gdbm_open (name, 512, GDBM_READER, mode, NULL);
if (gdbm)
*ro = 1;
}
}
- rc = gdbm == NULL;
+ rc = (gdbm == NULL) ? MU_ERR_FAILURE : 0;
if (rc == 0)
{
@@ -147,57 +156,98 @@ int
mu_dbm_fetch (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *ret)
{
*ret = gdbm_fetch(db->db, key);
- return ret->dptr == NULL;
+ if (ret->dptr == NULL)
+ return MU_ERR_NOENT;
+ return 0;
}
int
mu_dbm_delete (DBM_FILE *db, DBM_DATUM key)
{
- return gdbm_delete (db->db, key);
+ return gdbm_delete (db->db, key) ? MU_ERR_FAILURE : 0;
}
int
mu_dbm_insert (DBM_FILE *db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
- return gdbm_store(db->db, key, contents,
- replace ? GDBM_REPLACE : GDBM_INSERT);
+ switch (gdbm_store(db->db, key, contents,
+ replace ? GDBM_REPLACE : GDBM_INSERT))
+ {
+ case -1:
+ return MU_ERR_FAILURE;
+
+ case 0:
+ return 0;
+
+ case 1:
+ return MU_ERR_EXISTS;
+ }
+ return MU_ERR_FAILURE;
}
-DBM_DATUM
-mu_dbm_firstkey (DBM_FILE *db)
+int
+mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey)
{
- return gdbm_firstkey (db->db);
+ *pkey = gdbm_firstkey (db->db);
+ return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
}
-DBM_DATUM
-mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM key)
+int
+mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM prevkey, DBM_DATUM *pkey)
{
- return gdbm_nextkey (db->db, key);
+ *pkey = gdbm_nextkey (db->db, prevkey);
+ return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
}
void
-mu_dbm_datum_free(DBM_DATUM *datum)
+mu_dbm_datum_free (DBM_DATUM *datum)
{
- void *ptr = MU_DATUM_PTR(*datum);
+ void *ptr = MU_DATUM_PTR (*datum);
if (ptr)
- free(ptr);
- MU_DATUM_PTR(*datum) = 0;
+ free (ptr);
+ MU_DATUM_PTR (*datum) = 0;
+}
+
+const char *
+mu_dbm_strerror ()
+{
+ return gdbm_strerror (gdbm_errno);
}
#elif defined(WITH_BDB)
+int mu_dbm_errno;
+
#if DB_VERSION_MAJOR >= 2
static DB_ENV *dbenv;
+# if DB_VERSION_MAJOR == 2
+# define FREE_ENV() db_appexit (dbenv)
+# else
+# define FREE_ENV() \
+ if (dbenv) \
+ { \
+ dbenv->remove (dbenv, mailfromd_state_dir, 0); \
+ dbenv->close (dbenv, 0); \
+ }
+# endif
+#else
+# define FREE_ENV()
#endif
+void
+mu_dbm_finish ()
+{
+ FREE_ENV ();
+}
+
int
mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
{
int f, rc;
- DB *db;
+ DB *db = NULL;
if (mu_check_perm (name, mode))
- return -1;
+ return MU_ERR_UNSAFE_PERMS;
#if DB_VERSION_MAJOR >= 2
if (!dbenv)
@@ -205,23 +255,29 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
# if DB_VERSION_MAJOR == 2
dbenv = calloc (1, sizeof dbenv[0]);
if (!dbenv)
- return 1;
- if (db_appinit (mailfromd_state_dir, NULL, dbenv,
- DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL))
- return 1;
+ {
+ mu_dbm_errno = ENOMEM;
+ return MU_ERR_FAILURE;
+ }
+ mu_dbm_errno = db_appinit (mailfromd_state_dir, NULL, dbenv,
+ DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL);
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
# else
- if (rc = db_env_create (&dbenv, 0))
+ if (mu_dbm_errno = db_env_create (&dbenv, 0))
{
- mu_error ("Cannot create DB environment: %s", db_strerror (rc));
- return 1;
+ mu_error ("Cannot create DB environment: %s",
+ db_strerror (mu_dbm_errno));
+ return MU_ERR_FAILURE;
}
- if (rc = dbenv->open (dbenv, mailfromd_state_dir,
+ if (mu_dbm_errno = dbenv->open (dbenv, mailfromd_state_dir,
DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL,
0600))
{
- mu_error ("Cannot open DB environment: %s", db_strerror(rc));
- return 1;
+ mu_error ("Cannot open DB environment: %s",
+ db_strerror(mu_dbm_errno));
+ return MU_ERR_FAILURE;
}
# endif /* DB_VERSION_MAJOR == 2 */
}
@@ -250,19 +306,19 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
}
#if DB_VERSION_MAJOR == 2
- rc = db_open (name, DB_HASH, f, mode, dbenv, NULL, &db);
+ mu_dbm_errno = db_open (name, DB_HASH, f, mode, dbenv, NULL, &db);
#else
- rc = db_create (&db, dbenv, 0);
- if (rc != 0 || db == NULL)
- return rc;
+ mu_dbm_errno = db_create (&db, dbenv, 0);
+ if (mu_dbm_errno != 0 || db == NULL)
+ return MU_ERR_FAILURE;
# if DB_VERSION_MAJOR == 3
- rc = db->open (db, name, NULL, DB_HASH, f, mode);
+ mu_dbm_errno = db->open (db, name, NULL, DB_HASH, f, mode);
# else
- rc = db->open (db, NULL, name, NULL, DB_HASH, f, mode);
+ mu_dbm_errno = db->open (db, NULL, name, NULL, DB_HASH, f, mode);
# endif
#endif
- if (rc)
- return -1;
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
dbm->name = strdup (name);
dbm->db = db;
@@ -273,79 +329,121 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
int
mu_dbm_close (DBM_FILE *db)
{
- db->db->close (db->db, 0);
+ if (db->dbc)
+ {
+ mu_dbm_errno = db->dbc->c_close(db->dbc);
+ db->dbc = NULL;
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
+ }
+ mu_dbm_errno = db->db->close (db->db, 0);
+ if (mu_dbm_errno == DB_INCOMPLETE)
+ mu_dbm_errno = 0;
free (db->name);
- return 0;
+ return (mu_dbm_errno == 0) ? 0 : MU_ERR_FAILURE;
}
int
mu_dbm_fetch (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *ret)
{
- return db->db->get (db->db, NULL, &key, ret, 0);
+ mu_dbm_errno = db->db->get (db->db, NULL, &key, ret, 0);
+ switch (mu_dbm_errno)
+ {
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
+ }
}
int
mu_dbm_delete (DBM_FILE *db, DBM_DATUM key)
{
- return db->db->del (db->db, NULL, &key, 0);
+ return (mu_dbm_errno = db->db->del (db->db, NULL, &key, 0))
+ ? MU_ERR_FAILURE : 0;
}
int
mu_dbm_insert (DBM_FILE *db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
- /*FIXME: replace unused*/
- return db->db->put (db->db, NULL, &key, &contents, 0);
+ int flags = replace ? 0 : DB_NOOVERWRITE;
+ mu_dbm_errno = db->db->put (db->db, NULL, &key, &contents, flags);
+ switch (mu_dbm_errno)
+ {
+ case 0:
+ return 0;
+
+ case DB_KEYEXIST:
+ return MU_ERR_EXISTS;
+
+ default:
+ return MU_ERR_FAILURE;
+ }
}
-DBM_DATUM
-mu_dbm_firstkey (DBM_FILE *db)
+int
+mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey)
{
- DBT key, data;
+ DBT data;
int ret;
- memset(&key, 0, sizeof key);
+ memset(pkey, 0, sizeof *pkey);
memset(&data, 0, sizeof data);
if (!db->dbc)
{
- if (db->db->cursor(db->db, NULL, &db->dbc BDB2_CURSOR_LASTARG) != 0)
- return key;
+ mu_dbm_errno = db->db->cursor(db->db, NULL, &db->dbc
+ BDB2_CURSOR_LASTARG);
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
}
- if ((ret = db->dbc->c_get(db->dbc, &key, &data, DB_FIRST)) != 0)
+ mu_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_FIRST);
+ switch (mu_dbm_errno)
{
- key.data = NULL;
- key.size = 0;
- if (ret == DB_NOTFOUND)
- errno = MU_ERR_NOENT;
- else
- errno = ret;
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
}
- return key;
}
-DBM_DATUM
-mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM pkey /*unused*/)
+int
+mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM prevkey /*unused*/, DBM_DATUM *pkey)
{
- DBT key, data;
+ DBT data;
int ret;
- memset(&key, 0, sizeof key);
+ memset(pkey, 0, sizeof *pkey);
memset(&data, 0, sizeof data);
if (!db->dbc)
- return key;
+ {
+ mu_dbm_errno = EINVAL;
+ return MU_ERR_FAILURE;
+ }
+
+ mu_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_NEXT);
- if ((ret = db->dbc->c_get(db->dbc, &key, &data, DB_NEXT)) != 0)
+ switch (mu_dbm_errno)
{
- key.data = NULL;
- key.size = 0;
- if (ret == DB_NOTFOUND)
- errno = MU_ERR_NOENT;
- else
- errno = ret;
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
}
- return key;
}
void
@@ -354,6 +452,12 @@ mu_dbm_datum_free(DBM_DATUM *datum)
/* empty */
}
+const char *
+mu_dbm_strerror ()
+{
+ return db_strerror (mu_dbm_errno);
+}
+
#endif
/*
diff --git a/src/mu_dbm.h b/src/mu_dbm.h
index 0722e8b1..e4742bba 100644
--- a/src/mu_dbm.h
+++ b/src/mu_dbm.h
@@ -59,10 +59,11 @@ int mu_dbm_close (DBM_FILE *db);
int mu_dbm_fetch (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *ret);
int mu_dbm_insert (DBM_FILE *db, DBM_DATUM key, DBM_DATUM contents, int replace);
int mu_dbm_delete (DBM_FILE *db, DBM_DATUM key);
-DBM_DATUM mu_dbm_firstkey (DBM_FILE *db);
-DBM_DATUM mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM key);
+int mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey);
+int mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *pkey);
void mu_dbm_datum_free(DBM_DATUM *datum);
-
+const char *mu_dbm_strerror (void);
+void mu_dbm_finish (void);
#else
# define mu_dbm_datum_free(datum)
#endif
diff --git a/src/rate.c b/src/rate.c
index 49e607c0..4c06c191 100644
--- a/src/rate.c
+++ b/src/rate.c
@@ -45,7 +45,7 @@ get_rate(char *email, double *ret)
debug1(50, "getting rate info for %s", email);
if (mu_dbm_open(rate_format->dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", rate_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return mf_failure;
}
@@ -94,7 +94,7 @@ get_rate(char *email, double *ret)
MU_DATUM_PTR(contents) = (void*)rp;
MU_DATUM_SIZE(contents) = sizeof(*rp);
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error ("Cannot insert datum");
+ mu_error ("Cannot insert datum: %s", mu_dbm_strerror());
if (!local_contents)
mu_dbm_datum_free(&contents);

Return to:

Send suggestions and report system problems to the System administrator.