From f6067e4cbd7b7415571f12438aec00faec5657fb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 17 Mar 2011 22:12:20 +1030 Subject: [PATCH] tdb2: tdb_error() This makes transition from tdb1 much simpler. --- ccan/tdb2/check.c | 6 ++--- ccan/tdb2/hash.c | 6 +++-- ccan/tdb2/open.c | 1 + ccan/tdb2/private.h | 3 +++ ccan/tdb2/summary.c | 6 ++--- ccan/tdb2/tdb.c | 53 +++++++++++++++++++++++--------------- ccan/tdb2/tdb2.h | 11 ++++++++ ccan/tdb2/transaction.c | 56 +++++++++++++++++++++++++---------------- ccan/tdb2/traverse.c | 14 ++++++----- 9 files changed, 100 insertions(+), 56 deletions(-) diff --git a/ccan/tdb2/check.c b/ccan/tdb2/check.c index 077fa856..b44ae42a 100644 --- a/ccan/tdb2/check.c +++ b/ccan/tdb2/check.c @@ -765,13 +765,13 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb, ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); if (ecode != TDB_SUCCESS) { - return ecode; + return tdb->last_error = ecode; } ecode = tdb_lock_expand(tdb, F_RDLCK); if (ecode != TDB_SUCCESS) { tdb_allrecord_unlock(tdb, F_RDLCK); - return ecode; + return tdb->last_error = ecode; } ecode = check_header(tdb, &recovery, &features); @@ -812,5 +812,5 @@ out: tdb_unlock_expand(tdb, F_RDLCK); free(fr); free(used); - return ecode; + return tdb->last_error = ecode; } diff --git a/ccan/tdb2/hash.c b/ccan/tdb2/hash.c index 9ebc1fe2..3db1ac2e 100644 --- a/ccan/tdb2/hash.c +++ b/ccan/tdb2/hash.c @@ -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 */ 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) @@ -872,5 +873,6 @@ enum TDB_ERROR tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) lockstart = hlock_range(group, &locksize); 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); } diff --git a/ccan/tdb2/open.c b/ccan/tdb2/open.c index f2d23aed..9aaa218a 100644 --- a/ccan/tdb2/open.c +++ b/ccan/tdb2/open.c @@ -209,6 +209,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, tdb->transaction = NULL; tdb->stats = NULL; tdb->access = NULL; + tdb->last_error = TDB_SUCCESS; tdb->file = NULL; tdb_hash_init(tdb); tdb_io_init(tdb); diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index 030b46ca..63354a43 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -390,6 +390,9 @@ struct tdb_context { /* Direct access information */ struct tdb_access_hdr *access; + /* Last error we returned. */ + enum TDB_ERROR last_error; + /* The actual file information */ struct tdb_file *file; }; diff --git a/ccan/tdb2/summary.c b/ccan/tdb2/summary.c index 3b883dd3..a369f30e 100644 --- a/ccan/tdb2/summary.c +++ b/ccan/tdb2/summary.c @@ -169,13 +169,13 @@ enum TDB_ERROR tdb_summary(struct tdb_context *tdb, ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false); if (ecode != TDB_SUCCESS) { - return ecode; + return tdb->last_error = ecode; } ecode = tdb_lock_expand(tdb, F_RDLCK); if (ecode != TDB_SUCCESS) { tdb_allrecord_unlock(tdb, F_RDLCK); - return ecode; + return tdb->last_error = ecode; } /* Start stats off empty. */ @@ -289,5 +289,5 @@ unlock: tdb_allrecord_unlock(tdb, F_RDLCK); tdb_unlock_expand(tdb, F_RDLCK); - return ecode; + return tdb->last_error = ecode; } diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index 569c3d04..254aac5f 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -98,7 +98,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); if (TDB_OFF_IS_ERR(off)) { - return off; + return tdb->last_error = off; } /* Now we have lock on this hash bucket. */ @@ -128,7 +128,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, } tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK); - return TDB_SUCCESS; + return tdb->last_error = TDB_SUCCESS; } } else { if (flag == TDB_MODIFY) { @@ -145,7 +145,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, ecode = replace_data(tdb, &h, key, dbuf, off, old_room, off); out: 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, @@ -161,7 +161,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb, off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); if (TDB_OFF_IS_ERR(off)) { - return off; + return tdb->last_error = off; } if (off) { @@ -213,7 +213,7 @@ out_free_newdata: free(newdata); out: 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, @@ -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); if (TDB_OFF_IS_ERR(off)) { - return off; + return tdb->last_error = off; } if (!off) { @@ -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); - return ecode; + return tdb->last_error = ecode; } 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); if (TDB_OFF_IS_ERR(off)) { + tdb->last_error = off; return false; } tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK); + tdb->last_error = TDB_SUCCESS; return off ? true : false; } @@ -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); if (TDB_OFF_IS_ERR(off)) { - return off; + return tdb->last_error = off; } if (!off) { @@ -295,7 +297,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key) unlock: 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) @@ -306,8 +308,9 @@ unsigned int tdb_get_flags(struct tdb_context *tdb) void tdb_add_flag(struct tdb_context *tdb, unsigned flag) { if (tdb->flags & TDB_INTERNAL) { - tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_add_flag: internal db"); + tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_add_flag: internal db"); return; } switch (flag) { @@ -325,16 +328,19 @@ void tdb_add_flag(struct tdb_context *tdb, unsigned flag) tdb->flags |= TDB_SEQNUM; break; default: - tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_add_flag: Unknown flag %u", flag); + tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_add_flag: Unknown flag %u", + flag); } } void tdb_remove_flag(struct tdb_context *tdb, unsigned flag) { if (tdb->flags & TDB_INTERNAL) { - tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_remove_flag: internal db"); + tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_remove_flag: internal db"); return; } switch (flag) { @@ -352,8 +358,10 @@ void tdb_remove_flag(struct tdb_context *tdb, unsigned flag) tdb->flags &= ~TDB_SEQNUM; break; default: - tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_remove_flag: Unknown flag %u", flag); + tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + 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, off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); if (TDB_OFF_IS_ERR(off)) { - return off; + return tdb->last_error = off; } if (!off) { @@ -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); - return ecode; + return tdb->last_error = ecode; } 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) { - 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; } diff --git a/ccan/tdb2/tdb2.h b/ccan/tdb2/tdb2.h index 0940be1c..4f5be819 100644 --- a/ccan/tdb2/tdb2.h +++ b/ccan/tdb2/tdb2.h @@ -430,6 +430,17 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb, 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. */ diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index 73ab1e39..b80cede7 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -519,32 +519,42 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb) /* some sanity checks */ if (tdb->read_only || (tdb->flags & TDB_INTERNAL)) { - return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_transaction_start: cannot start a" - " transaction on a read-only or internal db"); + return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_transaction_start:" + " cannot start a" + " transaction on a " + "read-only or internal db"); } /* cope with nested tdb_transaction_start() calls */ if (tdb->transaction != NULL) { - return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_USE_ERROR, - "tdb_transaction_start:" - " already inside transaction"); + return tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, + TDB_LOG_USE_ERROR, + "tdb_transaction_start:" + " already inside" + " transaction"); } if (tdb_has_hash_locks(tdb)) { /* the caller must not have any locks when starting a transaction as otherwise we'll be screwed by lack of nested locks in POSIX */ - return tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_USE_ERROR, - "tdb_transaction_start: cannot start a" - " transaction with locks held"); + return tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, + TDB_LOG_USE_ERROR, + "tdb_transaction_start:" + " cannot start a" + " transaction with locks" + " held"); } tdb->transaction = (struct tdb_transaction *) calloc(sizeof(struct tdb_transaction), 1); if (tdb->transaction == NULL) { - return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, - "tdb_transaction_start: cannot allocate"); + return tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, + TDB_LOG_ERROR, + "tdb_transaction_start:" + " cannot allocate"); } /* 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) if (ecode != TDB_SUCCESS) { SAFE_FREE(tdb->transaction->blocks); SAFE_FREE(tdb->transaction); - return ecode; + return tdb->last_error = ecode; } /* 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) transaction specific methods */ tdb->transaction->io_methods = tdb->methods; tdb->methods = &transaction_methods; - return TDB_SUCCESS; + return tdb->last_error = TDB_SUCCESS; fail_allrecord_lock: tdb_transaction_unlock(tdb, F_WRLCK); SAFE_FREE(tdb->transaction->blocks); 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) enum TDB_ERROR ecode; if (tdb->transaction == NULL) { - return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, - "tdb_transaction_commit: no transaction"); + return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, + TDB_LOG_USE_ERROR, + "tdb_transaction_commit:" + " no transaction"); } tdb_trace(tdb, "tdb_transaction_commit"); if (tdb->transaction->nesting != 0) { tdb->transaction->nesting--; - return TDB_SUCCESS; + return tdb->last_error = TDB_SUCCESS; } /* check for a null transaction */ if (tdb->transaction->blocks == NULL) { _tdb_transaction_cancel(tdb); - return TDB_SUCCESS; + return tdb->last_error = TDB_SUCCESS; } if (!tdb->transaction->prepared) { ecode = _tdb_transaction_prepare_commit(tdb); if (ecode != TDB_SUCCESS) - return ecode; + return tdb->last_error = ecode; } methods = tdb->transaction->io_methods; @@ -1038,7 +1050,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) _tdb_transaction_cancel(tdb); - return ecode; + return tdb->last_error = ecode; } SAFE_FREE(tdb->transaction->blocks[i]); } @@ -1049,7 +1061,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) /* ensure the new data is on disk */ ecode = transaction_sync(tdb, 0, tdb->file->map_size); 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) transaction locks */ _tdb_transaction_cancel(tdb); - return TDB_SUCCESS; + return tdb->last_error = TDB_SUCCESS; } diff --git a/ccan/tdb2/traverse.c b/ccan/tdb2/traverse.c index 71a889e5..f8a2504d 100644 --- a/ccan/tdb2/traverse.c +++ b/ccan/tdb2/traverse.c @@ -37,14 +37,16 @@ int64_t tdb_traverse_(struct tdb_context *tdb, count++; if (fn && fn(tdb, k, d, p)) { free(k.dptr); + tdb->last_error = TDB_SUCCESS; return count; } free(k.dptr); } if (ecode != TDB_ERR_NOEXIST) { - return ecode; + return tdb->last_error = ecode; } + tdb->last_error = TDB_SUCCESS; return count; } @@ -52,7 +54,7 @@ enum TDB_ERROR tdb_firstkey(struct tdb_context *tdb, struct tdb_data *key) { 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. */ @@ -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); free(key->dptr); 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); - 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, @@ -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); if (ecode != TDB_SUCCESS) - return ecode; + return tdb->last_error = ecode; /* FIXME: Be smarter. */ count = tdb_traverse(tdb, wipe_one, &ecode); if (count < 0) ecode = count; tdb_allrecord_unlock(tdb, F_WRLCK); - return ecode; + return tdb->last_error = ecode; } -- 2.39.2