Commit f6067e4c authored by Rusty Russell's avatar Rusty Russell

tdb2: tdb_error()

This makes transition from tdb1 much simpler.
parent 8d8de08d
...@@ -765,13 +765,13 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb, ...@@ -765,13 +765,13 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb,
ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
return ecode; return tdb->last_error = ecode;
} }
ecode = tdb_lock_expand(tdb, F_RDLCK); ecode = tdb_lock_expand(tdb, F_RDLCK);
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
tdb_allrecord_unlock(tdb, F_RDLCK); tdb_allrecord_unlock(tdb, F_RDLCK);
return ecode; return tdb->last_error = ecode;
} }
ecode = check_header(tdb, &recovery, &features); ecode = check_header(tdb, &recovery, &features);
...@@ -812,5 +812,5 @@ out: ...@@ -812,5 +812,5 @@ out:
tdb_unlock_expand(tdb, F_RDLCK); tdb_unlock_expand(tdb, F_RDLCK);
free(fr); free(fr);
free(used); free(used);
return ecode; return tdb->last_error = ecode;
} }
...@@ -857,7 +857,8 @@ static enum TDB_ERROR chainlock(struct tdb_context *tdb, const TDB_DATA *key, ...@@ -857,7 +857,8 @@ static enum TDB_ERROR chainlock(struct tdb_context *tdb, const TDB_DATA *key,
contention - it cannot guarantee how many records will be locked */ contention - it cannot guarantee how many records will be locked */
enum TDB_ERROR tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) enum TDB_ERROR tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
{ {
return chainlock(tdb, &key, F_WRLCK, TDB_LOCK_WAIT, "tdb_chainlock"); return tdb->last_error = chainlock(tdb, &key, F_WRLCK, TDB_LOCK_WAIT,
"tdb_chainlock");
} }
enum TDB_ERROR tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) enum TDB_ERROR tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
...@@ -872,5 +873,6 @@ enum TDB_ERROR tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) ...@@ -872,5 +873,6 @@ enum TDB_ERROR tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
lockstart = hlock_range(group, &locksize); lockstart = hlock_range(group, &locksize);
tdb_trace_1rec(tdb, "tdb_chainunlock", key); tdb_trace_1rec(tdb, "tdb_chainunlock", key);
return tdb_unlock_hashes(tdb, lockstart, locksize, F_WRLCK); return tdb->last_error = tdb_unlock_hashes(tdb, lockstart, locksize,
F_WRLCK);
} }
...@@ -209,6 +209,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, ...@@ -209,6 +209,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
tdb->transaction = NULL; tdb->transaction = NULL;
tdb->stats = NULL; tdb->stats = NULL;
tdb->access = NULL; tdb->access = NULL;
tdb->last_error = TDB_SUCCESS;
tdb->file = NULL; tdb->file = NULL;
tdb_hash_init(tdb); tdb_hash_init(tdb);
tdb_io_init(tdb); tdb_io_init(tdb);
......
...@@ -390,6 +390,9 @@ struct tdb_context { ...@@ -390,6 +390,9 @@ 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;
}; };
......
...@@ -169,13 +169,13 @@ enum TDB_ERROR tdb_summary(struct tdb_context *tdb, ...@@ -169,13 +169,13 @@ enum TDB_ERROR tdb_summary(struct tdb_context *tdb,
ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
return ecode; return tdb->last_error = ecode;
} }
ecode = tdb_lock_expand(tdb, F_RDLCK); ecode = tdb_lock_expand(tdb, F_RDLCK);
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
tdb_allrecord_unlock(tdb, F_RDLCK); tdb_allrecord_unlock(tdb, F_RDLCK);
return ecode; return tdb->last_error = ecode;
} }
/* Start stats off empty. */ /* Start stats off empty. */
...@@ -289,5 +289,5 @@ unlock: ...@@ -289,5 +289,5 @@ unlock:
tdb_allrecord_unlock(tdb, F_RDLCK); tdb_allrecord_unlock(tdb, F_RDLCK);
tdb_unlock_expand(tdb, F_RDLCK); tdb_unlock_expand(tdb, F_RDLCK);
return ecode; return tdb->last_error = ecode;
} }
...@@ -98,7 +98,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, ...@@ -98,7 +98,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb,
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
return off; return tdb->last_error = off;
} }
/* Now we have lock on this hash bucket. */ /* Now we have lock on this hash bucket. */
...@@ -128,7 +128,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, ...@@ -128,7 +128,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb,
} }
tdb_unlock_hashes(tdb, h.hlock_start, tdb_unlock_hashes(tdb, h.hlock_start,
h.hlock_range, F_WRLCK); h.hlock_range, F_WRLCK);
return TDB_SUCCESS; return tdb->last_error = TDB_SUCCESS;
} }
} else { } else {
if (flag == TDB_MODIFY) { if (flag == TDB_MODIFY) {
...@@ -145,7 +145,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, ...@@ -145,7 +145,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb,
ecode = replace_data(tdb, &h, key, dbuf, off, old_room, off); ecode = replace_data(tdb, &h, key, dbuf, off, old_room, off);
out: out:
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
return ecode; return tdb->last_error = ecode;
} }
enum TDB_ERROR tdb_append(struct tdb_context *tdb, enum TDB_ERROR tdb_append(struct tdb_context *tdb,
...@@ -161,7 +161,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb, ...@@ -161,7 +161,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb,
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
return off; return tdb->last_error = off;
} }
if (off) { if (off) {
...@@ -213,7 +213,7 @@ out_free_newdata: ...@@ -213,7 +213,7 @@ out_free_newdata:
free(newdata); free(newdata);
out: out:
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
return ecode; return tdb->last_error = ecode;
} }
enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key, enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key,
...@@ -226,7 +226,7 @@ enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key, ...@@ -226,7 +226,7 @@ enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key,
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
return off; return tdb->last_error = off;
} }
if (!off) { if (!off) {
...@@ -242,7 +242,7 @@ enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key, ...@@ -242,7 +242,7 @@ enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key,
} }
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
return ecode; return tdb->last_error = ecode;
} }
bool tdb_exists(struct tdb_context *tdb, TDB_DATA key) bool tdb_exists(struct tdb_context *tdb, TDB_DATA key)
...@@ -253,10 +253,12 @@ bool tdb_exists(struct tdb_context *tdb, TDB_DATA key) ...@@ -253,10 +253,12 @@ bool tdb_exists(struct tdb_context *tdb, TDB_DATA key)
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
tdb->last_error = off;
return false; return false;
} }
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
tdb->last_error = TDB_SUCCESS;
return off ? true : false; return off ? true : false;
} }
...@@ -269,7 +271,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key) ...@@ -269,7 +271,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key)
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
return off; return tdb->last_error = off;
} }
if (!off) { if (!off) {
...@@ -295,7 +297,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key) ...@@ -295,7 +297,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key)
unlock: unlock:
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
return ecode; return tdb->last_error = ecode;
} }
unsigned int tdb_get_flags(struct tdb_context *tdb) unsigned int tdb_get_flags(struct tdb_context *tdb)
...@@ -306,8 +308,9 @@ unsigned int tdb_get_flags(struct tdb_context *tdb) ...@@ -306,8 +308,9 @@ unsigned int tdb_get_flags(struct tdb_context *tdb)
void tdb_add_flag(struct tdb_context *tdb, unsigned flag) void tdb_add_flag(struct tdb_context *tdb, unsigned flag)
{ {
if (tdb->flags & TDB_INTERNAL) { if (tdb->flags & TDB_INTERNAL) {
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_add_flag: internal db"); TDB_LOG_USE_ERROR,
"tdb_add_flag: internal db");
return; return;
} }
switch (flag) { switch (flag) {
...@@ -325,16 +328,19 @@ void tdb_add_flag(struct tdb_context *tdb, unsigned flag) ...@@ -325,16 +328,19 @@ void tdb_add_flag(struct tdb_context *tdb, unsigned flag)
tdb->flags |= TDB_SEQNUM; tdb->flags |= TDB_SEQNUM;
break; break;
default: default:
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_add_flag: Unknown flag %u", flag); TDB_LOG_USE_ERROR,
"tdb_add_flag: Unknown flag %u",
flag);
} }
} }
void tdb_remove_flag(struct tdb_context *tdb, unsigned flag) void tdb_remove_flag(struct tdb_context *tdb, unsigned flag)
{ {
if (tdb->flags & TDB_INTERNAL) { if (tdb->flags & TDB_INTERNAL) {
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_remove_flag: internal db"); TDB_LOG_USE_ERROR,
"tdb_remove_flag: internal db");
return; return;
} }
switch (flag) { switch (flag) {
...@@ -352,8 +358,10 @@ void tdb_remove_flag(struct tdb_context *tdb, unsigned flag) ...@@ -352,8 +358,10 @@ void tdb_remove_flag(struct tdb_context *tdb, unsigned flag)
tdb->flags &= ~TDB_SEQNUM; tdb->flags &= ~TDB_SEQNUM;
break; break;
default: default:
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_remove_flag: Unknown flag %u", flag); TDB_LOG_USE_ERROR,
"tdb_remove_flag: Unknown flag %u",
flag);
} }
} }
...@@ -419,7 +427,7 @@ enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb, ...@@ -419,7 +427,7 @@ enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb,
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) { if (TDB_OFF_IS_ERR(off)) {
return off; return tdb->last_error = off;
} }
if (!off) { if (!off) {
...@@ -439,7 +447,7 @@ enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb, ...@@ -439,7 +447,7 @@ enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb,
} }
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
return ecode; return tdb->last_error = ecode;
} }
const char *tdb_name(const struct tdb_context *tdb) const char *tdb_name(const struct tdb_context *tdb)
...@@ -449,7 +457,12 @@ const char *tdb_name(const struct tdb_context *tdb) ...@@ -449,7 +457,12 @@ const char *tdb_name(const struct tdb_context *tdb)
int64_t tdb_get_seqnum(struct tdb_context *tdb) int64_t tdb_get_seqnum(struct tdb_context *tdb)
{ {
return tdb_read_off(tdb, offsetof(struct tdb_header, seqnum)); tdb_off_t off = tdb_read_off(tdb, offsetof(struct tdb_header, seqnum));
if (TDB_OFF_IS_ERR(off))
tdb->last_error = off;
else
tdb->last_error = TDB_SUCCESS;
return off;
} }
......
...@@ -430,6 +430,17 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb, ...@@ -430,6 +430,17 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb,
void *private), void *private),
void *private); void *private);
/**
* tdb_error - get the last error (not threadsafe)
* @tdb: the tdb context returned from tdb_open()
*
* Returns the last error returned by a TDB function.
*
* This makes porting from TDB1 easier, but note that the last error is not
* reliable in threaded programs.
*/
enum TDB_ERROR tdb_error(struct tdb_context *tdb);
/** /**
* enum tdb_summary_flags - flags for tdb_summary. * enum tdb_summary_flags - flags for tdb_summary.
*/ */
......
...@@ -519,32 +519,42 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb) ...@@ -519,32 +519,42 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
/* some sanity checks */ /* some sanity checks */
if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) { if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) {
return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_transaction_start: cannot start a" TDB_LOG_USE_ERROR,
" transaction on a read-only or internal db"); "tdb_transaction_start:"
" cannot start a"
" transaction on a "
"read-only or internal db");
} }
/* cope with nested tdb_transaction_start() calls */ /* cope with nested tdb_transaction_start() calls */
if (tdb->transaction != NULL) { if (tdb->transaction != NULL) {
return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_USE_ERROR, return tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO,
"tdb_transaction_start:" TDB_LOG_USE_ERROR,
" already inside transaction"); "tdb_transaction_start:"
" already inside"
" transaction");
} }
if (tdb_has_hash_locks(tdb)) { if (tdb_has_hash_locks(tdb)) {
/* the caller must not have any locks when starting a /* the caller must not have any locks when starting a
transaction as otherwise we'll be screwed by lack transaction as otherwise we'll be screwed by lack
of nested locks in POSIX */ of nested locks in POSIX */
return tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_USE_ERROR, return tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK,
"tdb_transaction_start: cannot start a" TDB_LOG_USE_ERROR,
" transaction with locks held"); "tdb_transaction_start:"
" cannot start a"
" transaction with locks"
" held");
} }
tdb->transaction = (struct tdb_transaction *) tdb->transaction = (struct tdb_transaction *)
calloc(sizeof(struct tdb_transaction), 1); calloc(sizeof(struct tdb_transaction), 1);
if (tdb->transaction == NULL) { if (tdb->transaction == NULL) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, return tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM,
"tdb_transaction_start: cannot allocate"); TDB_LOG_ERROR,
"tdb_transaction_start:"
" cannot allocate");
} }
/* get the transaction write lock. This is a blocking lock. As /* get the transaction write lock. This is a blocking lock. As
...@@ -554,7 +564,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb) ...@@ -554,7 +564,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
SAFE_FREE(tdb->transaction->blocks); SAFE_FREE(tdb->transaction->blocks);
SAFE_FREE(tdb->transaction); SAFE_FREE(tdb->transaction);
return ecode; return tdb->last_error = ecode;
} }
/* get a read lock over entire file. This is upgraded to a write /* get a read lock over entire file. This is upgraded to a write
...@@ -573,13 +583,13 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb) ...@@ -573,13 +583,13 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
transaction specific methods */ transaction specific methods */
tdb->transaction->io_methods = tdb->methods; tdb->transaction->io_methods = tdb->methods;
tdb->methods = &transaction_methods; tdb->methods = &transaction_methods;
return TDB_SUCCESS; return tdb->last_error = TDB_SUCCESS;
fail_allrecord_lock: fail_allrecord_lock:
tdb_transaction_unlock(tdb, F_WRLCK); tdb_transaction_unlock(tdb, F_WRLCK);
SAFE_FREE(tdb->transaction->blocks); SAFE_FREE(tdb->transaction->blocks);
SAFE_FREE(tdb->transaction); SAFE_FREE(tdb->transaction);
return ecode; return tdb->last_error = ecode;
} }
...@@ -983,27 +993,29 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) ...@@ -983,27 +993,29 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
enum TDB_ERROR ecode; enum TDB_ERROR ecode;
if (tdb->transaction == NULL) { if (tdb->transaction == NULL) {
return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
"tdb_transaction_commit: no transaction"); TDB_LOG_USE_ERROR,
"tdb_transaction_commit:"
" no transaction");
} }
tdb_trace(tdb, "tdb_transaction_commit"); tdb_trace(tdb, "tdb_transaction_commit");
if (tdb->transaction->nesting != 0) { if (tdb->transaction->nesting != 0) {
tdb->transaction->nesting--; tdb->transaction->nesting--;
return TDB_SUCCESS; return tdb->last_error = TDB_SUCCESS;
} }
/* check for a null transaction */ /* check for a null transaction */
if (tdb->transaction->blocks == NULL) { if (tdb->transaction->blocks == NULL) {
_tdb_transaction_cancel(tdb); _tdb_transaction_cancel(tdb);
return TDB_SUCCESS; return tdb->last_error = TDB_SUCCESS;
} }
if (!tdb->transaction->prepared) { if (!tdb->transaction->prepared) {
ecode = _tdb_transaction_prepare_commit(tdb); ecode = _tdb_transaction_prepare_commit(tdb);
if (ecode != TDB_SUCCESS) if (ecode != TDB_SUCCESS)
return ecode; return tdb->last_error = ecode;
} }
methods = tdb->transaction->io_methods; methods = tdb->transaction->io_methods;
...@@ -1038,7 +1050,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) ...@@ -1038,7 +1050,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
_tdb_transaction_cancel(tdb); _tdb_transaction_cancel(tdb);
return ecode; return tdb->last_error = ecode;
} }
SAFE_FREE(tdb->transaction->blocks[i]); SAFE_FREE(tdb->transaction->blocks[i]);
} }
...@@ -1049,7 +1061,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) ...@@ -1049,7 +1061,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
/* ensure the new data is on disk */ /* ensure the new data is on disk */
ecode = transaction_sync(tdb, 0, tdb->file->map_size); ecode = transaction_sync(tdb, 0, tdb->file->map_size);
if (ecode != TDB_SUCCESS) { if (ecode != TDB_SUCCESS) {
return ecode; return tdb->last_error = ecode;
} }
/* /*
...@@ -1071,7 +1083,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) ...@@ -1071,7 +1083,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
transaction locks */ transaction locks */
_tdb_transaction_cancel(tdb); _tdb_transaction_cancel(tdb);
return TDB_SUCCESS; return tdb->last_error = TDB_SUCCESS;
} }
......
...@@ -37,14 +37,16 @@ int64_t tdb_traverse_(struct tdb_context *tdb, ...@@ -37,14 +37,16 @@ int64_t tdb_traverse_(struct tdb_context *tdb,
count++; count++;
if (fn && fn(tdb, k, d, p)) { if (fn && fn(tdb, k, d, p)) {
free(k.dptr); free(k.dptr);
tdb->last_error = TDB_SUCCESS;
return count; return count;
} }
free(k.dptr); free(k.dptr);
} }
if (ecode != TDB_ERR_NOEXIST) { if (ecode != TDB_ERR_NOEXIST) {
return ecode; return tdb->last_error = ecode;
} }
tdb->last_error = TDB_SUCCESS;
return count; return count;
} }
...@@ -52,7 +54,7 @@ enum TDB_ERROR tdb_firstkey(struct tdb_context *tdb, struct tdb_data *key) ...@@ -52,7 +54,7 @@ enum TDB_ERROR tdb_firstkey(struct tdb_context *tdb, struct tdb_data *key)
{ {
struct traverse_info tinfo; struct traverse_info tinfo;
return first_in_hash(tdb, &tinfo, key, NULL); return tdb->last_error = first_in_hash(tdb, &tinfo, key, NULL);
} }
/* We lock twice, not very efficient. We could keep last key & tinfo cached. */ /* We lock twice, not very efficient. We could keep last key & tinfo cached. */
...@@ -65,11 +67,11 @@ enum TDB_ERROR tdb_nextkey(struct tdb_context *tdb, struct tdb_data *key) ...@@ -65,11 +67,11 @@ enum TDB_ERROR tdb_nextkey(struct tdb_context *tdb, struct tdb_data *key)
tinfo.prev = find_and_lock(tdb, *key, F_RDLCK, &h, &rec, &tinfo); tinfo.prev = find_and_lock(tdb, *key, F_RDLCK, &h, &rec, &tinfo);
free(key->dptr); free(key->dptr);
if (TDB_OFF_IS_ERR(tinfo.prev)) { if (TDB_OFF_IS_ERR(tinfo.prev)) {
return tinfo.prev; return tdb->last_error = tinfo.prev;
} }
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
return next_in_hash(tdb, &tinfo, key, NULL); return tdb->last_error = next_in_hash(tdb, &tinfo, key, NULL);
} }
static int wipe_one(struct tdb_context *tdb, static int wipe_one(struct tdb_context *tdb,
...@@ -86,12 +88,12 @@ enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb) ...@@ -86,12 +88,12 @@ enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb)
ecode = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false); ecode = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false);
if (ecode != TDB_SUCCESS) if (ecode != TDB_SUCCESS)
return ecode; return tdb->last_error = ecode;
/* FIXME: Be smarter. */ /* FIXME: Be smarter. */
count = tdb_traverse(tdb, wipe_one, &ecode); count = tdb_traverse(tdb, wipe_one, &ecode);
if (count < 0) if (count < 0)
ecode = count; ecode = count;
tdb_allrecord_unlock(tdb, F_WRLCK); tdb_allrecord_unlock(tdb, F_WRLCK);
return ecode; return tdb->last_error = ecode;
} }
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