diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-11 19:54:43 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-11 19:54:43 +0000 |
commit | 06b8dd13216d028e7aa8a4bc028cac74532bd44c (patch) | |
tree | 3677a716519a1ae5fc6cbff0958dbfff1a645b00 | |
parent | a69565ae52c8e67f42149a1209eefb7ffb7aa568 (diff) | |
download | mailfromd-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-- | ChangeLog | 14 | ||||
-rw-r--r-- | doc/mailfromd.texi | 2 | ||||
-rw-r--r-- | etc/mailfromd.rc | 1 | ||||
-rw-r--r-- | src/bi_db.m4 | 18 | ||||
-rw-r--r-- | src/cache.c | 4 | ||||
-rw-r--r-- | src/db.c | 46 | ||||
-rw-r--r-- | src/dnscache.c | 6 | ||||
-rw-r--r-- | src/engine.c | 9 | ||||
-rw-r--r-- | src/mu_dbm.c | 256 | ||||
-rw-r--r-- | src/mu_dbm.h | 7 | ||||
-rw-r--r-- | src/rate.c | 4 |
11 files changed, 253 insertions, 114 deletions
@@ -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; } @@ -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 @@ -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); |