Commit 91993735 authored by Rusty Russell's avatar Rusty Russell

tdb2: make TDB1 code use tdb2's TDB_ERROR and tdb_logerr()

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.
parent 1e3138a0
...@@ -336,6 +336,9 @@ struct tdb_context { ...@@ -336,6 +336,9 @@ struct tdb_context {
void *data); void *data);
void *log_data; void *log_data;
/* Last error we returned. */
enum TDB_ERROR last_error;
/* Open flags passed to tdb_open. */ /* Open flags passed to tdb_open. */
int open_flags; int open_flags;
...@@ -375,9 +378,6 @@ struct tdb_context { ...@@ -375,9 +378,6 @@ struct tdb_context {
/* Direct access information */ /* Direct access information */
struct tdb_access_hdr *access; struct tdb_access_hdr *access;
/* Last error we returned. */
enum TDB_ERROR last_error;
/* The actual file information */ /* The actual file information */
struct tdb_file *file; struct tdb_file *file;
}; };
......
...@@ -55,39 +55,18 @@ ...@@ -55,39 +55,18 @@
#define TDB1_DISALLOW_NESTING 1024 /** Disallow transactions to nest */ #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. */ #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 */ /** The tdb data structure */
typedef struct TDB1_DATA { typedef struct TDB1_DATA {
unsigned char *dptr; unsigned char *dptr;
size_t dsize; size_t dsize;
} TDB1_DATA; } 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. */ /** This is the context structure that is returned from a db open. */
typedef struct tdb1_context TDB1_CONTEXT; typedef struct tdb1_context TDB1_CONTEXT;
typedef int (*tdb1_traverse_func)(struct tdb1_context *, TDB1_DATA, TDB1_DATA, void *); 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); typedef unsigned int (*tdb1_hash_func)(TDB1_DATA *key);
struct tdb1_logging_context { struct tdb1_logging_context {
...@@ -138,8 +117,6 @@ int tdb1_lockall_read(struct tdb1_context *tdb); ...@@ -138,8 +117,6 @@ int tdb1_lockall_read(struct tdb1_context *tdb);
int tdb1_unlockall_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_start(struct tdb1_context *tdb);
int tdb1_transaction_prepare_commit(struct tdb1_context *tdb); int tdb1_transaction_prepare_commit(struct tdb1_context *tdb);
......
...@@ -61,8 +61,8 @@ static bool tdb1_check_header(struct tdb1_context *tdb, tdb1_off_t *recovery) ...@@ -61,8 +61,8 @@ static bool tdb1_check_header(struct tdb1_context *tdb, tdb1_off_t *recovery)
return true; return true;
corrupt: corrupt:
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "Header is corrupt\n")); "Header is corrupt\n");
return false; return false;
} }
...@@ -75,21 +75,21 @@ static bool tdb1_check_record(struct tdb1_context *tdb, ...@@ -75,21 +75,21 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
/* Check rec->next: 0 or points to record offset, aligned. */ /* Check rec->next: 0 or points to record offset, aligned. */
if (rec->next > 0 && rec->next < TDB1_DATA_START(tdb->header.hash_size)){ if (rec->next > 0 && rec->next < TDB1_DATA_START(tdb->header.hash_size)){
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d too small next %d\n", "Record offset %d too small next %d\n",
off, rec->next)); off, rec->next);
goto corrupt; goto corrupt;
} }
if (rec->next + sizeof(*rec) < rec->next) { if (rec->next + sizeof(*rec) < rec->next) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d too large next %d\n", "Record offset %d too large next %d\n",
off, rec->next)); off, rec->next);
goto corrupt; goto corrupt;
} }
if ((rec->next % TDB1_ALIGNMENT) != 0) { if ((rec->next % TDB1_ALIGNMENT) != 0) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d misaligned next %d\n", "Record offset %d misaligned next %d\n",
off, rec->next)); off, rec->next);
goto corrupt; goto corrupt;
} }
if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0)) if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0))
...@@ -97,16 +97,16 @@ static bool tdb1_check_record(struct tdb1_context *tdb, ...@@ -97,16 +97,16 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
/* Check rec_len: similar to rec->next, implies next record. */ /* Check rec_len: similar to rec->next, implies next record. */
if ((rec->rec_len % TDB1_ALIGNMENT) != 0) { if ((rec->rec_len % TDB1_ALIGNMENT) != 0) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d misaligned length %d\n", "Record offset %d misaligned length %d\n",
off, rec->rec_len)); off, rec->rec_len);
goto corrupt; goto corrupt;
} }
/* Must fit tailer. */ /* Must fit tailer. */
if (rec->rec_len < sizeof(tailer)) { if (rec->rec_len < sizeof(tailer)) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d too short length %d\n", "Record offset %d too short length %d\n",
off, rec->rec_len)); off, rec->rec_len);
goto corrupt; goto corrupt;
} }
/* OOB allows "right at the end" access, so this works for last rec. */ /* 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, ...@@ -118,15 +118,15 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
&tailer) == -1) &tailer) == -1)
goto corrupt; goto corrupt;
if (tailer != sizeof(*rec) + rec->rec_len) { if (tailer != sizeof(*rec) + rec->rec_len) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d invalid tailer\n", off)); "Record offset %d invalid tailer\n", off);
goto corrupt; goto corrupt;
} }
return true; return true;
corrupt: corrupt:
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = TDB_ERR_CORRUPT;
return false; return false;
} }
...@@ -246,8 +246,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb, ...@@ -246,8 +246,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb,
/* key + data + tailer must fit in record */ /* key + data + tailer must fit in record */
if (rec->key_len + rec->data_len + sizeof(tdb1_off_t) > rec->rec_len) { if (rec->key_len + rec->data_len + sizeof(tdb1_off_t) > rec->rec_len) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d too short for contents\n", off)); "Record offset %d too short for contents\n", off);
return false; return false;
} }
...@@ -256,8 +256,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb, ...@@ -256,8 +256,8 @@ static bool tdb1_check_used_record(struct tdb1_context *tdb,
return false; return false;
if (tdb->hash_fn(&key) != rec->full_hash) { if (tdb->hash_fn(&key) != rec->full_hash) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Record offset %d has incorrect hash\n", off)); "Record offset %d has incorrect hash\n", off);
goto fail_put_key; goto fail_put_key;
} }
...@@ -353,8 +353,8 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -353,8 +353,8 @@ int tdb1_check(struct tdb1_context *tdb,
/* We should have the whole header, too. */ /* We should have the whole header, too. */
if (tdb->map_size < TDB1_DATA_START(tdb->header.hash_size)) { if (tdb->map_size < TDB1_DATA_START(tdb->header.hash_size)) {
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "File too short for hashes\n")); "File too short for hashes\n");
goto unlock; goto unlock;
} }
...@@ -363,7 +363,7 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -363,7 +363,7 @@ int tdb1_check(struct tdb1_context *tdb,
1, sizeof(hashes[0]) * (1+tdb->header.hash_size) 1, sizeof(hashes[0]) * (1+tdb->header.hash_size)
+ BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size)); + BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size));
if (!hashes) { if (!hashes) {
tdb->ecode = TDB1_ERR_OOM; tdb->last_error = TDB_ERR_OOM;
goto unlock; goto unlock;
} }
...@@ -410,26 +410,25 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -410,26 +410,25 @@ int tdb1_check(struct tdb1_context *tdb,
if (dead < sizeof(rec)) if (dead < sizeof(rec))
goto corrupt; goto corrupt;
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb_logerr(tdb, TDB_SUCCESS, TDB_LOG_WARNING,
"Dead space at %d-%d (of %u)\n", "Dead space at %d-%d (of %u)\n",
off, off + dead, tdb->map_size)); off, off + dead, tdb->map_size);
rec.rec_len = dead - sizeof(rec); rec.rec_len = dead - sizeof(rec);
break; break;
case TDB1_RECOVERY_MAGIC: case TDB1_RECOVERY_MAGIC:
if (recovery_start != off) { if (recovery_start != off) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Unexpected recovery record at offset %d\n", "Unexpected recovery record at offset %d\n",
off)); off);
goto free; goto free;
} }
found_recovery = true; found_recovery = true;
break; break;
default: ; default: ;
corrupt: corrupt:
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "Bad magic 0x%x at offset %d\n",
"Bad magic 0x%x at offset %d\n", rec.magic, off);
rec.magic, off));
goto free; goto free;
} }
} }
...@@ -440,9 +439,8 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -440,9 +439,8 @@ int tdb1_check(struct tdb1_context *tdb,
unsigned int i; unsigned int i;
for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) { for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) {
if (hashes[h][i] != 0) { if (hashes[h][i] != 0) {
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "Hashes do not match records\n");
"Hashes do not match records\n"));
goto free; goto free;
} }
} }
...@@ -450,9 +448,9 @@ int tdb1_check(struct tdb1_context *tdb, ...@@ -450,9 +448,9 @@ int tdb1_check(struct tdb1_context *tdb,
/* We must have found recovery area if there was one. */ /* We must have found recovery area if there was one. */
if (recovery_start != 0 && !found_recovery) { if (recovery_start != 0 && !found_recovery) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"Expected a recovery area at %u\n", "Expected a recovery area at %u\n",
recovery_start)); recovery_start);
goto free; goto free;
} }
......
...@@ -36,18 +36,18 @@ int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off, struct tdb1_rec ...@@ -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) { if (rec->magic == TDB1_MAGIC) {
/* this happens when a app is showdown while deleting a record - we should /* this happens when a app is showdown while deleting a record - we should
not completely fail when this happens */ 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", tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_WARNING,
rec->magic, off)); "tdb1_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
rec->magic, off);
rec->magic = TDB1_FREE_MAGIC; rec->magic = TDB1_FREE_MAGIC;
if (tdb->methods->tdb1_write(tdb, off, rec, sizeof(*rec)) == -1) if (tdb->methods->tdb1_write(tdb, off, rec, sizeof(*rec)) == -1)
return -1; return -1;
} }
if (rec->magic != TDB1_FREE_MAGIC) { if (rec->magic != TDB1_FREE_MAGIC) {
/* Ensure ecode is set for log fn. */ tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
tdb->ecode = TDB1_ERR_CORRUPT; "tdb1_rec_free_read bad magic 0x%x at offset=%d\n",
TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_rec_free_read bad magic 0x%x at offset=%d\n", rec->magic, off);
rec->magic, off));
return -1; return -1;
} }
if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0) != 0) 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 ...@@ -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 */ /* set an initial tailer, so if we fail we don't leave a bogus record */
if (update_tailer(tdb, offset, rec) != 0) { 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; goto fail;
} }
...@@ -90,7 +91,8 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r ...@@ -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 */ /* Read in tailer and jump back to header */
if (tdb1_ofs_read(tdb, left, &leftsize) == -1) { 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; goto update;
} }
...@@ -108,7 +110,8 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r ...@@ -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 */ /* Now read in the left record */
if (tdb->methods->tdb1_read(tdb, left, &l, sizeof(l), TDB1_DOCONV()) == -1) { 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; goto update;
} }
...@@ -119,11 +122,13 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r ...@@ -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 */ prevents traverse from being O(n^2) after a lot of deletes */
l.rec_len += sizeof(*rec) + rec->rec_len; l.rec_len += sizeof(*rec) + rec->rec_len;
if (tdb1_rec_write(tdb, left, &l) == -1) { 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; goto fail;
} }
if (update_tailer(tdb, left, &l) == -1) { 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; goto fail;
} }
tdb1_unlock(tdb, -1, F_WRLCK); tdb1_unlock(tdb, -1, F_WRLCK);
...@@ -139,7 +144,9 @@ update: ...@@ -139,7 +144,9 @@ update:
if (tdb1_ofs_read(tdb, TDB1_FREELIST_TOP, &rec->next) == -1 || if (tdb1_ofs_read(tdb, TDB1_FREELIST_TOP, &rec->next) == -1 ||
tdb1_rec_write(tdb, offset, rec) == -1 || tdb1_rec_write(tdb, offset, rec) == -1 ||
tdb1_ofs_write(tdb, TDB1_FREELIST_TOP, &offset) == -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; goto fail;
} }
......
...@@ -43,32 +43,30 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe) ...@@ -43,32 +43,30 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
return 0; return 0;
if (tdb->flags & TDB1_INTERNAL) { if (tdb->flags & TDB1_INTERNAL) {
if (!probe) { if (!probe) {
/* Ensure ecode is set for log fn. */ tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
tdb->ecode = TDB1_ERR_IO; "tdb1_oob len %d beyond internal malloc size %d",
TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_oob len %d beyond internal malloc size %d\n", (int)len, (int)tdb->map_size);
(int)len, (int)tdb->map_size));
} }
return -1; return -1;
} }
if (fstat(tdb->fd, &st) == -1) { if (fstat(tdb->fd, &st) == -1) {
tdb->ecode = TDB1_ERR_IO; tdb->last_error = TDB_ERR_IO;
return -1; return -1;
} }
if (st.st_size < (size_t)len) { if (st.st_size < (size_t)len) {
if (!probe) { if (!probe) {
/* Ensure ecode is set for log fn. */ tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
tdb->ecode = TDB1_ERR_IO; "tdb1_oob len %d beyond eof at %d",
TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_oob len %d beyond eof at %d\n", (int)len, (int)st.st_size);
(int)len, (int)st.st_size));
} }
return -1; return -1;
} }
/* Unmap, update size, remap */ /* Unmap, update size, remap */
if (tdb1_munmap(tdb) == -1) { if (tdb1_munmap(tdb) == -1) {
tdb->ecode = TDB1_ERR_IO; tdb->last_error = TDB_ERR_IO;
return -1; return -1;
} }
tdb->map_size = st.st_size; tdb->map_size = st.st_size;
...@@ -85,7 +83,7 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off, ...@@ -85,7 +83,7 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
} }
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_RDONLY; tdb->last_error = TDB_ERR_RDONLY;
return -1; return -1;
} }
...@@ -97,26 +95,26 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off, ...@@ -97,26 +95,26 @@ static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
} else { } else {
ssize_t written = pwrite(tdb->fd, buf, len, off); ssize_t written = pwrite(tdb->fd, buf, len, off);
if ((written != (ssize_t)len) && (written != -1)) { if ((written != (ssize_t)len) && (written != -1)) {
/* try once more */ tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
tdb->ecode = TDB1_ERR_IO; "tdb1_write: wrote only "
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_write: wrote only " "%d of %d bytes at %d, trying once more",
"%d of %d bytes at %d, trying once more\n", (int)written, len, off);
(int)written, len, off));
written = pwrite(tdb->fd, (const char *)buf+written, written = pwrite(tdb->fd, (const char *)buf+written,
len-written, len-written,
off+written); off+written);
} }
if (written == -1) { if (written == -1) {
/* Ensure ecode is set for log fn. */ /* Ensure ecode is set for log fn. */
tdb->ecode = TDB1_ERR_IO; tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_write failed at %d " "tdb1_write failed at %d "
"len=%d (%s)\n", off, len, strerror(errno))); "len=%d (%s)",
off, len, strerror(errno));
return -1; return -1;
} else if (written != (ssize_t)len) { } else if (written != (ssize_t)len) {
tdb->ecode = TDB1_ERR_IO; tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_write: failed to " "tdb1_write: failed to "
"write %d bytes at %d in two attempts\n", "write %d bytes at %d in two attempts",
len, off)); len, off);
return -1; return -1;
} }
} }
...@@ -147,11 +145,12 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf, ...@@ -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); ssize_t ret = pread(tdb->fd, buf, len, off);
if (ret != (ssize_t)len) { if (ret != (ssize_t)len) {
/* Ensure ecode is set for log fn. */ /* Ensure ecode is set for log fn. */
tdb->ecode = TDB1_ERR_IO; tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_read failed at %d " "tdb1_read failed at %d "
"len=%d ret=%d (%s) map_size=%d\n", "len=%d ret=%d (%s) map_size=%d",
(int)off, (int)len, (int)ret, strerror(errno), (int)off, (int)len, (int)ret,
(int)tdb->map_size)); strerror(errno),
(int)tdb->map_size);
return -1; return -1;
} }
} }
...@@ -223,8 +222,9 @@ void tdb1_mmap(struct tdb1_context *tdb) ...@@ -223,8 +222,9 @@ void tdb1_mmap(struct tdb1_context *tdb)
if (tdb->map_ptr == MAP_FAILED) { if (tdb->map_ptr == MAP_FAILED) {
tdb->map_ptr = NULL; tdb->map_ptr = NULL;
TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "tdb1_mmap failed for size %d (%s)\n", tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
tdb->map_size, strerror(errno))); "tdb1_mmap failed for size %d (%s)",
tdb->map_size, strerror(errno));
} }
} else { } else {
tdb->map_ptr = NULL; tdb->map_ptr = NULL;
...@@ -241,7 +241,7 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_ ...@@ -241,7 +241,7 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
char buf[8192]; char buf[8192];
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_RDONLY; tdb->last_error = TDB_ERR_RDONLY;
return -1; return -1;
} }
...@@ -257,8 +257,10 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_ ...@@ -257,8 +257,10 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
errno = ENOSPC; errno = ENOSPC;
} }
if (written != 1) { if (written != 1) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file to %d failed (%s)\n", tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
size+addition, strerror(errno))); "expand_file to %d failed (%s)",
size+addition,
strerror(errno));
return -1; return -1;
} }
} }
...@@ -276,19 +278,22 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_ ...@@ -276,19 +278,22 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
} }
if (written == 0) { if (written == 0) {
/* give up, trying to provide a useful errno */ /* give up, trying to provide a useful errno */
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file write " tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"returned 0 twice: giving up!\n")); "expand_file write "
"returned 0 twice: giving up!");
errno = ENOSPC; errno = ENOSPC;
return -1; return -1;
} else if (written == -1) { } else if (written == -1) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file write of " tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"%d bytes failed (%s)\n", (int)n, "expand_file write of "
strerror(errno))); "%d bytes failed (%s)", (int)n,
strerror(errno));
return -1; return -1;
} else if (written != n) { } else if (written != n) {
TDB1_LOG((tdb, TDB1_DEBUG_WARNING, "expand_file: wrote " tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_WARNING,
"only %d of %d bytes - retrying\n", (int)written, "expand_file: wrote "
(int)n)); "only %d of %d bytes - retrying",
(int)written, (int)n);
} }
addition -= written; addition -= written;
size += written; size += written;
...@@ -305,7 +310,8 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size) ...@@ -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; tdb1_off_t offset, new_size, top_size, map_size;
if (tdb1_lock(tdb, -1, F_WRLCK) == -1) { 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; return -1;
} }
...@@ -406,10 +412,10 @@ unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1 ...@@ -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 */ /* some systems don't like zero length malloc */
if (!(buf = (unsigned char *)malloc(len ? len : 1))) { if (!(buf = (unsigned char *)malloc(len ? len : 1))) {
/* Ensure ecode is set for log fn. */ tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
tdb->ecode = TDB1_ERR_OOM; "tdb1_alloc_read malloc failed"
TDB1_LOG((tdb, TDB1_DEBUG_ERROR,"tdb1_alloc_read malloc failed len=%d (%s)\n", " len=%d (%s)",
len, strerror(errno))); len, strerror(errno));
return NULL; return NULL;
} }
if (tdb->methods->tdb1_read(tdb, offset, buf, len, 0) == -1) { 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 ...@@ -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) if (tdb->methods->tdb1_read(tdb, offset, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
return -1; return -1;
if (TDB1_BAD_MAGIC(rec)) { if (TDB1_BAD_MAGIC(rec)) {
/* Ensure ecode is set for log fn. */ tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
tdb->ecode = TDB1_ERR_CORRUPT; "tdb1_rec_read bad magic 0x%x at offset=%d",
TDB1_LOG((tdb, TDB1_DEBUG_FATAL,"tdb1_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); rec->magic, offset);
return -1; return -1;
} }
return tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0); return tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0);
......
...@@ -139,7 +139,7 @@ int tdb1_brlock(struct tdb1_context *tdb, ...@@ -139,7 +139,7 @@ int tdb1_brlock(struct tdb1_context *tdb,
} }
if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
tdb->ecode = TDB1_ERR_RDONLY; tdb->last_error = TDB_ERR_RDONLY;
return -1; return -1;
} }
...@@ -149,13 +149,14 @@ int tdb1_brlock(struct tdb1_context *tdb, ...@@ -149,13 +149,14 @@ int tdb1_brlock(struct tdb1_context *tdb,
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
if (ret == -1) { if (ret == -1) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
/* Generic lock error. errno set by fcntl. /* Generic lock error. errno set by fcntl.
* EAGAIN is an expected return from non-blocking * EAGAIN is an expected return from non-blocking
* locks. */ * locks. */
if (!(flags & TDB1_LOCK_PROBE) && errno != EAGAIN) { 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_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
tdb->fd, offset, rw_type, flags, (int)len)); "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; return -1;
} }
...@@ -176,8 +177,10 @@ int tdb1_brunlock(struct tdb1_context *tdb, ...@@ -176,8 +177,10 @@ int tdb1_brunlock(struct tdb1_context *tdb,
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
if (ret == -1) { if (ret == -1) {
TDB1_LOG((tdb, TDB1_DEBUG_TRACE,"tdb1_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n", tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
tdb->fd, offset, rw_type, (int)len)); "tdb1_brunlock failed (fd=%d) at offset"
" %d rw_type=%d len=%d",
tdb->fd, offset, rw_type, (int)len);
} }
return ret; return ret;
} }
...@@ -193,15 +196,17 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb) ...@@ -193,15 +196,17 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
int count = 1000; int count = 1000;
if (tdb->allrecord_lock.count != 1) { if (tdb->allrecord_lock.count != 1) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
"tdb1_allrecord_upgrade failed: count %u too high\n", "tdb1_allrecord_upgrade failed: "
tdb->allrecord_lock.count)); "count %u too high",
tdb->allrecord_lock.count);
return -1; return -1;
} }
if (tdb->allrecord_lock.off != 1) { if (tdb->allrecord_lock.off != 1) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
"tdb1_allrecord_upgrade failed: already upgraded?\n")); "tdb1_allrecord_upgrade failed:"
" already upgraded?");
return -1; return -1;
} }
...@@ -221,7 +226,8 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb) ...@@ -221,7 +226,8 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
tv.tv_usec = 1; tv.tv_usec = 1;
select(0, NULL, NULL, NULL, &tv); 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; return -1;
} }
...@@ -245,9 +251,10 @@ int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype, ...@@ -245,9 +251,10 @@ int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype,
struct tdb1_lock_type *new_lck; struct tdb1_lock_type *new_lck;
if (offset >= lock_offset(tdb->header.hash_size)) { if (offset >= lock_offset(tdb->header.hash_size)) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_ERROR,"tdb1_lock: invalid offset %u for ltype=%d\n", "tdb1_lock: invalid offset %u for"
offset, ltype)); " ltype=%d",
offset, ltype);
return -1; return -1;
} }
if (tdb->flags & TDB1_NOLOCK) if (tdb->flags & TDB1_NOLOCK)
...@@ -332,7 +339,7 @@ static int tdb1_lock_list(struct tdb1_context *tdb, int list, int ltype, ...@@ -332,7 +339,7 @@ static int tdb1_lock_list(struct tdb1_context *tdb, int list, int ltype,
} }
if (tdb->allrecord_lock.count) { if (tdb->allrecord_lock.count) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
ret = -1; ret = -1;
} else { } else {
/* Only check when we grab first data lock. */ /* Only check when we grab first data lock. */
...@@ -358,8 +365,9 @@ int tdb1_lock(struct tdb1_context *tdb, int list, int ltype) ...@@ -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); ret = tdb1_lock_list(tdb, list, ltype, TDB1_LOCK_WAIT);
if (ret) { if (ret) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_lock failed on list %d " tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"ltype=%d (%s)\n", list, ltype, strerror(errno))); "tdb1_lock failed on list %d "
"ltype=%d (%s)", list, ltype, strerror(errno));
} }
return ret; return ret;
} }
...@@ -374,13 +382,16 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype) ...@@ -374,13 +382,16 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
/* Sanity checks */ /* Sanity checks */
if (offset >= lock_offset(tdb->header.hash_size)) { 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; return ret;
} }
lck = tdb1_find_nestlock(tdb, offset); lck = tdb1_find_nestlock(tdb, offset);
if ((lck == NULL) || (lck->count == 0)) { 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; return -1;
} }
...@@ -413,8 +424,6 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype) ...@@ -413,8 +424,6 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
SAFE_FREE(tdb->lockrecs); SAFE_FREE(tdb->lockrecs);
} }
if (ret)
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_unlock: An error occurred unlocking!\n"));
return ret; return ret;
} }
...@@ -427,7 +436,7 @@ int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype) ...@@ -427,7 +436,7 @@ int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype)
} }
if (tdb->allrecord_lock.count) { if (tdb->allrecord_lock.count) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
...@@ -457,7 +466,7 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype, ...@@ -457,7 +466,7 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype,
{ {
/* There are no locks on read-only dbs */ /* There are no locks on read-only dbs */
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
...@@ -468,19 +477,19 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype, ...@@ -468,19 +477,19 @@ static int tdb1_allrecord_check(struct tdb1_context *tdb, int ltype,
if (tdb->allrecord_lock.count) { if (tdb->allrecord_lock.count) {
/* a global lock of a different type exists */ /* a global lock of a different type exists */
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
if (tdb1_have_extra_locks(tdb)) { if (tdb1_have_extra_locks(tdb)) {
/* can't combine global and chain locks */ /* can't combine global and chain locks */
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
if (upgradable && ltype != F_RDLCK) { if (upgradable && ltype != F_RDLCK) {
/* tdb error: you can't upgrade a write lock! */ /* tdb error: you can't upgrade a write lock! */
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
return 1; return 1;
...@@ -577,19 +586,19 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype) ...@@ -577,19 +586,19 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
{ {
/* There are no locks on read-only dbs */ /* There are no locks on read-only dbs */
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
if (tdb->allrecord_lock.count == 0) { if (tdb->allrecord_lock.count == 0) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
/* Upgradable locks are marked as write locks. */ /* Upgradable locks are marked as write locks. */
if (tdb->allrecord_lock.ltype != ltype if (tdb->allrecord_lock.ltype != ltype
&& (!tdb->allrecord_lock.off || ltype != F_RDLCK)) { && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) {
tdb->ecode = TDB1_ERR_LOCK; tdb->last_error = TDB_ERR_LOCK;
return -1; return -1;
} }
...@@ -599,7 +608,8 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype) ...@@ -599,7 +608,8 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
} }
if (tdb1_brunlock(tdb, ltype, TDB1_FREELIST_TOP, 0)) { 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; return -1;
} }
......
...@@ -60,7 +60,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size) ...@@ -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 */ /* 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); size = sizeof(struct tdb1_header) + (hash_size+1)*sizeof(tdb1_off_t);
if (!(newdb = (struct tdb1_header *)calloc(size, 1))) { if (!(newdb = (struct tdb1_header *)calloc(size, 1))) {
tdb->ecode = TDB1_ERR_OOM; tdb->last_error = TDB_ERR_OOM;
return -1; return -1;
} }
...@@ -135,12 +135,6 @@ struct tdb1_context *tdb1_open(const char *name, int hash_size, int tdb1_flags, ...@@ -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); 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, static bool check_header_hash(struct tdb1_context *tdb,
bool default_hash, uint32_t *m1, uint32_t *m2) 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 ...@@ -188,11 +182,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
tdb->flags = tdb1_flags; tdb->flags = tdb1_flags;
tdb->open_flags = open_flags; tdb->open_flags = open_flags;
if (log_ctx) { if (log_ctx) {
tdb->log = *log_ctx; tdb->log_fn = log_ctx->log_fn;
} else { tdb->log_data = log_ctx->log_private;
tdb->log.log_fn = null_log_fn; } else
tdb->log.log_private = NULL; tdb->log_fn = NULL;
}
if (name == NULL && (tdb1_flags & TDB1_INTERNAL)) { if (name == NULL && (tdb1_flags & TDB1_INTERNAL)) {
name = "__TDB1_INTERNAL__"; name = "__TDB1_INTERNAL__";
...@@ -200,7 +193,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -200,7 +193,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
if (name == NULL) { if (name == NULL) {
tdb->name = (char *)"__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; tdb->name = NULL;
errno = EINVAL; errno = EINVAL;
goto fail; goto fail;
...@@ -213,8 +207,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -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. * work in case of an error.
*/ */
tdb->name = (char *)name; tdb->name = (char *)name;
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: can't strdup(%s)\n", tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
name)); "tdb1_open_ex: can't strdup(%s)", name);
tdb->name = NULL; tdb->name = NULL;
errno = ENOMEM; errno = ENOMEM;
goto fail; goto fail;
...@@ -242,8 +236,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -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; tdb->max_dead_records = (tdb1_flags & TDB1_VOLATILE) ? 5 : 0;
if ((open_flags & O_ACCMODE) == O_WRONLY) { if ((open_flags & O_ACCMODE) == O_WRONLY) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: can't open tdb %s write-only\n", tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
name)); "tdb1_open_ex: can't open tdb %s write-only",
name);
errno = EINVAL; errno = EINVAL;
goto fail; goto fail;
} }
...@@ -259,9 +254,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -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) && if ((tdb->flags & TDB1_ALLOW_NESTING) &&
(tdb->flags & TDB1_DISALLOW_NESTING)) { (tdb->flags & TDB1_DISALLOW_NESTING)) {
tdb->ecode = TDB1_ERR_NESTING; tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: " "tdb1_open_ex: "
"allow_nesting and disallow_nesting are not allowed together!")); "allow_nesting and disallow_nesting are not allowed together!");
errno = EINVAL; errno = EINVAL;
goto fail; goto fail;
} }
...@@ -279,15 +274,17 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -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_NOLOCK | TDB1_NOMMAP);
tdb->flags &= ~TDB1_CLEAR_IF_FIRST; tdb->flags &= ~TDB1_CLEAR_IF_FIRST;
if (tdb1_new_database(tdb, hash_size) != 0) { 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 fail;
} }
goto internal; goto internal;
} }
if ((tdb->fd = open(name, open_flags, mode)) == -1) { 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", tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
name, strerror(errno))); "tdb1_open_ex: could not open file %s: %s",
name, strerror(errno));
goto fail; /* errno set by open(2) */ 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 ...@@ -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 */ /* ensure there is only one process initialising at once */
if (tdb1_nest_lock(tdb, TDB1_OPEN_LOCK, F_WRLCK, TDB1_LOCK_WAIT) == -1) { 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", tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
name, strerror(errno))); "tdb1_open_ex: failed to get open lock on %s: %s",
name, strerror(errno));
goto fail; /* errno set by tdb1_brlock */ 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 ...@@ -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))) { (locked = (tdb1_nest_lock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK, TDB1_LOCK_NOWAIT|TDB1_LOCK_PROBE) == 0))) {
open_flags |= O_CREAT; open_flags |= O_CREAT;
if (ftruncate(tdb->fd, 0) == -1) { if (ftruncate(tdb->fd, 0) == -1) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: " tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"failed to truncate %s: %s\n", "tdb1_open_ex: "
name, strerror(errno))); "failed to truncate %s: %s",
name, strerror(errno));
goto fail; /* errno set by ftruncate */ 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 ...@@ -346,7 +345,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
if (tdb->header.rwlocks != 0 && if (tdb->header.rwlocks != 0 &&
tdb->header.rwlocks != TDB1_HASH_RWLOCK_MAGIC) { 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; goto fail;
} }
...@@ -354,26 +354,28 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -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 */ /* older TDB without magic hash references */
tdb->hash_fn = tdb1_old_hash; tdb->hash_fn = tdb1_old_hash;
} else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) { } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_open_ex: " tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_USE_ERROR,
"%s was not created with %s hash function we are using\n" "tdb1_open_ex: "
"magic1_hash[0x%08X %s 0x%08X] " "%s was not created with %s hash function we are using\n"
"magic2_hash[0x%08X %s 0x%08X]\n", "magic1_hash[0x%08X %s 0x%08X] "
name, hash_alg, "magic2_hash[0x%08X %s 0x%08X]",
tdb->header.magic1_hash, name, hash_alg,
(tdb->header.magic1_hash == magic1) ? "==" : "!=", tdb->header.magic1_hash,
magic1, (tdb->header.magic1_hash == magic1) ? "==" : "!=",
tdb->header.magic2_hash, magic1,
(tdb->header.magic2_hash == magic2) ? "==" : "!=", tdb->header.magic2_hash,
magic2)); (tdb->header.magic2_hash == magic2) ? "==" : "!=",
magic2);
errno = EINVAL; errno = EINVAL;
goto fail; goto fail;
} }
/* Is it already in the open list? If so, fail. */ /* Is it already in the open list? If so, fail. */
if (tdb1_already_open(st.st_dev, st.st_ino)) { if (tdb1_already_open(st.st_dev, st.st_ino)) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: " tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_USE_ERROR,
"%s (%d,%d) is already open in this process\n", "tdb1_open_ex: "
name, (int)st.st_dev, (int)st.st_ino)); "%s (%d,%d) is already open in this process",
name, (int)st.st_dev, (int)st.st_ino);
errno = EBUSY; errno = EBUSY;
goto fail; goto fail;
} }
...@@ -384,9 +386,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -384,9 +386,10 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
tdb1_mmap(tdb); tdb1_mmap(tdb);
if (locked) { if (locked) {
if (tdb1_nest_unlock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK) == -1) { if (tdb1_nest_unlock(tdb, TDB1_ACTIVE_LOCK, F_WRLCK) == -1) {
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, "tdb1_open_ex: " tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"failed to release ACTIVE_LOCK on %s: %s\n", "tdb1_open_ex: "
name, strerror(errno))); "failed to release ACTIVE_LOCK on %s: %s",
name, strerror(errno));
goto fail; goto fail;
} }
...@@ -433,7 +436,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag ...@@ -433,7 +436,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
} }
if (tdb->fd != -1) if (tdb->fd != -1)
if (close(tdb->fd) != 0) 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->lockrecs);
SAFE_FREE(tdb->name); SAFE_FREE(tdb->name);
SAFE_FREE(tdb); SAFE_FREE(tdb);
......
...@@ -28,10 +28,16 @@ ...@@ -28,10 +28,16 @@
#include "private.h" #include "private.h"
#include "tdb1.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/ */ /***** END FIXME ***/
#define tdb1_error(tdb) ((tdb)->ecode)
#include <limits.h>
/* #define TDB_TRACE 1 */ /* #define TDB_TRACE 1 */
#ifndef HAVE_GETPAGESIZE #ifndef HAVE_GETPAGESIZE
...@@ -80,11 +86,6 @@ typedef uint32_t tdb1_off_t; ...@@ -80,11 +86,6 @@ typedef uint32_t tdb1_off_t;
#define TDB1_PAD_BYTE 0x42 #define TDB1_PAD_BYTE 0x42
#define TDB1_PAD_U32 0x42424242 #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 */ /* lock offsets */
#define TDB1_OPEN_LOCK 0 #define TDB1_OPEN_LOCK 0
#define TDB1_ACTIVE_LOCK 4 #define TDB1_ACTIVE_LOCK 4
...@@ -167,7 +168,21 @@ struct tdb1_methods { ...@@ -167,7 +168,21 @@ struct tdb1_methods {
}; };
struct tdb1_context { struct tdb1_context {
struct tdb1_context *next;
char *name; /* the name of the database */ 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 */ void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */ int fd; /* open file descriptor for the database */
tdb1_len_t map_size; /* how much space has been mapped */ tdb1_len_t map_size; /* how much space has been mapped */
...@@ -177,14 +192,11 @@ struct tdb1_context { ...@@ -177,14 +192,11 @@ struct tdb1_context {
struct tdb1_lock_type allrecord_lock; /* .offset == upgradable */ struct tdb1_lock_type allrecord_lock; /* .offset == upgradable */
int num_lockrecs; int num_lockrecs;
struct tdb1_lock_type *lockrecs; /* only real locks, all with count>0 */ 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 */ struct tdb1_header header; /* a cached copy of the header */
uint32_t flags; /* the flags passed to tdb1_open */ uint32_t flags; /* the flags passed to tdb1_open */
struct tdb1_traverse_lock travlocks; /* current traversal locks */ 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 */ dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */ ino_t inode; /* uniquely identifies this tdb */
struct tdb1_logging_context log;
unsigned int (*hash_fn)(TDB1_DATA *key); unsigned int (*hash_fn)(TDB1_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */ int open_flags; /* flags used in the open - needed by reopen */
const struct tdb1_methods *methods; const struct tdb1_methods *methods;
......
...@@ -150,9 +150,11 @@ char *tdb1_summary(struct tdb1_context *tdb) ...@@ -150,9 +150,11 @@ char *tdb1_summary(struct tdb1_context *tdb)
tally1_add(&dead, rec.rec_len); tally1_add(&dead, rec.rec_len);
break; break;
default: default:
TDB1_LOG((tdb, TDB1_DEBUG_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
"Unexpected record magic 0x%x at offset %d\n", TDB_LOG_ERROR,
rec.magic, off)); "Unexpected record magic 0x%x"
" at offset %d",
rec.magic, off);
goto unlock; goto unlock;
} }
} }
......
...@@ -99,13 +99,14 @@ static tdb1_off_t tdb1_find(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha ...@@ -99,13 +99,14 @@ static tdb1_off_t tdb1_find(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha
} }
/* detect tight infinite loop */ /* detect tight infinite loop */
if (rec_ptr == r->next) { if (rec_ptr == r->next) {
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_find: loop detected.\n")); TDB_LOG_ERROR,
"tdb1_find: loop detected.");
return 0; return 0;
} }
rec_ptr = r->next; rec_ptr = r->next;
} }
tdb->ecode = TDB1_ERR_NOEXIST; tdb->last_error = TDB_ERR_NOEXIST;
return 0; return 0;
} }
...@@ -157,7 +158,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha ...@@ -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 */ /* must be long enough key, data and tailer */
if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb1_off_t)) { 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; return -1;
} }
...@@ -176,7 +177,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha ...@@ -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 */ /* find an entry in the database given a key */
/* If an entry doesn't exist tdb1_err will be set to /* 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 * then the TDB1_DATA will have zero length but
* a non-zero pointer * a non-zero pointer
*/ */
...@@ -239,7 +240,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB1_DATA key, ...@@ -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))) { if (!(rec_ptr = tdb1_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
/* record not found */ /* record not found */
tdb->ecode = TDB1_ERR_NOEXIST; tdb->last_error = TDB_ERR_NOEXIST;
return -1; return -1;
} }
...@@ -421,7 +422,8 @@ static int tdb1_delete_hash(struct tdb1_context *tdb, TDB1_DATA key, uint32_t ha ...@@ -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) 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; return ret;
} }
...@@ -474,7 +476,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, ...@@ -474,7 +476,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
/* check for it existing, on insert. */ /* check for it existing, on insert. */
if (flag == TDB1_INSERT) { if (flag == TDB1_INSERT) {
if (tdb1_exists_hash(tdb, key, hash)) { if (tdb1_exists_hash(tdb, key, hash)) {
tdb->ecode = TDB1_ERR_EXISTS; tdb->last_error = TDB_ERR_EXISTS;
goto fail; goto fail;
} }
} else { } else {
...@@ -482,7 +484,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, ...@@ -482,7 +484,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key,
if (tdb1_update_hash(tdb, key, hash, dbuf) == 0) { if (tdb1_update_hash(tdb, key, hash, dbuf) == 0) {
goto done; goto done;
} }
if (tdb->ecode == TDB1_ERR_NOEXIST && if (tdb->last_error == TDB_ERR_NOEXIST &&
flag == TDB1_MODIFY) { flag == TDB1_MODIFY) {
/* if the record doesn't exist and we are in TDB1_MODIFY mode then /* if the record doesn't exist and we are in TDB1_MODIFY mode then
we should fail the store */ we should fail the store */
...@@ -490,7 +492,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, ...@@ -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() */ /* 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 /* delete any existing record - if it doesn't exist we don't
care. Doing this first reduces fragmentation, and avoids care. Doing this first reduces fragmentation, and avoids
...@@ -502,7 +504,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, ...@@ -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. */ fails and we are left with a dead spot in the tdb. */
if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
tdb->ecode = TDB1_ERR_OOM; tdb->last_error = TDB_ERR_OOM;
goto fail; goto fail;
} }
...@@ -600,7 +602,7 @@ int tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA dbuf, int flag ...@@ -600,7 +602,7 @@ int tdb1_store(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA dbuf, int flag
int ret; int ret;
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_RDONLY; tdb->last_error = TDB_ERR_RDONLY;
return -1; return -1;
} }
...@@ -645,7 +647,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA new_dbuf) ...@@ -645,7 +647,7 @@ int tdb1_append(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA new_dbuf)
} }
if (dbuf.dptr == NULL) { if (dbuf.dptr == NULL) {
tdb->ecode = TDB1_ERR_OOM; tdb->last_error = TDB_ERR_OOM;
goto failed; goto failed;
} }
...@@ -661,16 +663,6 @@ 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 get the tdb sequence number. Only makes sense if the writers opened
with TDB1_SEQNUM set. Note that this sequence number will wrap quite 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 ...@@ -707,13 +699,16 @@ static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t
return 0; return 0;
} }
if (length + offset > tdb->map_size) { 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; return -1;
} }
memset(&rec,'\0',sizeof(rec)); memset(&rec,'\0',sizeof(rec));
rec.rec_len = length - sizeof(rec); rec.rec_len = length - sizeof(rec);
if (tdb1_free(tdb, offset, &rec) == -1) { 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 -1;
} }
return 0; return 0;
...@@ -744,14 +739,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb) ...@@ -744,14 +739,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
tdb1_wipe_all() in a transaction will increase the size of tdb1_wipe_all() in a transaction will increase the size of
the tdb by the size of the recovery area */ the tdb by the size of the recovery area */
if (tdb1_ofs_read(tdb, TDB1_RECOVERY_HEAD, &recovery_head) == -1) { 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; goto failed;
} }
if (recovery_head != 0) { if (recovery_head != 0) {
struct tdb1_record rec; struct tdb1_record rec;
if (tdb->methods->tdb1_read(tdb, recovery_head, &rec, sizeof(rec), TDB1_DOCONV()) == -1) { 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; return -1;
} }
recovery_size = rec.rec_len + sizeof(rec); recovery_size = rec.rec_len + sizeof(rec);
...@@ -760,14 +757,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb) ...@@ -760,14 +757,16 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
/* wipe the hashes */ /* wipe the hashes */
for (i=0;i<tdb->header.hash_size;i++) { for (i=0;i<tdb->header.hash_size;i++) {
if (tdb1_ofs_write(tdb, TDB1_HASH_TOP(i), &offset) == -1) { 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; goto failed;
} }
} }
/* wipe the freelist */ /* wipe the freelist */
if (tdb1_ofs_write(tdb, TDB1_FREELIST_TOP, &offset) == -1) { 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; goto failed;
} }
...@@ -800,7 +799,8 @@ int tdb1_wipe_all(struct tdb1_context *tdb) ...@@ -800,7 +799,8 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
} }
if (tdb1_unlockall(tdb) != 0) { 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; goto failed;
} }
...@@ -812,7 +812,7 @@ failed: ...@@ -812,7 +812,7 @@ failed:
} }
struct traverse_state { struct traverse_state {
bool error; enum TDB_ERROR error;
struct tdb1_context *dest_db; struct tdb1_context *dest_db;
}; };
...@@ -823,7 +823,7 @@ static int repack_traverse(struct tdb1_context *tdb, TDB1_DATA key, TDB1_DATA da ...@@ -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; struct traverse_state *state = (struct traverse_state *)private_data;
if (tdb1_store(state->dest_db, key, data, TDB1_INSERT) != 0) { if (tdb1_store(state->dest_db, key, data, TDB1_INSERT) != 0) {
state->error = true; state->error = state->dest_db->last_error;
return -1; return -1;
} }
return 0; return 0;
...@@ -838,53 +838,60 @@ int tdb1_repack(struct tdb1_context *tdb) ...@@ -838,53 +838,60 @@ int tdb1_repack(struct tdb1_context *tdb)
struct traverse_state state; struct traverse_state state;
if (tdb1_transaction_start(tdb) != 0) { 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; return -1;
} }
tmp_db = tdb1_open("tmpdb", tdb1_hash_size(tdb), TDB1_INTERNAL, O_RDWR|O_CREAT, 0); tmp_db = tdb1_open("tmpdb", tdb1_hash_size(tdb), TDB1_INTERNAL, O_RDWR|O_CREAT, 0);
if (tmp_db == NULL) { 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); tdb1_transaction_cancel(tdb);
return -1; return -1;
} }
state.error = false; state.error = TDB_SUCCESS;
state.dest_db = tmp_db; state.dest_db = tmp_db;
if (tdb1_traverse_read(tdb, repack_traverse, &state) == -1) { 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_transaction_cancel(tdb);
tdb1_close(tmp_db); tdb1_close(tmp_db);
return -1; return -1;
} }
if (state.error) { if (state.error != TDB_SUCCESS) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, __location__ " Error during traversal\n")); tdb->last_error = tdb_logerr(tdb, state.error, TDB_LOG_ERROR,
__location__ " Error during traversal");
tdb1_transaction_cancel(tdb); tdb1_transaction_cancel(tdb);
tdb1_close(tmp_db); tdb1_close(tmp_db);
return -1; return -1;
} }
if (tdb1_wipe_all(tdb) != 0) { 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_transaction_cancel(tdb);
tdb1_close(tmp_db); tdb1_close(tmp_db);
return -1; return -1;
} }
state.error = false; state.error = TDB_SUCCESS;
state.dest_db = tdb; state.dest_db = tdb;
if (tdb1_traverse_read(tmp_db, repack_traverse, &state) == -1) { 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_transaction_cancel(tdb);
tdb1_close(tmp_db); tdb1_close(tmp_db);
return -1; return -1;
} }
if (state.error) { 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_transaction_cancel(tdb);
tdb1_close(tmp_db); tdb1_close(tmp_db);
return -1; return -1;
...@@ -893,7 +900,8 @@ int tdb1_repack(struct tdb1_context *tdb) ...@@ -893,7 +900,8 @@ int tdb1_repack(struct tdb1_context *tdb)
tdb1_close(tmp_db); tdb1_close(tmp_db);
if (tdb1_transaction_commit(tdb) != 0) { 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; return -1;
} }
......
This diff is collapsed.
...@@ -102,8 +102,10 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_ ...@@ -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>. */ /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
if (tlock->off == rec->next) { if (tlock->off == rec->next) {
tdb->ecode = TDB1_ERR_CORRUPT; tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "tdb1_next_lock: loop detected.\n")); TDB_LOG_ERROR,
"tdb1_next_lock:"
" loop detected.");
goto fail; goto fail;
} }
...@@ -125,13 +127,14 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_ ...@@ -125,13 +127,14 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
want_next = 0; want_next = 0;
} }
/* We finished iteration without finding anything */ /* We finished iteration without finding anything */
tdb->ecode = TDB1_SUCCESS; tdb->last_error = TDB_SUCCESS;
return 0; return 0;
fail: fail:
tlock->off = 0; tlock->off = 0;
if (tdb1_unlock(tdb, tlock->hash, tlock->lock_rw) != 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; return TDB1_NEXT_LOCK_ERR;
} }
...@@ -172,7 +175,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb, ...@@ -172,7 +175,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
if (tdb1_unlock(tdb, tl->hash, tl->lock_rw) != 0) if (tdb1_unlock(tdb, tl->hash, tl->lock_rw) != 0)
goto out; goto out;
if (tdb1_unlock_record(tdb, tl->off) != 0) 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; goto out;
} }
key.dsize = rec.key_len; key.dsize = rec.key_len;
...@@ -188,7 +193,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb, ...@@ -188,7 +193,9 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
if (fn && fn(tdb, key, dbuf, private_data)) { if (fn && fn(tdb, key, dbuf, private_data)) {
/* They want us to terminate traversal */ /* They want us to terminate traversal */
if (tdb1_unlock_record(tdb, tl->off) != 0) { 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; ret = -1;
} }
SAFE_FREE(key.dptr); SAFE_FREE(key.dptr);
...@@ -284,7 +291,9 @@ TDB1_DATA tdb1_firstkey(struct tdb1_context *tdb) ...@@ -284,7 +291,9 @@ TDB1_DATA tdb1_firstkey(struct tdb1_context *tdb)
/* Unlock the hash chain of the record we just read. */ /* Unlock the hash chain of the record we just read. */
if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) 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; return key;
} }
...@@ -328,7 +337,9 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey) ...@@ -328,7 +337,9 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey)
} }
tdb->travlocks.hash = TDB1_BUCKET(rec.full_hash); tdb->travlocks.hash = TDB1_BUCKET(rec.full_hash);
if (tdb1_lock_record(tdb, tdb->travlocks.off) != 0) { 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; return tdb1_null;
} }
} }
...@@ -343,10 +354,12 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey) ...@@ -343,10 +354,12 @@ TDB1_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB1_DATA oldkey)
key.dsize); key.dsize);
/* Unlock the chain of this new record */ /* Unlock the chain of this new record */
if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) 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 */ /* Unlock the chain of old record */
if (tdb1_unlock(tdb, TDB1_BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) 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; return key;
} }
...@@ -11,7 +11,7 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb, ...@@ -11,7 +11,7 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
tdb1_off_t addition) tdb1_off_t addition)
{ {
if (tdb->read_only || tdb->traverse_read) { if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB1_ERR_RDONLY; tdb->last_error = TDB_ERR_RDONLY;
return -1; return -1;
} }
...@@ -27,8 +27,10 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb, ...@@ -27,8 +27,10 @@ static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
errno = ENOSPC; errno = ENOSPC;
} }
if (written != 1) { if (written != 1) {
TDB1_LOG((tdb, TDB1_DEBUG_FATAL, "expand_file to %d failed (%s)\n", tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
size+addition, strerror(errno))); "expand_file to %d failed (%s)",
size+addition,
strerror(errno));
return -1; return -1;
} }
} }
......
...@@ -35,7 +35,7 @@ int main(int argc, char *argv[]) ...@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
&taplogctx, NULL); &taplogctx, NULL);
ok1(tdb); ok1(tdb);
ok1(tdb1_check(tdb, NULL, NULL) == -1); ok1(tdb1_check(tdb, NULL, NULL) == -1);
ok1(tdb1_error(tdb) == TDB1_ERR_CORRUPT); ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
tdb1_close(tdb); tdb1_close(tdb);
/* Big and little endian should work! */ /* Big and little endian should work! */
......
...@@ -21,10 +21,10 @@ int main(int argc, char *argv[]) ...@@ -21,10 +21,10 @@ int main(int argc, char *argv[])
data.dptr = (void *)"world"; data.dptr = (void *)"world";
ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) < 0); 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_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); ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == 0);
data = tdb1_fetch(tdb, key); data = tdb1_fetch(tdb, key);
......
...@@ -8,10 +8,11 @@ static unsigned int tdb1_dumb_hash(TDB1_DATA *key) ...@@ -8,10 +8,11 @@ static unsigned int tdb1_dumb_hash(TDB1_DATA *key)
return key->dsize; 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; unsigned int *count = priv;
if (strstr(fmt, "hash")) if (strstr(message, "hash"))
(*count)++; (*count)++;
} }
......
...@@ -28,7 +28,7 @@ int main(int argc, char *argv[]) ...@@ -28,7 +28,7 @@ int main(int argc, char *argv[])
ok1(memcmp(data.dptr, "world", strlen("world")) == 0); ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
free(data.dptr); free(data.dptr);
ok1(tdb1_transaction_start(tdb) != 0); 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); data = tdb1_fetch(tdb, key);
ok1(data.dsize == strlen("world")); ok1(data.dsize == strlen("world"));
......
...@@ -35,7 +35,7 @@ int main(int argc, char *argv[]) ...@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
ok1(tdb); ok1(tdb);
ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == -1); 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_check(tdb, NULL, NULL) == 0);
ok1(tdb1_close(tdb) == 0); ok1(tdb1_close(tdb) == 0);
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <err.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; unsigned int *count = priv;
if (strstr(fmt, "spinlocks")) if (strstr(message, "spinlocks"))
(*count)++; (*count)++;
} }
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <err.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; unsigned int *count = priv;
if (strstr(fmt, "hash")) if (strstr(message, "hash"))
(*count)++; (*count)++;
} }
......
...@@ -20,10 +20,10 @@ int main(int argc, char *argv[]) ...@@ -20,10 +20,10 @@ int main(int argc, char *argv[])
data.dptr = (void *)"world"; data.dptr = (void *)"world";
ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) < 0); 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_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); ok1(tdb1_store(tdb, key, data, TDB1_MODIFY) == 0);
data = tdb1_fetch(tdb, key); data = tdb1_fetch(tdb, key);
......
...@@ -61,7 +61,7 @@ static enum agent_return do_operation(enum operation op, const char *name) ...@@ -61,7 +61,7 @@ static enum agent_return do_operation(enum operation op, const char *name)
case FETCH: case FETCH:
data = tdb1_fetch(tdb, k); data = tdb1_fetch(tdb, k);
if (data.dptr == NULL) { if (data.dptr == NULL) {
if (tdb->ecode == TDB1_ERR_NOEXIST) if (tdb->last_error == TDB_ERR_NOEXIST)
ret = FAILED; ret = FAILED;
else else
ret = OTHER_FAILURE; ret = OTHER_FAILURE;
......
...@@ -7,24 +7,19 @@ ...@@ -7,24 +7,19 @@
/* Turn log messages into tap diag messages. */ /* Turn log messages into tap diag messages. */
static void taplog(struct tdb1_context *tdb, static void taplog(struct tdb1_context *tdb,
enum tdb1_debug_level level, enum tdb_log_level level,
const char *fmt, ...) enum TDB_ERROR ecode,
const char *message,
void *data)
{ {
va_list ap;
char line[200];
if (suppress_logging) if (suppress_logging)
return; return;
va_start(ap, fmt);
vsprintf(line, fmt, ap);
va_end(ap);
/* Strip trailing \n: diag adds it. */ /* Strip trailing \n: diag adds it. */
if (line[0] && line[strlen(line)-1] == '\n') if (message[0] && message[strlen(message)-1] == '\n')
diag("%s%.*s", log_prefix, (unsigned)strlen(line)-1, line); diag("%s%.*s", log_prefix, (unsigned)strlen(message)-1, message);
else else
diag("%s%s", log_prefix, line); diag("%s%s", log_prefix, message);
} }
struct tdb1_logging_context taplogctx = { taplog, NULL }; struct tdb1_logging_context taplogctx = { taplog, NULL };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment