Implemented cache_detach_sub_transaction() - not tested yet, though.
Added and implemented new functions cache_blocks_in_[sub_]transaction(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14431 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6ded062819
commit
ca7c5a9e13
@ -21,11 +21,13 @@ extern int32 cache_start_transaction(void *_cache);
|
|||||||
extern status_t cache_sync_transaction(void *_cache, int32 id);
|
extern status_t cache_sync_transaction(void *_cache, int32 id);
|
||||||
extern status_t cache_end_transaction(void *_cache, int32 id, transaction_notification_hook hook, void *data);
|
extern status_t cache_end_transaction(void *_cache, int32 id, transaction_notification_hook hook, void *data);
|
||||||
extern status_t cache_abort_transaction(void *_cache, int32 id);
|
extern status_t cache_abort_transaction(void *_cache, int32 id);
|
||||||
extern int32 cache_detach_sub_transaction(void *_cache, int32 id);
|
extern int32 cache_detach_sub_transaction(void *_cache, int32 id, transaction_notification_hook hook, void *data);
|
||||||
extern status_t cache_abort_sub_transaction(void *_cache, int32 id);
|
extern status_t cache_abort_sub_transaction(void *_cache, int32 id);
|
||||||
extern status_t cache_start_sub_transaction(void *_cache, int32 id);
|
extern status_t cache_start_sub_transaction(void *_cache, int32 id);
|
||||||
extern status_t cache_next_block_in_transaction(void *_cache, int32 id, uint32 *_cookie,
|
extern status_t cache_next_block_in_transaction(void *_cache, int32 id, uint32 *_cookie,
|
||||||
off_t *_blockNumber, void **_data, void **_unchangedData);
|
off_t *_blockNumber, void **_data, void **_unchangedData);
|
||||||
|
extern int32 cache_blocks_in_transaction(void *_cache, int32 id);
|
||||||
|
extern int32 cache_blocks_in_sub_transaction(void *_cache, int32 id);
|
||||||
|
|
||||||
/* block cache */
|
/* block cache */
|
||||||
extern void block_cache_delete(void *_cache, bool allowWrites);
|
extern void block_cache_delete(void *_cache, bool allowWrites);
|
||||||
|
122
src/system/kernel/cache/block_cache.cpp
vendored
122
src/system/kernel/cache/block_cache.cpp
vendored
@ -39,9 +39,12 @@
|
|||||||
|
|
||||||
|
|
||||||
struct cache_transaction {
|
struct cache_transaction {
|
||||||
|
cache_transaction();
|
||||||
|
|
||||||
cache_transaction *next;
|
cache_transaction *next;
|
||||||
int32 id;
|
int32 id;
|
||||||
int32 num_blocks;
|
int32 num_blocks;
|
||||||
|
int32 sub_num_blocks;
|
||||||
cached_block *first_block;
|
cached_block *first_block;
|
||||||
block_list blocks;
|
block_list blocks;
|
||||||
transaction_notification_hook notification_hook;
|
transaction_notification_hook notification_hook;
|
||||||
@ -56,6 +59,17 @@ static status_t write_cached_block(block_cache *cache, cached_block *block, bool
|
|||||||
// #pragma mark - private transaction
|
// #pragma mark - private transaction
|
||||||
|
|
||||||
|
|
||||||
|
cache_transaction::cache_transaction()
|
||||||
|
{
|
||||||
|
num_blocks = 0;
|
||||||
|
sub_num_blocks = 0;
|
||||||
|
first_block = NULL;
|
||||||
|
notification_hook = NULL;
|
||||||
|
notification_data = NULL;
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
transaction_compare(void *_transaction, const void *_id)
|
transaction_compare(void *_transaction, const void *_id)
|
||||||
{
|
{
|
||||||
@ -476,6 +490,7 @@ get_writable_cached_block(block_cache *cache, off_t blockNumber, off_t base, off
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(block->parent_data, block->data, cache->block_size);
|
memcpy(block->parent_data, block->data, cache->block_size);
|
||||||
|
block->transaction->sub_num_blocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cleared)
|
if (cleared)
|
||||||
@ -551,11 +566,6 @@ cache_start_transaction(void *_cache)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
transaction->id = atomic_add(&cache->next_transaction_id, 1);
|
transaction->id = atomic_add(&cache->next_transaction_id, 1);
|
||||||
transaction->num_blocks = 0;
|
|
||||||
transaction->first_block = NULL;
|
|
||||||
transaction->notification_hook = NULL;
|
|
||||||
transaction->notification_data = NULL;
|
|
||||||
transaction->open = true;
|
|
||||||
cache->last_transaction = transaction;
|
cache->last_transaction = transaction;
|
||||||
|
|
||||||
TRACE(("cache_transaction_start(): id %ld started\n", transaction->id));
|
TRACE(("cache_transaction_start(): id %ld started\n", transaction->id));
|
||||||
@ -629,7 +639,8 @@ cache_end_transaction(void *_cache, int32 id, transaction_notification_hook hook
|
|||||||
cache->Free(block->original);
|
cache->Free(block->original);
|
||||||
block->original = NULL;
|
block->original = NULL;
|
||||||
}
|
}
|
||||||
if (transaction->has_sub_transaction && block->parent_data != block->data) {
|
if (transaction->has_sub_transaction) {
|
||||||
|
if (block->parent_data != block->data)
|
||||||
cache->Free(block->parent_data);
|
cache->Free(block->parent_data);
|
||||||
block->parent_data = NULL;
|
block->parent_data = NULL;
|
||||||
}
|
}
|
||||||
@ -690,10 +701,73 @@ cache_abort_transaction(void *_cache, int32 id)
|
|||||||
|
|
||||||
|
|
||||||
extern "C" int32
|
extern "C" int32
|
||||||
cache_detach_sub_transaction(void *_cache, int32 id)
|
cache_detach_sub_transaction(void *_cache, int32 id,
|
||||||
|
transaction_notification_hook hook, void *data)
|
||||||
{
|
{
|
||||||
// ToDo: implement me!
|
block_cache *cache = (block_cache *)_cache;
|
||||||
return B_ERROR;
|
BenaphoreLocker locker(&cache->lock);
|
||||||
|
|
||||||
|
TRACE(("cache_end_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
|
if (transaction == NULL) {
|
||||||
|
panic("cache_end_transaction(): invalid transaction ID\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
if (!transaction->has_sub_transaction)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// create a new transaction for the sub transaction
|
||||||
|
cache_transaction *newTransaction = new cache_transaction;
|
||||||
|
if (transaction == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
newTransaction->id = atomic_add(&cache->next_transaction_id, 1);
|
||||||
|
|
||||||
|
transaction->notification_hook = hook;
|
||||||
|
transaction->notification_data = data;
|
||||||
|
|
||||||
|
// iterate through all blocks and free the unchanged original contents
|
||||||
|
|
||||||
|
cached_block *block = transaction->first_block, *next, *last = NULL;
|
||||||
|
for (; block != NULL; block = next) {
|
||||||
|
next = block->transaction_next;
|
||||||
|
|
||||||
|
if (block->previous_transaction != NULL) {
|
||||||
|
// need to write back pending changes
|
||||||
|
write_cached_block(cache, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->original != NULL) {
|
||||||
|
cache->Free(block->original);
|
||||||
|
block->original = NULL;
|
||||||
|
}
|
||||||
|
if (block->parent_data != block->data) {
|
||||||
|
// we need to move this block over to the new transaction
|
||||||
|
block->original = block->parent_data;
|
||||||
|
if (last == NULL)
|
||||||
|
newTransaction->first_block = block;
|
||||||
|
else
|
||||||
|
last->transaction_next = block;
|
||||||
|
|
||||||
|
last = block;
|
||||||
|
}
|
||||||
|
block->parent_data = NULL;
|
||||||
|
|
||||||
|
// move the block to the previous transaction list
|
||||||
|
transaction->blocks.Add(block);
|
||||||
|
|
||||||
|
block->previous_transaction = transaction;
|
||||||
|
block->transaction_next = NULL;
|
||||||
|
block->transaction = newTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction->open = false;
|
||||||
|
|
||||||
|
hash_insert(cache->transaction_hash, newTransaction);
|
||||||
|
cache->last_transaction = newTransaction;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -781,6 +855,8 @@ panic("unchanged block in transaction!");
|
|||||||
|
|
||||||
// all subsequent changes will go into the sub transaction
|
// all subsequent changes will go into the sub transaction
|
||||||
transaction->has_sub_transaction = true;
|
transaction->has_sub_transaction = true;
|
||||||
|
transaction->sub_num_blocks = 0;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,6 +894,34 @@ cache_next_block_in_transaction(void *_cache, int32 id, uint32 *_cookie, off_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int32
|
||||||
|
cache_blocks_in_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
block_cache *cache = (block_cache *)_cache;
|
||||||
|
BenaphoreLocker locker(&cache->lock);
|
||||||
|
|
||||||
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
|
if (transaction == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return transaction->num_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int32
|
||||||
|
cache_blocks_in_sub_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
block_cache *cache = (block_cache *)_cache;
|
||||||
|
BenaphoreLocker locker(&cache->lock);
|
||||||
|
|
||||||
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
|
if (transaction == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return transaction->sub_num_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - public block cache
|
// #pragma mark - public block cache
|
||||||
// public interface
|
// public interface
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user