- /*
+ /*
Trivial Database 2: free list/block handling
Copyright (C) Rusty Russell 2010
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
#ifdef CCAN_TDB2_DEBUG
if (tdb_read_off(tdb, off) != r_off) {
- tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_DEBUG_FATAL,
+ tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"remove_from_list: %llu bad prev in list %llu",
(long long)r_off, (long long)b_off);
return -1;
#ifdef CCAN_TDB2_DEBUG
if (tdb_read_off(tdb, off) & TDB_OFF_MASK != r_off) {
- tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_DEBUG_FATAL,
+ tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"remove_from_list: %llu bad list %llu",
(long long)r_off, (long long)b_off);
return -1;
new.next + offsetof(struct tdb_free_record,
magic_and_prev))
!= magic) {
- tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_DEBUG_FATAL,
+ tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"enqueue_in_free: %llu bad head"
" prev %llu",
(long long)new.next, (long long)b_off);
tdb_off_t b_off;
tdb_len_t len;
int ret;
+ enum TDB_ERROR ecode;
assert(len_with_header >= sizeof(struct tdb_free_record));
len = len_with_header - sizeof(struct tdb_used_record);
b_off = bucket_off(tdb->ftable_off, size_to_bucket(len));
- if (tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) != 0)
+ ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
+ if (ecode != TDB_SUCCESS) {
+ tdb->ecode = ecode;
return -1;
+ }
ret = enqueue_in_free(tdb, b_off, off, len);
tdb_unlock_free_bucket(tdb, b_off);
tdb_access_release(tdb, r);
/* We may be violating lock order here, so best effort. */
- if (tdb_lock_free_bucket(tdb, nb_off, TDB_LOCK_NOWAIT) == -1) {
+ if (tdb_lock_free_bucket(tdb, nb_off, TDB_LOCK_NOWAIT)
+ != TDB_SUCCESS) {
add_stat(tdb, alloc_coalesce_lockfail, 1);
break;
}
goto err;
if (frec_len(&rec) != data_len) {
- tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_DEBUG_FATAL,
+ tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"coalesce: expected data len %zu not %zu",
(size_t)data_len, (size_t)frec_len(&rec));
goto err;
struct tdb_free_record best = { 0 };
double multiplier;
size_t size = adjust_size(keylen, datalen);
+ enum TDB_ERROR ecode;
add_stat(tdb, allocs, 1);
again:
/* FIXME: Try non-blocking wait first, to measure contention. */
/* Lock this bucket. */
- if (tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == -1) {
+ ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
+ if (ecode != TDB_SUCCESS) {
+ tdb->ecode = ecode;
return TDB_OFF_ERR;
}
if (frec_magic(r) != TDB_FREE_MAGIC) {
tdb_access_release(tdb, r);
- tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_DEBUG_FATAL,
+ tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
"lock_and_alloc: %llu non-free 0x%llx",
(long long)off, (long long)r->magic_and_prev);
goto unlock_err;
if (rec_key_length(rec) != keylen
|| rec_data_length(rec) != datalen
|| rec_extra_padding(rec) != actuallen - (keylen + datalen)) {
- tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR,
+ tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"Could not encode k=%llu,d=%llu,a=%llu",
(long long)keylen, (long long)datalen,
(long long)actuallen);
{
uint64_t old_size;
tdb_len_t wanted;
+ enum TDB_ERROR ecode;
/* We need room for the record header too. */
wanted = sizeof(struct tdb_used_record) + size;
/* Need to hold a hash lock to expand DB: transactions rely on it. */
if (!(tdb->flags & TDB_NOLOCK)
&& !tdb->allrecord_lock.count && !tdb_has_hash_locks(tdb)) {
- tdb_logerr(tdb, TDB_ERR_LOCK, TDB_DEBUG_ERROR,
+ tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
"tdb_expand: must hold lock during expand");
return -1;
}
wanted = adjust_size(0, wanted);
/* Only one person can expand file at a time. */
- if (tdb_lock_expand(tdb, F_WRLCK) != 0)
+ ecode = tdb_lock_expand(tdb, F_WRLCK);
+ if (ecode != TDB_SUCCESS) {
+ tdb->ecode = ecode;
return -1;
+ }
/* Someone else may have expanded the file, so retry. */
old_size = tdb->map_size;