X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;ds=sidebyside;f=ccan%2Ftdb2%2Ftransaction.c;h=66be5bdc8e533cf67c49fddea59e2951ca10e863;hb=a2083afe4b327a542649b719e88178279fb5dc88;hp=ab287bf195ece587611a05e67f6d7de712ad5961;hpb=a56db4a5cbf4346ec8a74322b5267d47b2590ed7;p=ccan diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index ab287bf1..66be5bdc 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -151,7 +151,8 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, if (tdb->transaction->num_blocks <= blk || tdb->transaction->blocks[blk] == NULL) { /* nope, do a real read */ - if (tdb->transaction->io_methods->read(tdb, off, buf, len) != 0) { + if (tdb->transaction->io_methods->tread(tdb, off, buf, len) + != 0) { goto fail; } return 0; @@ -249,9 +250,9 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, if (len2 + (blk * getpagesize()) > tdb->transaction->old_map_size) { len2 = tdb->transaction->old_map_size - (blk * getpagesize()); } - if (tdb->transaction->io_methods->read(tdb, blk * getpagesize(), - tdb->transaction->blocks[blk], - len2) != 0) { + if (tdb->transaction->io_methods->tread(tdb, blk * getpagesize(), + tdb->transaction->blocks[blk], + len2) != 0) { tdb_logerr(tdb, TDB_ERR_OOM, TDB_DEBUG_FATAL, "transaction_write: failed to" " read old block: %s", @@ -363,10 +364,39 @@ static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t addition) } static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off, - size_t len, bool write) + size_t len, bool write_mode) { - /* FIXME */ - return NULL; + size_t blk = off / getpagesize(), end_blk; + + /* This is wrong for zero-length blocks, but will fail gracefully */ + end_blk = (off + len - 1) / getpagesize(); + + /* Can only do direct if in single block and we've already copied. */ + if (write_mode) { + if (blk != end_blk) + return NULL; + if (blk >= tdb->transaction->num_blocks) + return NULL; + if (tdb->transaction->blocks[blk] == NULL) + return NULL; + return tdb->transaction->blocks[blk] + off % getpagesize(); + } + + /* Single which we have copied? */ + if (blk == end_blk + && blk < tdb->transaction->num_blocks + && tdb->transaction->blocks[blk]) + return tdb->transaction->blocks[blk] + off % getpagesize(); + + /* Otherwise must be all not copied. */ + while (blk < end_blk) { + if (blk >= tdb->transaction->num_blocks) + break; + if (tdb->transaction->blocks[blk]) + return NULL; + blk++; + } + return tdb->transaction->io_methods->direct(tdb, off, len, false); } static const struct tdb_methods transaction_methods = { @@ -439,8 +469,8 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb) uint64_t invalid = TDB_RECOVERY_INVALID_MAGIC; /* remove the recovery marker */ - if (methods->write(tdb, tdb->transaction->magic_offset, - &invalid, sizeof(invalid)) == -1 || + if (methods->twrite(tdb, tdb->transaction->magic_offset, + &invalid, sizeof(invalid)) == -1 || transaction_sync(tdb, tdb->transaction->magic_offset, sizeof(invalid)) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, @@ -595,7 +625,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, } if (recovery_head != 0) { - if (methods->read(tdb, recovery_head, &rec, sizeof(rec))) { + if (methods->tread(tdb, recovery_head, &rec, sizeof(rec))) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_recovery_allocate:" " failed to read recovery record"); @@ -667,8 +697,8 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, /* write the recovery header offset and sync - we can sync without a race here as the magic ptr in the recovery record has not been set */ tdb_convert(tdb, &recovery_head, sizeof(recovery_head)); - if (methods->write(tdb, offsetof(struct tdb_header, recovery), - &recovery_head, sizeof(tdb_off_t)) == -1) { + if (methods->twrite(tdb, offsetof(struct tdb_header, recovery), + &recovery_head, sizeof(tdb_off_t)) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_recovery_allocate:" " failed to write recovery head"); @@ -761,9 +791,9 @@ static int transaction_setup_recovery(struct tdb_context *tdb, /* the recovery area contains the old data, not the new data, so we have to call the original tdb_read method to get it */ - if (methods->read(tdb, offset, - p + sizeof(offset) + sizeof(length), - length) != 0) { + if (methods->tread(tdb, offset, + p + sizeof(offset) + sizeof(length), + length) != 0) { free(data); return -1; } @@ -776,8 +806,8 @@ static int transaction_setup_recovery(struct tdb_context *tdb, tdb_convert(tdb, p, sizeof(tailer)); /* write the recovery data to the recovery area */ - if (methods->write(tdb, recovery_offset, data, - sizeof(*rec) + recovery_size) == -1) { + if (methods->twrite(tdb, recovery_offset, data, + sizeof(*rec) + recovery_size) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery:" " failed to write recovery data"); @@ -804,7 +834,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, *magic_offset = recovery_offset + offsetof(struct tdb_recovery_record, magic); - if (methods->write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { + if (methods->twrite(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery:" " failed to write recovery magic"); @@ -978,8 +1008,8 @@ int tdb_transaction_commit(struct tdb_context *tdb) length = tdb->transaction->last_block_size; } - if (methods->write(tdb, offset, tdb->transaction->blocks[i], - length) == -1) { + if (methods->twrite(tdb, offset, tdb->transaction->blocks[i], + length) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_transaction_commit:" " write failed during commit"); @@ -1084,8 +1114,8 @@ int tdb_transaction_recover(struct tdb_context *tdb) } /* read the full recovery data */ - if (tdb->methods->read(tdb, recovery_head + sizeof(rec), data, - rec.len) == -1) { + if (tdb->methods->tread(tdb, recovery_head + sizeof(rec), data, + rec.len) == -1) { tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_transaction_recover:" " failed to read recovery data"); @@ -1102,7 +1132,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) memcpy(&len, p + sizeof(ofs), sizeof(len)); p += sizeof(ofs) + sizeof(len); - if (tdb->methods->write(tdb, ofs, p, len) == -1) { + if (tdb->methods->twrite(tdb, ofs, p, len) == -1) { free(data); tdb_logerr(tdb, tdb->ecode, TDB_DEBUG_FATAL, "tdb_transaction_recover:"