tdb2: make TDB1 code use tdb2's TDB_ERROR and tdb_logerr()
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 05:48:16 +0000 (15:18 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 31 Aug 2011 05:48:16 +0000 (15:18 +0930)
To do this, we make sure that the first few fields of tdb1_context and
tdb_context are the same.

This sweep also fixes up a few paths where we weren't setting
tdb->ecode before our old logging function.

23 files changed:
ccan/tdb2/private.h
ccan/tdb2/tdb1.h
ccan/tdb2/tdb1_check.c
ccan/tdb2/tdb1_freelist.c
ccan/tdb2/tdb1_io.c
ccan/tdb2/tdb1_lock.c
ccan/tdb2/tdb1_open.c
ccan/tdb2/tdb1_private.h
ccan/tdb2/tdb1_summary.c
ccan/tdb2/tdb1_tdb.c
ccan/tdb2/tdb1_transaction.c
ccan/tdb2/tdb1_traverse.c
ccan/tdb2/test/run-tdb1-3G-file.c
ccan/tdb2/test/run-tdb1-check.c
ccan/tdb2/test/run-tdb1-endian.c
ccan/tdb2/test/run-tdb1-incompatible.c
ccan/tdb2/test/run-tdb1-nested-transactions.c
ccan/tdb2/test/run-tdb1-readonly-check.c
ccan/tdb2/test/run-tdb1-rwlock-check.c
ccan/tdb2/test/run-tdb1-wronghash-fail.c
ccan/tdb2/test/run-tdb1.c
ccan/tdb2/test/tdb1-external-agent.c
ccan/tdb2/test/tdb1-logging.c

index 8d961e82c365c6b0f6956fbf1019451c285597f5..f6ed65a90969596e2661995f974a4b8f4fd6bd67 100644 (file)
@@ -336,6 +336,9 @@ struct tdb_context {
                       void *data);
        void *log_data;
 
+       /* Last error we returned. */
+       enum TDB_ERROR last_error;
+
        /* Open flags passed to tdb_open. */
        int open_flags;
 
@@ -375,9 +378,6 @@ struct tdb_context {
        /* Direct access information */
        struct tdb_access_hdr *access;
 
-       /* Last error we returned. */
-       enum TDB_ERROR last_error;
-
        /* The actual file information */
        struct tdb_file *file;
 };
index 8ce5fa9d0777515aede35c4151ff55b4bccf2466..8b3130ad2a788fbe79e0b14ea0215dd4b2988807 100644 (file)
 #define TDB1_DISALLOW_NESTING 1024 /** Disallow transactions to nest */
 #define TDB1_INCOMPATIBLE_HASH 2048 /** Better hashing: can't be opened by tdb < 1.2.6. */
 
-/** The tdb error codes */
-enum TDB1_ERROR {TDB1_SUCCESS=0, TDB1_ERR_CORRUPT, TDB1_ERR_IO, TDB1_ERR_LOCK,
-               TDB1_ERR_OOM, TDB1_ERR_EXISTS, TDB1_ERR_NOLOCK, TDB1_ERR_LOCK_TIMEOUT,
-               TDB1_ERR_NOEXIST, TDB1_ERR_EINVAL, TDB1_ERR_RDONLY,
-               TDB1_ERR_NESTING};
-
-/** Debugging uses one of the following levels */
-enum tdb1_debug_level {TDB1_DEBUG_FATAL = 0, TDB1_DEBUG_ERROR,
-                     TDB1_DEBUG_WARNING, TDB1_DEBUG_TRACE};
-
 /** The tdb data structure */
 typedef struct TDB1_DATA {
        unsigned char *dptr;
        size_t dsize;
 } TDB1_DATA;
 
-#ifndef PRINTF_ATTRIBUTE
-#if (__GNUC__ >= 3)
-/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
-
 /** This is the context structure that is returned from a db open. */
 typedef struct tdb1_context TDB1_CONTEXT;
 
 typedef int (*tdb1_traverse_func)(struct tdb1_context *, TDB1_DATA, TDB1_DATA, void *);
-typedef void (*tdb1_log_func)(struct tdb1_context *, enum tdb1_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4);
+typedef void (*tdb1_log_func)(struct tdb1_context *, enum tdb_log_level, enum TDB_ERROR,
+                             const char *, void *);
 typedef unsigned int (*tdb1_hash_func)(TDB1_DATA *key);
 
 struct tdb1_logging_context {
@@ -138,8 +117,6 @@ int tdb1_lockall_read(struct tdb1_context *tdb);
 
 int tdb1_unlockall_read(struct tdb1_context *tdb);
 
-tdb1_log_func tdb1_log_fn(struct tdb1_context *tdb);
-
 int tdb1_transaction_start(struct tdb1_context *tdb);
 
 int tdb1_transaction_prepare_commit(struct tdb1_context *tdb);
index 306cd7e05f811d55ad03e854c2ff7a3c050952ad..f0eb32bdef1baccbaf39fa15b69a588c3fd962c3 100644 (file)
@@ -61,8 +61,8 @@ static bool tdb1_check_header(struct tdb1_context *tdb, tdb1_off_t *recovery)
        return true;
 
 corrupt:
-       tdb->ecode = TDB1_ERR_CORRUPT;
-       TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "Header is corrupt\n"));
+       tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                               "Header is corrupt\n");
        return false;
 }
 
@@ -75,21 +75,21 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
 
        /* Check rec->next: 0 or points to record offset, aligned. */
        if (rec->next > 0 && rec->next < TDB1_DATA_START(tdb->header.hash_size)){
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d too small next %d\n",
-                        off, rec->next));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d too small next %d\n",
+                          off, rec->next);
                goto corrupt;
        }
        if (rec->next + sizeof(*rec) < rec->next) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d too large next %d\n",
-                        off, rec->next));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d too large next %d\n",
+                          off, rec->next);
                goto corrupt;
        }
        if ((rec->next % TDB1_ALIGNMENT) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d misaligned next %d\n",
-                        off, rec->next));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d misaligned next %d\n",
+                          off, rec->next);
                goto corrupt;
        }
        if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0))
@@ -97,16 +97,16 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
 
        /* Check rec_len: similar to rec->next, implies next record. */
        if ((rec->rec_len % TDB1_ALIGNMENT) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d misaligned length %d\n",
-                        off, rec->rec_len));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d misaligned length %d\n",
+                          off, rec->rec_len);
                goto corrupt;
        }
        /* Must fit tailer. */
        if (rec->rec_len < sizeof(tailer)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d too short length %d\n",
-                        off, rec->rec_len));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d too short length %d\n",
+                          off, rec->rec_len);
                goto corrupt;
        }
        /* OOB allows "right at the end" access, so this works for last rec. */
@@ -118,15 +118,15 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
                         &tailer) == -1)
                goto corrupt;
        if (tailer != sizeof(*rec) + rec->rec_len) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d invalid tailer\n", off));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "Record offset %d invalid tailer\n", off);
                goto corrupt;
        }
 
        return true;
 
 corrupt:
-       tdb->ecode = TDB1_ERR_CORRUPT;
+       tdb->last_error = TDB_ERR_CORRUPT;
        return false;
 }
 
@@ -246,8 +246,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb,
 
        /* key + data + tailer must fit in record */
        if (rec->key_len + rec->data_len + sizeof(tdb1_off_t) > rec->rec_len) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d too short for contents\n", off));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "Record offset %d too short for contents\n", off);
                return false;
        }
 
@@ -256,8 +256,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb,
                return false;
 
        if (tdb->hash_fn(&key) != rec->full_hash) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Record offset %d has incorrect hash\n", off));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "Record offset %d has incorrect hash\n", off);
                goto fail_put_key;
        }
 
@@ -353,8 +353,8 @@ int tdb1_check(struct tdb1_context *tdb,
 
        /* We should have the whole header, too. */
        if (tdb->map_size < TDB1_DATA_START(tdb->header.hash_size)) {
-               tdb->ecode = TDB1_ERR_CORRUPT;
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "File too short for hashes\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "File too short for hashes\n");
                goto unlock;
        }
 
@@ -363,7 +363,7 @@ int tdb1_check(struct tdb1_context *tdb,
                        1, sizeof(hashes[0]) * (1+tdb->header.hash_size)
                        + BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size));
        if (!hashes) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                goto unlock;
        }
 
@@ -410,26 +410,25 @@ int tdb1_check(struct tdb1_context *tdb,
                        if (dead < sizeof(rec))
                                goto corrupt;
 
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                                "Dead space at %d-%d (of %u)\n",
-                                off, off + dead, tdb->map_size));
+                       tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING,
+                                  "Dead space at %d-%d (of %u)\n",
+                                  off, off + dead, tdb->map_size);
                        rec.rec_len = dead - sizeof(rec);
                        break;
                case TDB1_RECOVERY_MAGIC:
                        if (recovery_start != off) {
-                               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                                        "Unexpected recovery record at offset %d\n",
-                                        off));
+                               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                                       "Unexpected recovery record at offset %d\n",
+                                                       off);
                                goto free;
                        }
                        found_recovery = true;
                        break;
                default: ;
                corrupt:
-                       tdb->ecode = TDB1_ERR_CORRUPT;
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                                "Bad magic 0x%x at offset %d\n",
-                                rec.magic, off));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                               "Bad magic 0x%x at offset %d\n",
+                                               rec.magic, off);
                        goto free;
                }
        }
@@ -440,9 +439,8 @@ int tdb1_check(struct tdb1_context *tdb,
                unsigned int i;
                for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) {
                        if (hashes[h][i] != 0) {
-                               tdb->ecode = TDB1_ERR_CORRUPT;
-                               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                                        "Hashes do not match records\n"));
+                               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                                       "Hashes do not match records\n");
                                goto free;
                        }
                }
@@ -450,9 +448,9 @@ int tdb1_check(struct tdb1_context *tdb,
 
        /* We must have found recovery area if there was one. */
        if (recovery_start != 0 && !found_recovery) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "Expected a recovery area at %u\n",
-                        recovery_start));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "Expected a recovery area at %u\n",
+                                       recovery_start);
                goto free;
        }
 
index ba93b5892cd3daa7b028c443ef4ff7a0f2ee9ff3..cf2eeb7febac18e790bb1e20726de77d986bc363 100644 (file)
@@ -36,18 +36,18 @@ int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off, struct tdb1_rec
        if (rec->magic == TDB1_MAGIC) {
                /* this happens when a app is showdown while deleting a record - we should
                   not completely fail when this happens */
-               TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
-                        rec->magic, off));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_WARNING,
+                          "tdb1_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
+                          rec->magic, off);
                rec->magic = TDB1_FREE_MAGIC;
                if (tdb->methods->tdb1_write(tdb, off, rec, sizeof(*rec)) == -1)
                        return -1;
        }
 
        if (rec->magic != TDB1_FREE_MAGIC) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB1_ERR_CORRUPT;
-               TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_rec_free_read bad magic 0x%x at offset=%d\n",
-                          rec->magic, off));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "tdb1_rec_free_read bad magic 0x%x at offset=%d\n",
+                                       rec->magic, off);
                return -1;
        }
        if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
@@ -78,7 +78,8 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
 
        /* set an initial tailer, so if we fail we don't leave a bogus record */
        if (update_tailer(tdb, offset, rec) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free: update_tailer failed!\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb_free: update_tailer failed!\n");
                goto fail;
        }
 
@@ -90,7 +91,8 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
 
                /* Read in tailer and jump back to header */
                if (tdb1_ofs_read(tdb, left, &leftsize) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free: left offset read failed at %u\n", left));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_free: left offset read failed at %u", left);
                        goto update;
                }
 
@@ -108,7 +110,8 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
 
                /* Now read in the left record */
                if (tdb->methods->tdb1_read(tdb, left, &l, sizeof(l), TDB1_DOCONV()) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free: left read failed at %u (%u)\n", left, leftsize));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_free: left read failed at %u (%u)", left, leftsize);
                        goto update;
                }
 
@@ -119,11 +122,13 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
                           prevents traverse from being O(n^2) after a lot of deletes */
                        l.rec_len += sizeof(*rec) + rec->rec_len;
                        if (tdb1_rec_write(tdb, left, &l) == -1) {
-                               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free: update_left failed at %u\n", left));
+                               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                          "tdb1_free: update_left failed at %u", left);
                                goto fail;
                        }
                        if (update_tailer(tdb, left, &l) == -1) {
-                               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free: update_tailer failed at %u\n", offset));
+                               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                          "tdb1_free: update_tailer failed at %u", offset);
                                goto fail;
                        }
                        tdb1_unlock(tdb, -1, F_WRLCK);
@@ -139,7 +144,9 @@ update:
        if (tdb1_ofs_read(tdb, TDB1_FREELIST_TOP, &rec->next) == -1 ||
            tdb1_rec_write(tdb, offset, rec) == -1 ||
            tdb1_ofs_write(tdb, TDB1_FREELIST_TOP, &offset) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_free record write failed at offset=%d\n", offset));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_free record write failed at offset=%d",
+                          offset);
                goto fail;
        }
 
index 212e94ae14488a6dec32c8f3fc8f9b36a688609a..cd6efc34b1b2f4141f799be12150654493ef5434 100644 (file)
@@ -43,32 +43,30 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
                return 0;
        if (tdb->flags & TDB1_INTERNAL) {
                if (!probe) {
-                       /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_oob len %d beyond internal malloc size %d\n",
-                                (int)len, (int)tdb->map_size));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_oob len %d beyond internal malloc size %d",
+                                               (int)len, (int)tdb->map_size);
                }
                return -1;
        }
 
        if (fstat(tdb->fd, &st) == -1) {
-               tdb->ecode = TDB1_ERR_IO;
+               tdb->last_error = TDB_ERR_IO;
                return -1;
        }
 
        if (st.st_size < (size_t)len) {
                if (!probe) {
-                       /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_oob len %d beyond eof at %d\n",
-                                (int)len, (int)st.st_size));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_oob len %d beyond eof at %d",
+                                               (int)len, (int)st.st_size);
                }
                return -1;
        }
 
        /* Unmap, update size, remap */
        if (tdb1_munmap(tdb) == -1) {
-               tdb->ecode = TDB1_ERR_IO;
+               tdb->last_error = TDB_ERR_IO;
                return -1;
        }
        tdb->map_size = st.st_size;
@@ -85,7 +83,7 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
        }
 
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_RDONLY;
+               tdb->last_error = TDB_ERR_RDONLY;
                return -1;
        }
 
@@ -97,26 +95,26 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
        } else {
                ssize_t written = pwrite(tdb->fd, buf, len, off);
                if ((written != (ssize_t)len) && (written != -1)) {
-                       /* try once more */
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_write: wrote only "
-                                "%d of %d bytes at %d, trying once more\n",
-                                (int)written, len, off));
+                       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
+                                  "tdb1_write: wrote only "
+                                  "%d of %d bytes at %d, trying once more",
+                                  (int)written, len, off);
                        written = pwrite(tdb->fd, (const char *)buf+written,
                                         len-written,
                                         off+written);
                }
                if (written == -1) {
                        /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_write failed at %d "
-                                "len=%d (%s)\n", off, len, strerror(errno)));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_write failed at %d "
+                                               "len=%d (%s)",
+                                               off, len, strerror(errno));
                        return -1;
                } else if (written != (ssize_t)len) {
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_write: failed to "
-                                "write %d bytes at %d in two attempts\n",
-                                len, off));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_write: failed to "
+                                               "write %d bytes at %d in two attempts",
+                                               len, off);
                        return -1;
                }
        }
@@ -147,11 +145,12 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
                ssize_t ret = pread(tdb->fd, buf, len, off);
                if (ret != (ssize_t)len) {
                        /* Ensure ecode is set for log fn. */
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_read failed at %d "
-                                "len=%d ret=%d (%s) map_size=%d\n",
-                                (int)off, (int)len, (int)ret, strerror(errno),
-                                (int)tdb->map_size));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_read failed at %d "
+                                               "len=%d ret=%d (%s) map_size=%d",
+                                               (int)off, (int)len, (int)ret,
+                                               strerror(errno),
+                                               (int)tdb->map_size);
                        return -1;
                }
        }
@@ -223,8 +222,9 @@ void tdb1_mmap(struct tdb1_context *tdb)
 
                if (tdb->map_ptr == MAP_FAILED) {
                        tdb->map_ptr = NULL;
-                       TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_mmap failed for size %d (%s)\n",
-                                tdb->map_size, strerror(errno)));
+                       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
+                                  "tdb1_mmap failed for size %d (%s)",
+                                  tdb->map_size, strerror(errno));
                }
        } else {
                tdb->map_ptr = NULL;
@@ -241,7 +241,7 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
        char buf[8192];
 
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_RDONLY;
+               tdb->last_error = TDB_ERR_RDONLY;
                return -1;
        }
 
@@ -257,8 +257,10 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
                        errno = ENOSPC;
                }
                if (written != 1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
-                                size+addition, strerror(errno)));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "expand_file to %d failed (%s)",
+                                               size+addition,
+                                               strerror(errno));
                        return -1;
                }
        }
@@ -276,19 +278,22 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
                }
                if (written == 0) {
                        /* give up, trying to provide a useful errno */
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file write "
-                               "returned 0 twice: giving up!\n"));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "expand_file write "
+                                               "returned 0 twice: giving up!");
                        errno = ENOSPC;
                        return -1;
                } else if (written == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file write of "
-                                "%d bytes failed (%s)\n", (int)n,
-                                strerror(errno)));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "expand_file write of "
+                                               "%d bytes failed (%s)", (int)n,
+                                               strerror(errno));
                        return -1;
                } else if (written != n) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "expand_file: wrote "
-                                "only %d of %d bytes - retrying\n", (int)written,
-                                (int)n));
+                       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
+                                  "expand_file: wrote "
+                                  "only %d of %d bytes - retrying",
+                                  (int)written, (int)n);
                }
                addition -= written;
                size += written;
@@ -305,7 +310,8 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
        tdb1_off_t offset, new_size, top_size, map_size;
 
        if (tdb1_lock(tdb, -1, F_WRLCK) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "lock failed in tdb1_expand\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "lock failed in tdb1_expand");
                return -1;
        }
 
@@ -406,10 +412,10 @@ unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1
        /* some systems don't like zero length malloc */
 
        if (!(buf = (unsigned char *)malloc(len ? len : 1))) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB1_ERR_OOM;
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,"tdb1_alloc_read malloc failed len=%d (%s)\n",
-                          len, strerror(errno)));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+                                            "tdb1_alloc_read malloc failed"
+                                            " len=%d (%s)",
+                                            len, strerror(errno));
                return NULL;
        }
        if (tdb->methods->tdb1_read(tdb, offset, buf, len, 0) == -1) {
@@ -459,9 +465,9 @@ int tdb1_rec_read(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_recor
        if (tdb->methods->tdb1_read(tdb, offset, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
                return -1;
        if (TDB1_BAD_MAGIC(rec)) {
-               /* Ensure ecode is set for log fn. */
-               tdb->ecode = TDB1_ERR_CORRUPT;
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "tdb1_rec_read bad magic 0x%x at offset=%d",
+                                       rec->magic, offset);
                return -1;
        }
        return tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0);
index a33c851c1721e0c92b10b834b33756bed2c602bc..68f394aad24c8b2ddeb1b4557e26fd1247d7b101 100644 (file)
@@ -139,7 +139,7 @@ int tdb1_brlock(struct tdb1_context *tdb,
        }
 
        if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
-               tdb->ecode = TDB1_ERR_RDONLY;
+               tdb->last_error = TDB_ERR_RDONLY;
                return -1;
        }
 
@@ -149,13 +149,14 @@ int tdb1_brlock(struct tdb1_context *tdb,
        } while (ret == -1 && errno == EINTR);
 
        if (ret == -1) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                /* Generic lock error. errno set by fcntl.
                 * EAGAIN is an expected return from non-blocking
                 * locks. */
                if (!(flags & TDB1_LOCK_PROBE) && errno != EAGAIN) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_TRACE,"tdb1_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
-                                tdb->fd, offset, rw_type, flags, (int)len));
+                       tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                  "tdb1_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d",
+                                  tdb->fd, offset, rw_type, flags, (int)len);
                }
                return -1;
        }
@@ -176,8 +177,10 @@ int tdb1_brunlock(struct tdb1_context *tdb,
        } while (ret == -1 && errno == EINTR);
 
        if (ret == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_TRACE,"tdb1_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
-                        tdb->fd, offset, rw_type, (int)len));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_brunlock failed (fd=%d) at offset"
+                                       " %d rw_type=%d len=%d",
+                                       tdb->fd, offset, rw_type, (int)len);
        }
        return ret;
 }
@@ -193,15 +196,17 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
        int count = 1000;
 
        if (tdb->allrecord_lock.count != 1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "tdb1_allrecord_upgrade failed: count %u too high\n",
-                        tdb->allrecord_lock.count));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_allrecord_upgrade failed: "
+                                       "count %u too high",
+                                       tdb->allrecord_lock.count);
                return -1;
        }
 
        if (tdb->allrecord_lock.off != 1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                        "tdb1_allrecord_upgrade failed: already upgraded?\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_allrecord_upgrade failed:"
+                                       " already upgraded?");
                return -1;
        }
 
@@ -221,7 +226,8 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
                tv.tv_usec = 1;
                select(0, NULL, NULL, NULL, &tv);
        }
-       TDB1_LOG((tdb, TDB1_DEBUG_TRACE,"tdb1_allrecord_upgrade failed\n"));
+       tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                               "tdb1_allrecord_upgrade failed");
        return -1;
 }
 
@@ -245,9 +251,10 @@ int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype,
        struct tdb1_lock_type *new_lck;
 
        if (offset >= lock_offset(tdb->header.hash_size)) {
-               tdb->ecode = TDB1_ERR_LOCK;
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR,"tdb1_lock: invalid offset %u for ltype=%d\n",
-                        offset, ltype));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_lock: invalid offset %u for"
+                                       " ltype=%d",
+                                       offset, ltype);
                return -1;
        }
        if (tdb->flags & TDB1_NOLOCK)
@@ -332,7 +339,7 @@ static int tdb1_lock_list(struct tdb1_context *tdb, int list, int ltype,
        }
 
        if (tdb->allrecord_lock.count) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                ret = -1;
        } else {
                /* Only check when we grab first data lock. */
@@ -358,8 +365,9 @@ int tdb1_lock(struct tdb1_context *tdb, int list, int ltype)
 
        ret = tdb1_lock_list(tdb, list, ltype, TDB1_LOCK_WAIT);
        if (ret) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_lock failed on list %d "
-                        "ltype=%d (%s)\n",  list, ltype, strerror(errno)));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_lock failed on list %d "
+                          "ltype=%d (%s)",  list, ltype, strerror(errno));
        }
        return ret;
 }
@@ -374,13 +382,16 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
 
        /* Sanity checks */
        if (offset >= lock_offset(tdb->header.hash_size)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_unlock: offset %u invalid (%d)\n", offset, tdb->header.hash_size));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_unlock: offset %u invalid (%d)",
+                                       offset, tdb->header.hash_size);
                return ret;
        }
 
        lck = tdb1_find_nestlock(tdb, offset);
        if ((lck == NULL) || (lck->count == 0)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_unlock: count is 0\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
+                                       "tdb1_unlock: count is 0");
                return -1;
        }
 
@@ -413,8 +424,6 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
                SAFE_FREE(tdb->lockrecs);
        }
 
-       if (ret)
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_unlock: An error occurred unlocking!\n"));
        return ret;
 }
 
@@ -427,7 +436,7 @@ int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype)
        }
 
        if (tdb->allrecord_lock.count) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
@@ -457,7 +466,7 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype,
 {
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
@@ -468,19 +477,19 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype,
 
        if (tdb->allrecord_lock.count) {
                /* a global lock of a different type exists */
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
        if (tdb1_have_extra_locks(tdb)) {
                /* can't combine global and chain locks */
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
        if (upgradable && ltype != F_RDLCK) {
                /* tdb error: you can't upgrade a write lock! */
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
        return 1;
@@ -577,19 +586,19 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
 {
        /* There are no locks on read-only dbs */
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
        if (tdb->allrecord_lock.count == 0) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
        /* Upgradable locks are marked as write locks. */
        if (tdb->allrecord_lock.ltype != ltype
            && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) {
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = TDB_ERR_LOCK;
                return -1;
        }
 
@@ -599,7 +608,8 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
        }
 
        if (tdb1_brunlock(tdb, ltype, TDB1_FREELIST_TOP, 0)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_unlockall failed (%s)\n", strerror(errno)));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_unlockall failed (%s)", strerror(errno));
                return -1;
        }
 
index aed4df65585bf8c45f353f1ccbfbda6bb29943aa..e1f16053666537eb91ba8501ab7c151fe8d35994 100644 (file)
@@ -60,7 +60,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
        /* We make it up in memory, then write it out if not internal */
        size = sizeof(struct tdb1_header) + (hash_size+1)*sizeof(tdb1_off_t);
        if (!(newdb = (struct tdb1_header *)calloc(size, 1))) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                return -1;
        }
 
@@ -135,12 +135,6 @@ struct tdb1_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
        return tdb1_open_ex(name, hash_size, tdb1_flags, open_flags, mode, NULL, NULL);
 }
 
-/* a default logging function */
-static void null_log_fn(struct tdb1_context *tdb, enum tdb1_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
-static void null_log_fn(struct tdb1_context *tdb, enum tdb1_debug_level level, const char *fmt, ...)
-{
-}
-
 static bool check_header_hash(struct tdb1_context *tdb,
                              bool default_hash, uint32_t *m1, uint32_t *m2)
 {
@@ -188,11 +182,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        tdb->flags = tdb1_flags;
        tdb->open_flags = open_flags;
        if (log_ctx) {
-               tdb->log = *log_ctx;
-       } else {
-               tdb->log.log_fn = null_log_fn;
-               tdb->log.log_private = NULL;
-       }
+               tdb->log_fn = log_ctx->log_fn;
+               tdb->log_data = log_ctx->log_private;
+       } else
+               tdb->log_fn = NULL;
 
        if (name == NULL && (tdb1_flags & TDB1_INTERNAL)) {
                name = "__TDB1_INTERNAL__";
@@ -200,7 +193,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        if (name == NULL) {
                tdb->name = (char *)"__NULL__";
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: called with name == NULL\n"));
+               tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                          "tdb1_open_ex: called with name == NULL");
                tdb->name = NULL;
                errno = EINVAL;
                goto fail;
@@ -213,8 +207,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
                 * work in case of an error.
                 */
                tdb->name = (char *)name;
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: can't strdup(%s)\n",
-                        name));
+               tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+                          "tdb1_open_ex: can't strdup(%s)", name);
                tdb->name = NULL;
                errno = ENOMEM;
                goto fail;
@@ -242,8 +236,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        tdb->max_dead_records = (tdb1_flags & TDB1_VOLATILE) ? 5 : 0;
 
        if ((open_flags & O_ACCMODE) == O_WRONLY) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: can't open tdb %s write-only\n",
-                        name));
+               tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                          "tdb1_open_ex: can't open tdb %s write-only",
+                          name);
                errno = EINVAL;
                goto fail;
        }
@@ -259,9 +254,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        if ((tdb->flags & TDB1_ALLOW_NESTING) &&
            (tdb->flags & TDB1_DISALLOW_NESTING)) {
-               tdb->ecode = TDB1_ERR_NESTING;
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: "
-                       "allow_nesting and disallow_nesting are not allowed together!"));
+               tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                          "tdb1_open_ex: "
+                          "allow_nesting and disallow_nesting are not allowed together!");
                errno = EINVAL;
                goto fail;
        }
@@ -279,15 +274,17 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
                tdb->flags |= (TDB1_NOLOCK | TDB1_NOMMAP);
                tdb->flags &= ~TDB1_CLEAR_IF_FIRST;
                if (tdb1_new_database(tdb, hash_size) != 0) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: tdb1_new_database failed!"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_open_ex: tdb1_new_database failed!");
                        goto fail;
                }
                goto internal;
        }
 
        if ((tdb->fd = open(name, open_flags, mode)) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_open_ex: could not open file %s: %s\n",
-                        name, strerror(errno)));
+               tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                          "tdb1_open_ex: could not open file %s: %s",
+                          name, strerror(errno));
                goto fail;      /* errno set by open(2) */
        }
 
@@ -297,8 +294,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        /* ensure there is only one process initialising at once */
        if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB1_LOCK_WAIT) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: failed to get open lock on %s: %s\n",
-                        name, strerror(errno)));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_open_ex: failed to get open lock on %s: %s",
+                          name, strerror(errno));
                goto fail;      /* errno set by tdb1_brlock */
        }
 
@@ -308,9 +306,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
            (locked = (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK, TDB1_LOCK_NOWAIT|TDB1_LOCK_PROBE) == 0))) {
                open_flags |= O_CREAT;
                if (ftruncate(tdb->fd, 0) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: "
-                                "failed to truncate %s: %s\n",
-                                name, strerror(errno)));
+                       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                  "tdb1_open_ex: "
+                                  "failed to truncate %s: %s",
+                                  name, strerror(errno));
                        goto fail; /* errno set by ftruncate */
                }
        }
@@ -346,7 +345,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
 
        if (tdb->header.rwlocks != 0 &&
            tdb->header.rwlocks != TDB1_HASH_RWLOCK_MAGIC) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: spinlocks no longer supported\n"));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                          "tdb1_open_ex: spinlocks no longer supported");
                goto fail;
        }
 
@@ -354,26 +354,28 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
                /* older TDB without magic hash references */
                tdb->hash_fn = tdb1_old_hash;
        } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: "
-                        "%s was not created with %s hash function we are using\n"
-                        "magic1_hash[0x%08X %s 0x%08X] "
-                        "magic2_hash[0x%08X %s 0x%08X]\n",
-                        name, hash_alg,
-                        tdb->header.magic1_hash,
-                        (tdb->header.magic1_hash == magic1) ? "==" : "!=",
-                        magic1,
-                        tdb->header.magic2_hash,
-                        (tdb->header.magic2_hash == magic2) ? "==" : "!=",
-                        magic2));
+               tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_USE_ERROR,
+                          "tdb1_open_ex: "
+                          "%s was not created with %s hash function we are using\n"
+                          "magic1_hash[0x%08X %s 0x%08X] "
+                          "magic2_hash[0x%08X %s 0x%08X]",
+                          name, hash_alg,
+                          tdb->header.magic1_hash,
+                          (tdb->header.magic1_hash == magic1) ? "==" : "!=",
+                          magic1,
+                          tdb->header.magic2_hash,
+                          (tdb->header.magic2_hash == magic2) ? "==" : "!=",
+                          magic2);
                errno = EINVAL;
                goto fail;
        }
 
        /* Is it already in the open list?  If so, fail. */
        if (tdb1_already_open(st.st_dev, st.st_ino)) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: "
-                        "%s (%d,%d) is already open in this process\n",
-                        name, (int)st.st_dev, (int)st.st_ino));
+               tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_USE_ERROR,
+                          "tdb1_open_ex: "
+                          "%s (%d,%d) is already open in this process",
+                          name, (int)st.st_dev, (int)st.st_ino);
                errno = EBUSY;
                goto fail;
        }
@@ -384,9 +386,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        tdb1_mmap(tdb);
        if (locked) {
                if (tdb1_nest_unlock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: "
-                                "failed to release ACTIVE_LOCK on %s: %s\n",
-                                name, strerror(errno)));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_open_ex: "
+                                  "failed to release ACTIVE_LOCK on %s: %s",
+                                  name, strerror(errno));
                        goto fail;
                }
 
@@ -433,7 +436,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
        }
        if (tdb->fd != -1)
                if (close(tdb->fd) != 0)
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: failed to close tdb->fd on error!\n"));
+                       tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                  "tdb1_open_ex: failed to close tdb->fd on error!");
        SAFE_FREE(tdb->lockrecs);
        SAFE_FREE(tdb->name);
        SAFE_FREE(tdb);
index 7ce192b9a6d0cbd30fda6ee5e2688dfd0d5725b1..932e76110bbfb61747e47b27d65c2e4e73ec36fc 100644 (file)
 #include "private.h"
 #include "tdb1.h"
 
-#include <limits.h>
+/**** FIXME: Type overrides for tdb2, for transition! */
+#define tdb_logerr(tdb, ecode, level, ...) \
+       tdb_logerr((struct tdb_context *)(tdb), (ecode), (level), __VA_ARGS__)
+
+#define tdb_error(tdb) \
+       tdb_error((struct tdb_context *)(tdb))
 
-/* Temporary wrapper to avoid undue churn in test/ */
-#define tdb1_error(tdb) ((tdb)->ecode)
+/***** END FIXME ***/
+
+#include <limits.h>
 
 /* #define TDB_TRACE 1 */
 #ifndef HAVE_GETPAGESIZE
@@ -80,11 +86,6 @@ typedef uint32_t tdb1_off_t;
 #define TDB1_PAD_BYTE 0x42
 #define TDB1_PAD_U32  0x42424242
 
-/* NB assumes there is a local variable called "tdb" that is the
- * current context, also takes doubly-parenthesized print-style
- * argument. */
-#define TDB1_LOG(x) tdb->log.log_fn x
-
 /* lock offsets */
 #define TDB1_OPEN_LOCK        0
 #define TDB1_ACTIVE_LOCK      4
@@ -167,7 +168,21 @@ struct tdb1_methods {
 };
 
 struct tdb1_context {
+       struct tdb1_context *next;
+
        char *name; /* the name of the database */
+
+       /* Logging function */
+       void (*log_fn)(struct tdb1_context *tdb,
+                      enum tdb_log_level level,
+                      enum TDB_ERROR ecode,
+                      const char *message,
+                      void *data);
+       void *log_data;
+
+       /* Last error we returned. */
+       enum TDB_ERROR last_error; /* error code for last tdb error */
+
        void *map_ptr; /* where it is currently mapped */
        int fd; /* open file descriptor for the database */
        tdb1_len_t map_size; /* how much space has been mapped */
@@ -177,14 +192,11 @@ struct tdb1_context {
        struct tdb1_lock_type allrecord_lock; /* .offset == upgradable */
        int num_lockrecs;
        struct tdb1_lock_type *lockrecs; /* only real locks, all with count>0 */
-       enum TDB1_ERROR ecode; /* error code for last tdb error */
        struct tdb1_header header; /* a cached copy of the header */
        uint32_t flags; /* the flags passed to tdb1_open */
        struct tdb1_traverse_lock travlocks; /* current traversal locks */
-       struct tdb1_context *next; /* all tdbs to avoid multiple opens */
        dev_t device;   /* uniquely identifies this tdb */
        ino_t inode;    /* uniquely identifies this tdb */
-       struct tdb1_logging_context log;
        unsigned int (*hash_fn)(TDB1_DATA *key);
        int open_flags; /* flags used in the open - needed by reopen */
        const struct tdb1_methods *methods;
index a2d2ae8f2fdbb31884e1dc08750d85680855335a..b6889bc4440fdff56088c2cd4025d56a2da17819 100644 (file)
@@ -150,9 +150,11 @@ char *tdb1_summary(struct tdb1_context *tdb)
                        tally1_add(&dead, rec.rec_len);
                        break;
                default:
-                       TDB1_LOG((tdb, TDB1_DEBUG_ERROR,
-                                "Unexpected record magic 0x%x at offset %d\n",
-                                rec.magic, off));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
+                                               TDB_LOG_ERROR,
+                                               "Unexpected record magic 0x%x"
+                                               " at offset %d",
+                                               rec.magic, off);
                        goto unlock;
                }
        }
index 113ebc0b6d122d42521a6ea84102651e7d6d448f..802311504508cca01c040cadc00849983897ba30 100644 (file)
@@ -99,13 +99,14 @@ static tdb1_off_t tdb1_find(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha
                }
                /* detect tight infinite loop */
                if (rec_ptr == r->next) {
-                       tdb->ecode = TDB1_ERR_CORRUPT;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_find: loop detected.\n"));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
+                                               TDB_LOG_ERROR,
+                                               "tdb1_find: loop detected.");
                        return 0;
                }
                rec_ptr = r->next;
        }
-       tdb->ecode = TDB1_ERR_NOEXIST;
+       tdb->last_error = TDB_ERR_NOEXIST;
        return 0;
 }
 
@@ -157,7 +158,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha
 
        /* must be long enough key, data and tailer */
        if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb1_off_t)) {
-               tdb->ecode = TDB1_SUCCESS; /* Not really an error */
+               tdb->last_error = TDB_SUCCESS; /* Not really an error */
                return -1;
        }
 
@@ -176,7 +177,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha
 
 /* find an entry in the database given a key */
 /* If an entry doesn't exist tdb1_err will be set to
- * TDB1_ERR_NOEXIST. If a key has no data attached
+ * TDB_ERR_NOEXIST. If a key has no data attached
  * then the TDB1_DATA will have zero length but
  * a non-zero pointer
  */
@@ -239,7 +240,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB1_DATA key,
 
        if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
                /* record not found */
-               tdb->ecode = TDB1_ERR_NOEXIST;
+               tdb->last_error = TDB_ERR_NOEXIST;
                return -1;
        }
 
@@ -421,7 +422,8 @@ static int tdb1_delete_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha
        }
 
        if (tdb1_unlock(tdb, TDB1_BUCKET(rec.full_hash), F_WRLCK) != 0)
-               TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_delete: WARNING tdb1_unlock failed!\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_delete: WARNING tdb1_unlock failed!");
        return ret;
 }
 
@@ -474,7 +476,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
        /* check for it existing, on insert. */
        if (flag == TDB1_INSERT) {
                if (tdb1_exists_hash(tdb, key, hash)) {
-                       tdb->ecode = TDB1_ERR_EXISTS;
+                       tdb->last_error = TDB_ERR_EXISTS;
                        goto fail;
                }
        } else {
@@ -482,7 +484,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
                if (tdb1_update_hash(tdb, key, hash, dbuf) == 0) {
                        goto done;
                }
-               if (tdb->ecode == TDB1_ERR_NOEXIST &&
+               if (tdb->last_error == TDB_ERR_NOEXIST &&
                    flag == TDB1_MODIFY) {
                        /* if the record doesn't exist and we are in TDB1_MODIFY mode then
                         we should fail the store */
@@ -490,7 +492,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
                }
        }
        /* reset the error code potentially set by the tdb1_update() */
-       tdb->ecode = TDB1_SUCCESS;
+       tdb->last_error = TDB_SUCCESS;
 
        /* delete any existing record - if it doesn't exist we don't
            care.  Doing this first reduces fragmentation, and avoids
@@ -502,7 +504,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
           fails and we are left with a dead spot in the tdb. */
 
        if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                goto fail;
        }
 
@@ -600,7 +602,7 @@ int tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA dbuf, int flag
        int ret;
 
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_RDONLY;
+               tdb->last_error = TDB_ERR_RDONLY;
                return -1;
        }
 
@@ -645,7 +647,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA new_dbuf)
        }
 
        if (dbuf.dptr == NULL) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                goto failed;
        }
 
@@ -661,16 +663,6 @@ failed:
 }
 
 
-/*
-  return the current logging function
-  useful for external tdb routines that wish to log tdb errors
-*/
-tdb1_log_func tdb1_log_fn(struct tdb1_context *tdb)
-{
-       return tdb->log.log_fn;
-}
-
-
 /*
   get the tdb sequence number. Only makes sense if the writers opened
   with TDB1_SEQNUM set. Note that this sequence number will wrap quite
@@ -707,13 +699,16 @@ static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t
                return 0;
        }
        if (length + offset > tdb->map_size) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_free_region: adding region beyond end of file\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "tdb1_free_region: adding region beyond"
+                                       " end of file");
                return -1;
        }
        memset(&rec,'\0',sizeof(rec));
        rec.rec_len = length - sizeof(rec);
        if (tdb1_free(tdb, offset, &rec) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_free_region: failed to add free record\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_free_region: failed to add free record");
                return -1;
        }
        return 0;
@@ -744,14 +739,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
           tdb1_wipe_all() in a transaction will increase the size of
           the tdb by the size of the recovery area */
        if (tdb1_ofs_read(tdb, TDB1_RECOVERY_HEAD, &recovery_head) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_wipe_all: failed to read recovery head\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_wipe_all: failed to read recovery head");
                goto failed;
        }
 
        if (recovery_head != 0) {
                struct tdb1_record rec;
                if (tdb->methods->tdb1_read(tdb, recovery_head, &rec, sizeof(rec), TDB1_DOCONV()) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_wipe_all: failed to read recovery record\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_wipe_all: failed to read recovery record");
                        return -1;
                }
                recovery_size = rec.rec_len + sizeof(rec);
@@ -760,14 +757,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
        /* wipe the hashes */
        for (i=0;i<tdb->header.hash_size;i++) {
                if (tdb1_ofs_write(tdb, TDB1_HASH_TOP(i), &offset) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_wipe_all: failed to write hash %d\n", i));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_wipe_all: failed to write hash %d", i);
                        goto failed;
                }
        }
 
        /* wipe the freelist */
        if (tdb1_ofs_write(tdb, TDB1_FREELIST_TOP, &offset) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_wipe_all: failed to write freelist\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_wipe_all: failed to write freelist");
                goto failed;
        }
 
@@ -800,7 +799,8 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
        }
 
        if (tdb1_unlockall(tdb) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_wipe_all: failed to unlock\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_wipe_all: failed to unlock");
                goto failed;
        }
 
@@ -812,7 +812,7 @@ failed:
 }
 
 struct traverse_state {
-       bool error;
+       enum TDB_ERROR error;
        struct tdb1_context *dest_db;
 };
 
@@ -823,7 +823,7 @@ static int repack_traverse(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA da
 {
        struct traverse_state *state = (struct traverse_state *)private_data;
        if (tdb1_store(state->dest_db, key, data, TDB1_INSERT) != 0) {
-               state->error = true;
+               state->error = state->dest_db->last_error;
                return -1;
        }
        return 0;
@@ -838,53 +838,60 @@ int tdb1_repack(struct tdb1_context *tdb)
        struct traverse_state state;
 
        if (tdb1_transaction_start(tdb) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to start transaction\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          __location__ " Failed to start transaction");
                return -1;
        }
 
        tmp_db = tdb1_open("tmpdb", tdb1_hash_size(tdb), TDB1_INTERNAL, O_RDWR|O_CREAT, 0);
        if (tmp_db == NULL) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to create tmp_db\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+                                       __location__ " Failed to create tmp_db");
                tdb1_transaction_cancel(tdb);
                return -1;
        }
 
-       state.error = false;
+       state.error = TDB_SUCCESS;
        state.dest_db = tmp_db;
 
        if (tdb1_traverse_read(tdb, repack_traverse, &state) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to traverse copying out\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          __location__ " Failed to traverse copying out");
                tdb1_transaction_cancel(tdb);
                tdb1_close(tmp_db);
                return -1;
        }
 
-       if (state.error) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Error during traversal\n"));
+       if (state.error != TDB_SUCCESS) {
+               tdb->last_error = tdb_logerr(tdb, state.error, TDB_LOG_ERROR,
+                                       __location__ " Error during traversal");
                tdb1_transaction_cancel(tdb);
                tdb1_close(tmp_db);
                return -1;
        }
 
        if (tdb1_wipe_all(tdb) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to wipe database\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          __location__ " Failed to wipe database\n");
                tdb1_transaction_cancel(tdb);
                tdb1_close(tmp_db);
                return -1;
        }
 
-       state.error = false;
+       state.error = TDB_SUCCESS;
        state.dest_db = tdb;
 
        if (tdb1_traverse_read(tmp_db, repack_traverse, &state) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to traverse copying back\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          __location__ " Failed to traverse copying back");
                tdb1_transaction_cancel(tdb);
                tdb1_close(tmp_db);
                return -1;
        }
 
        if (state.error) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Error during second traversal\n"));
+               tdb->last_error = tdb_logerr(tdb, state.error, TDB_LOG_ERROR,
+                                       __location__ " Error during second traversal");
                tdb1_transaction_cancel(tdb);
                tdb1_close(tmp_db);
                return -1;
@@ -893,7 +900,8 @@ int tdb1_repack(struct tdb1_context *tdb)
        tdb1_close(tmp_db);
 
        if (tdb1_transaction_commit(tdb) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Failed to commit\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          __location__ " Failed to commit");
                return -1;
        }
 
index b09a2b3c10c157c5afbba0fb2c3d2a0f4b22abba..165fd7f972f5b74dd0d1de0271c97ec9e502ebbe 100644 (file)
@@ -97,7 +97,7 @@
   - if TDB1_DISALLOW_NESTING is passed to flags in tdb open, or added using
     tdb1_add_flags() transaction nesting is disabled.
     It resets the TDB1_ALLOW_NESTING flag, as both cannot be used together.
-    An attempt create a nested transaction will fail with TDB1_ERR_NESTING.
+    An attempt create a nested transaction will fail with TDB_ERR_EINVAL.
     The default is that transaction nesting is allowed.
     Note: this default may change in future versions of tdb.
 */
@@ -194,8 +194,9 @@ static int transaction1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf
        return 0;
 
 fail:
-       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len));
-       tdb->ecode = TDB1_ERR_IO;
+       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                               "transaction_read: failed at off=%d len=%d",
+                               off, len);
        tdb->transaction->transaction_error = 1;
        return -1;
 }
@@ -211,8 +212,9 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
 
        /* Only a commit is allowed on a prepared transaction */
        if (tdb->transaction->prepared) {
-               tdb->ecode = TDB1_ERR_EINVAL;
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "transaction_write: transaction already prepared, write not allowed\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "transaction_write: transaction already"
+                                       " prepared, write not allowed");
                tdb->transaction->transaction_error = 1;
                return -1;
        }
@@ -257,7 +259,7 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
                                (blk+1)*sizeof(uint8_t *));
                }
                if (new_blocks == NULL) {
-                       tdb->ecode = TDB1_ERR_OOM;
+                       tdb->last_error = TDB_ERR_OOM;
                        goto fail;
                }
                memset(&new_blocks[tdb->transaction->num_blocks], 0,
@@ -271,7 +273,7 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
        if (tdb->transaction->blocks[blk] == NULL) {
                tdb->transaction->blocks[blk] = (uint8_t *)calloc(tdb->transaction->block_size, 1);
                if (tdb->transaction->blocks[blk] == NULL) {
-                       tdb->ecode = TDB1_ERR_OOM;
+                       tdb->last_error = TDB_ERR_OOM;
                        tdb->transaction->transaction_error = 1;
                        return -1;
                }
@@ -284,7 +286,7 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
                                                                   tdb->transaction->blocks[blk],
                                                                   len2, 0) != 0) {
                                SAFE_FREE(tdb->transaction->blocks[blk]);
-                               tdb->ecode = TDB1_ERR_IO;
+                               tdb->last_error = TDB_ERR_IO;
                                goto fail;
                        }
                        if (blk == tdb->transaction->num_blocks-1) {
@@ -308,8 +310,9 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
        return 0;
 
 fail:
-       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n",
-                (blk*tdb->transaction->block_size) + off, len));
+       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                  "transaction_write: failed at off=%d len=%d",
+                  (blk*tdb->transaction->block_size) + off, len);
        tdb->transaction->transaction_error = 1;
        return -1;
 }
@@ -387,7 +390,7 @@ static int transaction1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
        if (len <= tdb->map_size) {
                return 0;
        }
-       tdb->ecode = TDB1_ERR_IO;
+       tdb->last_error = TDB_ERR_IO;
        return -1;
 }
 
@@ -425,20 +428,20 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
 {
        /* some sanity checks */
        if (tdb->read_only || (tdb->flags & TDB1_INTERNAL) || tdb->traverse_read) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_start: cannot start a transaction on a read-only or internal db\n"));
-               tdb->ecode = TDB1_ERR_EINVAL;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_start: cannot start a"
+                                       " transaction on a read-only or"
+                                       " internal db");
                return -1;
        }
 
        /* cope with nested tdb1_transaction_start() calls */
        if (tdb->transaction != NULL) {
                if (!(tdb->flags & TDB1_ALLOW_NESTING)) {
-                       tdb->ecode = TDB1_ERR_NESTING;
+                       tdb->last_error = TDB_ERR_EINVAL;
                        return -1;
                }
                tdb->transaction->nesting++;
-               TDB1_LOG((tdb, TDB1_DEBUG_TRACE, "tdb1_transaction_start: nesting %d\n",
-                        tdb->transaction->nesting));
                return 0;
        }
 
@@ -446,8 +449,9 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
                /* the caller must not have any locks when starting a
                   transaction as otherwise we'll be screwed by lack
                   of nested locks in posix */
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_start: cannot start a transaction with locks held\n"));
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_start: cannot start a"
+                                       " transaction with locks held");
                return -1;
        }
 
@@ -455,15 +459,16 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
                /* you cannot use transactions inside a traverse (although you can use
                   traverse inside a transaction) as otherwise you can end up with
                   deadlock */
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_start: cannot start a transaction within a traverse\n"));
-               tdb->ecode = TDB1_ERR_LOCK;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_start: cannot start a"
+                                       " transaction within a traverse");
                return -1;
        }
 
        tdb->transaction = (struct tdb1_transaction *)
                calloc(sizeof(struct tdb1_transaction), 1);
        if (tdb->transaction == NULL) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                return -1;
        }
 
@@ -482,7 +487,8 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
        /* get a read lock from the freelist to the end of file. This
           is upgraded to a write lock during the commit */
        if (tdb1_allrecord_lock(tdb, F_RDLCK, TDB1_LOCK_WAIT, true) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_start: failed to get hash locks\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_start: failed to get hash locks");
                goto fail_allrecord_lock;
        }
 
@@ -491,13 +497,13 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
        tdb->transaction->hash_heads = (uint32_t *)
                calloc(tdb->header.hash_size+1, sizeof(uint32_t));
        if (tdb->transaction->hash_heads == NULL) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                goto fail;
        }
        if (tdb->methods->tdb1_read(tdb, TDB1_FREELIST_TOP, tdb->transaction->hash_heads,
                                   TDB1_HASHTABLE_SIZE(tdb), 0) != 0) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_start: failed to read hash heads\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_start: failed to read hash heads");
                goto fail;
        }
 
@@ -542,8 +548,8 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l
 #else
        if (fsync(tdb->fd) != 0) {
 #endif
-               tdb->ecode = TDB1_ERR_IO;
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction: fsync failed\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                       "tdb1_transaction: fsync failed");
                return -1;
        }
 #if HAVE_MMAP
@@ -551,9 +557,10 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l
                tdb1_off_t moffset = offset & ~(tdb->page_size-1);
                if (msync(moffset + (char *)tdb->map_ptr,
                          length + (offset - moffset), MS_SYNC) != 0) {
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction: msync failed - %s\n",
-                                strerror(errno)));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "tdb1_transaction:"
+                                               " msync failed - %s",
+                                               strerror(errno));
                        return -1;
                }
        }
@@ -567,7 +574,9 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
        int i, ret = 0;
 
        if (tdb->transaction == NULL) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_cancel: no transaction\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_cancel:"
+                                       " no transaction");
                return -1;
        }
 
@@ -594,7 +603,9 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
                /* remove the recovery marker */
                if (methods->tdb1_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 ||
                transaction1_sync(tdb, tdb->transaction->magic_offset, 4) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_cancel: failed to remove recovery magic\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_cancel: failed to"
+                                  " remove recovery magic");
                        ret = -1;
                }
        }
@@ -688,7 +699,9 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
        tdb1_off_t recovery_head;
 
        if (tdb1_recovery_area(tdb, methods, &recovery_head, &rec) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_recovery_allocate: failed to read recovery head\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_recovery_allocate:"
+                          " failed to read recovery head");
                return -1;
        }
 
@@ -708,7 +721,9 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
           the transaction) */
        if (recovery_head != 0) {
                if (tdb1_free(tdb, recovery_head, &rec) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_recovery_allocate: failed to free previous recovery area\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_recovery_allocate: failed to free"
+                                  " previous recovery area");
                        return -1;
                }
        }
@@ -724,7 +739,9 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
        if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
                                     (tdb->map_size - tdb->transaction->old_map_size) +
                                     sizeof(rec) + *recovery_max_size) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_recovery_allocate: failed to create recovery area\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_recovery_allocate:"
+                          " failed to create recovery area");
                return -1;
        }
 
@@ -740,11 +757,15 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
        TDB1_CONV(recovery_head);
        if (methods->tdb1_write(tdb, TDB1_RECOVERY_HEAD,
                               &recovery_head, sizeof(tdb1_off_t)) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_recovery_allocate: failed to write recovery head\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_recovery_allocate:"
+                          " failed to write recovery head");
                return -1;
        }
        if (transaction1_write_existing(tdb, TDB1_RECOVERY_HEAD, &recovery_head, sizeof(tdb1_off_t)) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_recovery_allocate: failed to write recovery head\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_recovery_allocate:"
+                          " failed to write recovery head");
                return -1;
        }
 
@@ -777,7 +798,7 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
 
        data = (unsigned char *)malloc(recovery_size + sizeof(*rec));
        if (data == NULL) {
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = TDB_ERR_OOM;
                return -1;
        }
 
@@ -811,9 +832,10 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
                        continue;
                }
                if (offset + length > tdb->transaction->old_map_size) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_setup_recovery: transaction data over new region boundary\n"));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
+                                               TDB_LOG_ERROR,
+                                               "tdb1_transaction_setup_recovery: transaction data over new region boundary");
                        free(data);
-                       tdb->ecode = TDB1_ERR_CORRUPT;
                        return -1;
                }
                memcpy(p, &offset, 4);
@@ -826,7 +848,7 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
                   method to get it */
                if (methods->tdb1_read(tdb, offset, p + 8, length, 0) != 0) {
                        free(data);
-                       tdb->ecode = TDB1_ERR_IO;
+                       tdb->last_error = TDB_ERR_IO;
                        return -1;
                }
                p += 8 + length;
@@ -841,15 +863,17 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
 
        /* write the recovery data to the recovery area */
        if (methods->tdb1_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_setup_recovery: failed to write recovery data\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_setup_recovery:"
+                          " failed to write recovery data");
                free(data);
-               tdb->ecode = TDB1_ERR_IO;
                return -1;
        }
        if (transaction1_write_existing(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_setup_recovery: failed to write secondary recovery data\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_setup_recovery: failed to write"
+                          " secondary recovery data");
                free(data);
-               tdb->ecode = TDB1_ERR_IO;
                return -1;
        }
 
@@ -869,13 +893,15 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
        *magic_offset = recovery_offset + offsetof(struct tdb1_record, magic);
 
        if (methods->tdb1_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_setup_recovery: failed to write recovery magic\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_setup_recovery:"
+                          " failed to write recovery magic");
                return -1;
        }
        if (transaction1_write_existing(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_setup_recovery: failed to write secondary recovery magic\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_setup_recovery:"
+                          " failed to write secondary recovery magic");
                return -1;
        }
 
@@ -892,21 +918,25 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
        const struct tdb1_methods *methods;
 
        if (tdb->transaction == NULL) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: no transaction\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_prepare_commit:"
+                                       " no transaction");
                return -1;
        }
 
        if (tdb->transaction->prepared) {
-               tdb->ecode = TDB1_ERR_EINVAL;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_prepare_commit:"
+                                       " transaction already prepared");
                _tdb1_transaction_cancel(tdb);
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: transaction already prepared\n"));
                return -1;
        }
 
        if (tdb->transaction->transaction_error) {
-               tdb->ecode = TDB1_ERR_IO;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                       "tdb1_transaction_prepare_commit:"
+                                       " transaction error pending");
                _tdb1_transaction_cancel(tdb);
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: transaction error pending\n"));
                return -1;
        }
 
@@ -925,15 +955,18 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
        /* if there are any locks pending then the caller has not
           nested their locks properly, so fail the transaction */
        if (tdb1_have_extra_locks(tdb)) {
-               tdb->ecode = TDB1_ERR_LOCK;
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: locks pending on commit\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_prepare_commit:"
+                                       " locks pending on commit");
                _tdb1_transaction_cancel(tdb);
                return -1;
        }
 
        /* upgrade the main transaction lock region to a write lock */
        if (tdb1_allrecord_upgrade(tdb) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: failed to upgrade hash locks\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_prepare_commit:"
+                          " failed to upgrade hash locks");
                _tdb1_transaction_cancel(tdb);
                return -1;
        }
@@ -941,7 +974,9 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
        /* get the open lock - this prevents new users attaching to the database
           during the commit */
        if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB1_LOCK_WAIT) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_prepare_commit: failed to get open lock\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_prepare_commit:"
+                          " failed to get open lock");
                _tdb1_transaction_cancel(tdb);
                return -1;
        }
@@ -949,7 +984,9 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
        if (!(tdb->flags & TDB1_NOSYNC)) {
                /* write the recovery data to the end of the file */
                if (transaction1_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_prepare_commit: failed to setup recovery data\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_prepare_commit:"
+                                  " failed to setup recovery data");
                        _tdb1_transaction_cancel(tdb);
                        return -1;
                }
@@ -962,8 +999,9 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
                if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
                                             tdb->map_size -
                                             tdb->transaction->old_map_size) == -1) {
-                       tdb->ecode = TDB1_ERR_IO;
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_prepare_commit: expansion failed\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_prepare_commit:"
+                                  " expansion failed");
                        _tdb1_transaction_cancel(tdb);
                        return -1;
                }
@@ -1016,14 +1054,17 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
        bool need_repack = false;
 
        if (tdb->transaction == NULL) {
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_commit: no transaction\n"));
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
+                                       "tdb1_transaction_commit:"
+                                       " no transaction");
                return -1;
        }
 
        if (tdb->transaction->transaction_error) {
-               tdb->ecode = TDB1_ERR_IO;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                       "tdb1_transaction_commit:"
+                                       " transaction error pending");
                _tdb1_transaction_cancel(tdb);
-               TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_transaction_commit: transaction error pending\n"));
                return -1;
        }
 
@@ -1063,7 +1104,9 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
                }
 
                if (methods->tdb1_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_commit: write failed during commit\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_commit:"
+                                  " write failed during commit");
 
                        /* we've overwritten part of the data and
                           possibly expanded the file, so we need to
@@ -1073,7 +1116,8 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
 
                        _tdb1_transaction_cancel(tdb);
 
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_commit: write failed\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_commit: write failed");
                        return -1;
                }
                SAFE_FREE(tdb->transaction->blocks[i]);
@@ -1133,8 +1177,9 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
 
        /* find the recovery area */
        if (tdb1_ofs_read(tdb, TDB1_RECOVERY_HEAD, &recovery_head) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to read recovery head\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover:"
+                          " failed to read recovery head");
                return -1;
        }
 
@@ -1146,8 +1191,9 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
        /* read the recovery record */
        if (tdb->methods->tdb1_read(tdb, recovery_head, &rec,
                                   sizeof(rec), TDB1_DOCONV()) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to read recovery record\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover:"
+                          " failed to read recovery record");
                return -1;
        }
 
@@ -1157,8 +1203,10 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
        }
 
        if (tdb->read_only) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: attempt to recover read only database\n"));
-               tdb->ecode = TDB1_ERR_CORRUPT;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
+                                       "tdb1_transaction_recover:"
+                                       " attempt to recover read only"
+                                       " database");
                return -1;
        }
 
@@ -1166,16 +1214,18 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
 
        data = (unsigned char *)malloc(rec.data_len);
        if (data == NULL) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to allocate recovery data\n"));
-               tdb->ecode = TDB1_ERR_OOM;
+               tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+                                       "tdb1_transaction_recover:"
+                                       " failed to allocate recovery data");
                return -1;
        }
 
        /* read the full recovery data */
        if (tdb->methods->tdb1_read(tdb, recovery_head + sizeof(rec), data,
                                   rec.data_len, 0) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to read recovery data\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover:"
+                          " failed to read recovery data");
                return -1;
        }
 
@@ -1191,8 +1241,9 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
 
                if (tdb->methods->tdb1_write(tdb, ofs, p+8, len) == -1) {
                        free(data);
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs));
-                       tdb->ecode = TDB1_ERR_IO;
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_recover: failed to recover"
+                                  " %d bytes at offset %d", len, ofs);
                        return -1;
                }
                p += 8 + len;
@@ -1201,16 +1252,17 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
        free(data);
 
        if (transaction1_sync(tdb, 0, tdb->map_size) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to sync recovery\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover: failed to sync recovery");
                return -1;
        }
 
        /* if the recovery area is after the recovered eof then remove it */
        if (recovery_eof <= recovery_head) {
                if (tdb1_ofs_write(tdb, TDB1_RECOVERY_HEAD, &zero) == -1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to remove recovery head\n"));
-                       tdb->ecode = TDB1_ERR_IO;
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_transaction_recover: failed to remove"
+                                  " recovery head");
                        return -1;
                }
        }
@@ -1218,19 +1270,22 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
        /* remove the recovery magic */
        if (tdb1_ofs_write(tdb, recovery_head + offsetof(struct tdb1_record, magic),
                          &zero) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to remove recovery magic\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover: failed to remove"
+                          " recovery magic");
                return -1;
        }
 
        if (transaction1_sync(tdb, 0, recovery_eof) == -1) {
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_transaction_recover: failed to sync2 recovery\n"));
-               tdb->ecode = TDB1_ERR_IO;
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_transaction_recover:"
+                          " failed to sync2 recovery");
                return -1;
        }
 
-       TDB1_LOG((tdb, TDB1_DEBUG_TRACE, "tdb1_transaction_recover: recovered %d byte database\n",
-                recovery_eof));
+       tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING,
+                  "tdb1_transaction_recover: recovered %d byte database",
+                  recovery_eof);
 
        /* all done */
        return 0;
index ba1501279dbdfee1e07b50c3680f823f76e4db80..13813eebbb3179c3a0ee92578e944a11482b108e 100644 (file)
@@ -102,8 +102,10 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
 
                        /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
                        if (tlock->off == rec->next) {
-                               tdb->ecode = TDB1_ERR_CORRUPT;
-                               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_next_lock: loop detected.\n"));
+                               tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
+                                                       TDB_LOG_ERROR,
+                                                       "tdb1_next_lock:"
+                                                       " loop detected.");
                                goto fail;
                        }
 
@@ -125,13 +127,14 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
                want_next = 0;
        }
        /* We finished iteration without finding anything */
-       tdb->ecode = TDB1_SUCCESS;
+       tdb->last_error = TDB_SUCCESS;
        return 0;
 
  fail:
        tlock->off = 0;
        if (tdb1_unlock(tdb, tlock->hash, tlock->lock_rw) != 0)
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_next_lock: On error unlock failed!\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_next_lock: On error unlock failed!");
        return TDB1_NEXT_LOCK_ERR;
 }
 
@@ -172,7 +175,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
                        if (tdb1_unlock(tdb, tl->hash, tl->lock_rw) != 0)
                                goto out;
                        if (tdb1_unlock_record(tdb, tl->off) != 0)
-                               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_traverse: key.dptr == NULL and unlock_record failed!\n"));
+                               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                          "tdb1_traverse: key.dptr == NULL and"
+                                          " unlock_record failed!");
                        goto out;
                }
                key.dsize = rec.key_len;
@@ -188,7 +193,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
                if (fn && fn(tdb, key, dbuf, private_data)) {
                        /* They want us to terminate traversal */
                        if (tdb1_unlock_record(tdb, tl->off) != 0) {
-                               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_traverse: unlock_record failed!\n"));;
+                               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                          "tdb1_traverse:"
+                                          " unlock_record failed!");
                                ret = -1;
                        }
                        SAFE_FREE(key.dptr);
@@ -284,7 +291,9 @@ TDB1_DATA tdb1_firstkey(struct tdb1_context *tdb)
 
        /* Unlock the hash chain of the record we just read. */
        if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_firstkey: error occurred while tdb1_unlocking!\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_firstkey:"
+                          " error occurred while tdb1_unlocking!");
        return key;
 }
 
@@ -328,7 +337,9 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey)
                }
                tdb->travlocks.hash = TDB1_BUCKET(rec.full_hash);
                if (tdb1_lock_record(tdb, tdb->travlocks.off) != 0) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_nextkey: lock_record failed (%s)!\n", strerror(errno)));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_nextkey: lock_record failed (%s)!",
+                                  strerror(errno));
                        return tdb1_null;
                }
        }
@@ -343,10 +354,12 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey)
                                          key.dsize);
                /* Unlock the chain of this new record */
                if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_nextkey: WARNING tdb1_unlock failed!\n"));
+                       tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                                  "tdb1_nextkey: WARNING tdb1_unlock failed!");
        }
        /* Unlock the chain of old record */
        if (tdb1_unlock(tdb, TDB1_BUCKET(oldhash), tdb->travlocks.lock_rw) != 0)
-               TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_nextkey: WARNING tdb1_unlock failed!\n"));
+               tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
+                          "tdb1_nextkey: WARNING tdb1_unlock failed!");
        return key;
 }
index 6509ca3ab7fa32a19bd839680482a098bf1de8da..fd66c047b1f1e64e29229302965e895b8d024c42 100644 (file)
@@ -11,7 +11,7 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
                                  tdb1_off_t addition)
 {
        if (tdb->read_only || tdb->traverse_read) {
-               tdb->ecode = TDB1_ERR_RDONLY;
+               tdb->last_error = TDB_ERR_RDONLY;
                return -1;
        }
 
@@ -27,8 +27,10 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
                        errno = ENOSPC;
                }
                if (written != 1) {
-                       TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file to %d failed (%s)\n",
-                                size+addition, strerror(errno)));
+                       tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+                                               "expand_file to %d failed (%s)",
+                                               size+addition,
+                                               strerror(errno));
                        return -1;
                }
        }
index 03b0191a17168d5cac68a45383dfdb41fa0bf15f..b3b240e0020fda8a14a499167ebc3a9af3aea733 100644 (file)
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
                          &taplogctx, NULL);
        ok1(tdb);
        ok1(tdb1_check(tdb, NULL, NULL) == -1);
-       ok1(tdb1_error(tdb) == TDB1_ERR_CORRUPT);
+       ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
        tdb1_close(tdb);
 
        /* Big and little endian should work! */
index 1a01de17ab31d6757a5a51d4dac2a3bb3da34467..7691260606fd486490131985606868d2b76d7d89 100644 (file)
@@ -21,10 +21,10 @@ int main(int argc, char *argv[])
        data.dptr = (void *)"world";
 
        ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) < 0);
-       ok1(tdb1_error(tdb) == TDB1_ERR_NOEXIST);
+       ok1(tdb_error(tdb) == TDB_ERR_NOEXIST);
        ok1(tdb1_store(tdb, key, data, TDB1_INSERT) == 0);
        ok1(tdb1_store(tdb, key, data, TDB1_INSERT) < 0);
-       ok1(tdb1_error(tdb) == TDB1_ERR_EXISTS);
+       ok1(tdb_error(tdb) == TDB_ERR_EXISTS);
        ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == 0);
 
        data = tdb1_fetch(tdb, key);
index 5a4a61af331e918383ebbf1c1c8013479f7e5a05..13ba810169f9bb9a53ed1fc9d8a937023938cbf6 100644 (file)
@@ -8,10 +8,11 @@ static unsigned int tdb1_dumb_hash(TDB1_DATA *key)
        return key->dsize;
 }
 
-static void log_fn(struct tdb1_context *tdb, enum tdb1_debug_level level, const char *fmt, ...)
+static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
+                  enum TDB_ERROR ecode, const char *message, void *priv)
 {
-       unsigned int *count = tdb->log.log_private;
-       if (strstr(fmt, "hash"))
+       unsigned int *count = priv;
+       if (strstr(message, "hash"))
                (*count)++;
 }
 
index 2518003c634d06b464bba28d98ac82818e2aec84..e9640990e02945bddf952cabf3b431b8db0f912e 100644 (file)
@@ -28,7 +28,7 @@ int main(int argc, char *argv[])
        ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
        free(data.dptr);
        ok1(tdb1_transaction_start(tdb) != 0);
-       ok1(tdb1_error(tdb) == TDB1_ERR_NESTING);
+       ok1(tdb_error(tdb) == TDB_ERR_EINVAL);
 
        data = tdb1_fetch(tdb, key);
        ok1(data.dsize == strlen("world"));
index 2c06ca92eeb02cdc930f57b5677db93d0743001e..6bfa0dc3f5ad4ac434c88c24c5c4b56532094a71 100644 (file)
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
 
        ok1(tdb);
        ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == -1);
-       ok1(tdb1_error(tdb) == TDB1_ERR_RDONLY);
+       ok1(tdb_error(tdb) == TDB_ERR_RDONLY);
        ok1(tdb1_check(tdb, NULL, NULL) == 0);
        ok1(tdb1_close(tdb) == 0);
 
index f40a6fe13ec1148e6ed9281fa2193b03049cfb85..ec2a66a5bfd21afd3ddc4425bd66aec25e8f5a07 100644 (file)
@@ -3,10 +3,11 @@
 #include <stdlib.h>
 #include <err.h>
 
-static void log_fn(struct tdb1_context *tdb, enum tdb1_debug_level level, const char *fmt, ...)
+static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
+                  enum TDB_ERROR ecode, const char *message, void *priv)
 {
-       unsigned int *count = tdb->log.log_private;
-       if (strstr(fmt, "spinlocks"))
+       unsigned int *count = priv;
+       if (strstr(message, "spinlocks"))
                (*count)++;
 }
 
index 15047677a2ce2e73ca4d9daf288b34241e303e5a..59bfbbeccb076ad73ab4442671a4f9ac7a7fc95b 100644 (file)
@@ -3,10 +3,11 @@
 #include <stdlib.h>
 #include <err.h>
 
-static void log_fn(struct tdb1_context *tdb, enum tdb1_debug_level level, const char *fmt, ...)
+static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
+                  enum TDB_ERROR ecode, const char *message, void *priv)
 {
-       unsigned int *count = tdb->log.log_private;
-       if (strstr(fmt, "hash"))
+       unsigned int *count = priv;
+       if (strstr(message, "hash"))
                (*count)++;
 }
 
index ebbfd77bb2bae9f92704ed2af44312b3ebab7c0e..30de924cd205b970e5ce4d02f0e238d0309645e8 100644 (file)
@@ -20,10 +20,10 @@ int main(int argc, char *argv[])
        data.dptr = (void *)"world";
 
        ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) < 0);
-       ok1(tdb1_error(tdb) == TDB1_ERR_NOEXIST);
+       ok1(tdb_error(tdb) == TDB_ERR_NOEXIST);
        ok1(tdb1_store(tdb, key, data, TDB1_INSERT) == 0);
        ok1(tdb1_store(tdb, key, data, TDB1_INSERT) < 0);
-       ok1(tdb1_error(tdb) == TDB1_ERR_EXISTS);
+       ok1(tdb_error(tdb) == TDB_ERR_EXISTS);
        ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == 0);
 
        data = tdb1_fetch(tdb, key);
index da9d70946861a38959287b4b405776a88ac93f62..7ccbd9ca37164b17f38261e1ad86ee8d81c065dc 100644 (file)
@@ -61,7 +61,7 @@ static enum agent_return do_operation(enum operation op, const char *name)
        case FETCH:
                data = tdb1_fetch(tdb, k);
                if (data.dptr == NULL) {
-                       if (tdb->ecode == TDB1_ERR_NOEXIST)
+                       if (tdb->last_error == TDB_ERR_NOEXIST)
                                ret = FAILED;
                        else
                                ret = OTHER_FAILURE;
index 43ce07b27cc3bb46a0762fb5ad382f9a4c4b67aa..3424296b9184ffeb73f0128d9c7b43f950c04999 100644 (file)
@@ -7,24 +7,19 @@
 
 /* Turn log messages into tap diag messages. */
 static void taplog(struct tdb1_context *tdb,
-                  enum tdb1_debug_level level,
-                  const char *fmt, ...)
+                  enum tdb_log_level level,
+                  enum TDB_ERROR ecode,
+                  const char *message,
+                  void *data)
 {
-       va_list ap;
-       char line[200];
-
        if (suppress_logging)
                return;
 
-       va_start(ap, fmt);
-       vsprintf(line, fmt, ap);
-       va_end(ap);
-
        /* Strip trailing \n: diag adds it. */
-       if (line[0] && line[strlen(line)-1] == '\n')
-               diag("%s%.*s", log_prefix, (unsigned)strlen(line)-1, line);
+       if (message[0] && message[strlen(message)-1] == '\n')
+               diag("%s%.*s", log_prefix, (unsigned)strlen(message)-1, message);
        else
-               diag("%s%s", log_prefix, line);
+               diag("%s%s", log_prefix, message);
 }
 
 struct tdb1_logging_context taplogctx = { taplog, NULL };