X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftdb2%2Ftransaction.c;h=a27c027365eec3fc7be001d9693bde42ec6f0b45;hb=a8b30ad4dcea31c68ca809d2a6e6e4c7c6c30398;hp=29192beece4e3e48f0a6a337c677af2e14c0de63;hpb=b556ef1fc167e1010b07df5ebd75d808cc30f970;p=ccan diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index 29192bee..a27c0273 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -110,7 +110,7 @@ struct tdb_transaction { /* when inside a transaction we need to keep track of any nested tdb_transaction_start() calls, as these are allowed, but don't create a new transaction */ - int nesting; + unsigned int nesting; /* set when a prepare has already occurred */ bool prepared; @@ -531,11 +531,15 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb) /* cope with nested tdb_transaction_start() calls */ if (tdb->transaction != NULL) { - return tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, - TDB_LOG_USE_ERROR, - "tdb_transaction_start:" - " already inside" - " transaction"); + if (!(tdb->flags & TDB_ALLOW_NESTING)) { + return tdb->last_error + = tdb_logerr(tdb, TDB_ERR_IO, + TDB_LOG_USE_ERROR, + "tdb_transaction_start:" + " already inside transaction"); + } + tdb->transaction->nesting++; + return 0; } if (tdb_has_hash_locks(tdb)) { @@ -682,9 +686,10 @@ static enum TDB_ERROR tdb_recovery_allocate(struct tdb_context *tdb, us an area that is being currently used (as of the start of the transaction) */ if (recovery_head != 0) { - add_stat(tdb, frees, 1); + tdb->stats.frees++; ecode = add_free_record(tdb, recovery_head, - sizeof(rec) + rec.max_len); + sizeof(rec) + rec.max_len, + TDB_LOCK_WAIT); if (ecode != TDB_SUCCESS) { return tdb_logerr(tdb, ecode, TDB_LOG_ERROR, "tdb_recovery_allocate:" @@ -696,10 +701,11 @@ static enum TDB_ERROR tdb_recovery_allocate(struct tdb_context *tdb, /* the tdb_free() call might have increased the recovery size */ *recovery_size = tdb_recovery_size(tdb); - /* round up to a multiple of page size */ + /* round up to a multiple of page size. Overallocate, since each + * such allocation forces us to expand the file. */ *recovery_max_size - = (((sizeof(rec) + *recovery_size) + PAGESIZE-1) - & ~(PAGESIZE-1)) + = (((sizeof(rec) + *recovery_size + *recovery_size / 2) + + PAGESIZE-1) & ~(PAGESIZE-1)) - sizeof(rec); *recovery_offset = tdb->file->map_size; recovery_head = *recovery_offset; @@ -907,7 +913,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb) if (tdb->transaction->nesting != 0) { - tdb->transaction->nesting--; return TDB_SUCCESS; } @@ -921,10 +926,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb) /* upgrade the main transaction lock region to a write lock */ ecode = tdb_allrecord_upgrade(tdb); if (ecode != TDB_SUCCESS) { - tdb_logerr(tdb, ecode, TDB_LOG_ERROR, - "tdb_transaction_prepare_commit:" - " failed to upgrade hash locks"); - _tdb_transaction_cancel(tdb); return ecode; } @@ -932,10 +933,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb) during the commit */ ecode = tdb_lock_open(tdb, TDB_LOCK_WAIT|TDB_LOCK_NOCHECK); if (ecode != TDB_SUCCESS) { - tdb_logerr(tdb, ecode, TDB_LOG_ERROR, - "tdb_transaction_prepare_commit:" - " failed to get open lock"); - _tdb_transaction_cancel(tdb); return ecode; } @@ -946,10 +943,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb) &tdb->transaction ->magic_offset); if (ecode != TDB_SUCCESS) { - tdb_logerr(tdb, ecode, TDB_LOG_ERROR, - "tdb_transaction_prepare_commit:" - " failed to setup recovery data"); - _tdb_transaction_cancel(tdb); return ecode; } } @@ -965,10 +958,6 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb) tdb->file->map_size = tdb->transaction->old_map_size; ecode = methods->expand_file(tdb, add); if (ecode != TDB_SUCCESS) { - tdb_logerr(tdb, ecode, TDB_LOG_ERROR, - "tdb_transaction_prepare_commit:" - " expansion failed"); - _tdb_transaction_cancel(tdb); return ecode; } } @@ -1016,8 +1005,10 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) if (!tdb->transaction->prepared) { ecode = _tdb_transaction_prepare_commit(tdb); - if (ecode != TDB_SUCCESS) + if (ecode != TDB_SUCCESS) { + _tdb_transaction_cancel(tdb); return tdb->last_error = ecode; + } } methods = tdb->transaction->io_methods; @@ -1040,10 +1031,6 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb) ecode = methods->twrite(tdb, offset, tdb->transaction->blocks[i], length); if (ecode != TDB_SUCCESS) { - tdb_logerr(tdb, ecode, TDB_LOG_ERROR, - "tdb_transaction_commit:" - " write failed during commit"); - /* we've overwritten part of the data and possibly expanded the file, so we need to run the crash recovery code */