* Added a TRANSACTION_IDLE notification that is sent when the transaction
hasn't been used for more than 2 seconds. * Replaced the block_cache::lock benaphore with a recursive lock, so that you can call cache functions from within the notification listeners. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24737 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,7 +14,8 @@
|
|||||||
enum {
|
enum {
|
||||||
TRANSACTION_WRITTEN,
|
TRANSACTION_WRITTEN,
|
||||||
TRANSACTION_ABORTED,
|
TRANSACTION_ABORTED,
|
||||||
TRANSACTION_ENDED
|
TRANSACTION_ENDED,
|
||||||
|
TRANSACTION_IDLE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*transaction_notification_hook)(int32 id, int32 event,
|
typedef void (*transaction_notification_hook)(int32 id, int32 event,
|
||||||
@@ -22,7 +23,7 @@ typedef void (*transaction_notification_hook)(int32 id, int32 event,
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* transactions */
|
/* transactions */
|
||||||
extern int32 cache_start_transaction(void *_cache);
|
extern int32 cache_start_transaction(void *_cache);
|
||||||
@@ -88,6 +89,6 @@ extern status_t file_map_translate(void *_map, off_t offset, size_t size,
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _FS_CACHE_H */
|
#endif /* _FS_CACHE_H */
|
||||||
|
|||||||
@@ -790,6 +790,7 @@
|
|||||||
#define TRANSACTION_WRITTEN FSSH_TRANSACTION_WRITTEN
|
#define TRANSACTION_WRITTEN FSSH_TRANSACTION_WRITTEN
|
||||||
#define TRANSACTION_ABORTED FSSH_TRANSACTION_ABORTED
|
#define TRANSACTION_ABORTED FSSH_TRANSACTION_ABORTED
|
||||||
#define TRANSACTION_ENDED FSSH_TRANSACTION_ENDED
|
#define TRANSACTION_ENDED FSSH_TRANSACTION_ENDED
|
||||||
|
#define TRANSACTION_IDLE FSSH_TRANSACTION_IDLE
|
||||||
|
|
||||||
#define transaction_notification_hook fssh_transaction_notification_hook
|
#define transaction_notification_hook fssh_transaction_notification_hook
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
enum {
|
enum {
|
||||||
FSSH_TRANSACTION_WRITTEN,
|
FSSH_TRANSACTION_WRITTEN,
|
||||||
FSSH_TRANSACTION_ABORTED,
|
FSSH_TRANSACTION_ABORTED,
|
||||||
FSSH_TRANSACTION_ENDED
|
FSSH_TRANSACTION_ENDED,
|
||||||
|
FSSH_TRANSACTION_IDLE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*fssh_transaction_notification_hook)(int32_t id, int32_t event,
|
typedef void (*fssh_transaction_notification_hook)(int32_t id, int32_t event,
|
||||||
@@ -22,7 +23,7 @@ typedef void (*fssh_transaction_notification_hook)(int32_t id, int32_t event,
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* transactions */
|
/* transactions */
|
||||||
extern int32_t fssh_cache_start_transaction(void *_cache);
|
extern int32_t fssh_cache_start_transaction(void *_cache);
|
||||||
@@ -110,6 +111,6 @@ extern fssh_status_t fssh_file_map_translate(void *_map, fssh_off_t offset,
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _FSSH_FS_CACHE_H */
|
#endif /* _FSSH_FS_CACHE_H */
|
||||||
|
|||||||
+56
-36
@@ -49,6 +49,9 @@
|
|||||||
#define FATAL(x) panic x
|
#define FATAL(x) panic x
|
||||||
|
|
||||||
|
|
||||||
|
static const bigtime_t kTransactionIdleTime = 2000000LL;
|
||||||
|
// a transaction is considered idle after 2 seconds of inactivity
|
||||||
|
|
||||||
struct cache_hook : DoublyLinkedListLinkImpl<cache_hook> {
|
struct cache_hook : DoublyLinkedListLinkImpl<cache_hook> {
|
||||||
transaction_notification_hook hook;
|
transaction_notification_hook hook;
|
||||||
void *data;
|
void *data;
|
||||||
@@ -71,6 +74,7 @@ struct cache_transaction {
|
|||||||
HookList listeners;
|
HookList listeners;
|
||||||
bool open;
|
bool open;
|
||||||
bool has_sub_transaction;
|
bool has_sub_transaction;
|
||||||
|
bigtime_t last_used;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BLOCK_CACHE_TRANSACTION_TRACING
|
#ifdef BLOCK_CACHE_TRANSACTION_TRACING
|
||||||
@@ -212,6 +216,7 @@ cache_transaction::cache_transaction()
|
|||||||
notification_hook = NULL;
|
notification_hook = NULL;
|
||||||
notification_data = NULL;
|
notification_data = NULL;
|
||||||
open = true;
|
open = true;
|
||||||
|
last_used = system_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -239,10 +244,11 @@ transaction_hash(void *_transaction, const void *_id, uint32 range)
|
|||||||
|
|
||||||
|
|
||||||
/*! Notifies all listeners of this transaction, and removes them
|
/*! Notifies all listeners of this transaction, and removes them
|
||||||
afterwards.
|
afterwards if requested via \a removeListener.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
notify_transaction_listeners(cache_transaction *transaction, int32 event)
|
notify_transaction_listeners(cache_transaction *transaction, int32 event,
|
||||||
|
bool removeListener)
|
||||||
{
|
{
|
||||||
HookList::Iterator iterator = transaction->listeners.GetIterator();
|
HookList::Iterator iterator = transaction->listeners.GetIterator();
|
||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
@@ -250,8 +256,10 @@ notify_transaction_listeners(cache_transaction *transaction, int32 event)
|
|||||||
|
|
||||||
hook->hook(transaction->id, event, hook->data);
|
hook->hook(transaction->id, event, hook->data);
|
||||||
|
|
||||||
iterator.Remove();
|
if (removeListener) {
|
||||||
delete hook;
|
iterator.Remove();
|
||||||
|
delete hook;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +361,7 @@ block_cache::block_cache(int _fd, off_t numBlocks, size_t blockSize,
|
|||||||
if (transaction_hash == NULL)
|
if (transaction_hash == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (benaphore_init(&lock, "block cache") < B_OK)
|
if (recursive_lock_init(&lock, "block cache") < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
register_low_memory_handler(&block_cache::LowMemoryHandler, this, 0);
|
register_low_memory_handler(&block_cache::LowMemoryHandler, this, 0);
|
||||||
@@ -368,7 +376,7 @@ block_cache::~block_cache()
|
|||||||
|
|
||||||
unregister_low_memory_handler(&block_cache::LowMemoryHandler, this);
|
unregister_low_memory_handler(&block_cache::LowMemoryHandler, this);
|
||||||
|
|
||||||
benaphore_destroy(&lock);
|
recursive_lock_destroy(&lock);
|
||||||
|
|
||||||
hash_uninit(transaction_hash);
|
hash_uninit(transaction_hash);
|
||||||
hash_uninit(hash);
|
hash_uninit(hash);
|
||||||
@@ -525,7 +533,7 @@ void
|
|||||||
block_cache::LowMemoryHandler(void *data, int32 level)
|
block_cache::LowMemoryHandler(void *data, int32 level)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)data;
|
block_cache *cache = (block_cache *)data;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
if (!locker.IsLocked()) {
|
if (!locker.IsLocked()) {
|
||||||
// If our block_cache were deleted, it could be that we had
|
// If our block_cache were deleted, it could be that we had
|
||||||
@@ -767,6 +775,8 @@ get_writable_cached_block(block_cache *cache, off_t blockNumber, off_t base,
|
|||||||
transaction->first_block = block;
|
transaction->first_block = block;
|
||||||
transaction->num_blocks++;
|
transaction->num_blocks++;
|
||||||
}
|
}
|
||||||
|
if (transaction != NULL)
|
||||||
|
transaction->last_used = system_time();
|
||||||
|
|
||||||
bool wasUnchanged = block->original_data == NULL
|
bool wasUnchanged = block->original_data == NULL
|
||||||
|| block->previous_transaction != NULL;
|
|| block->previous_transaction != NULL;
|
||||||
@@ -854,6 +864,7 @@ write_cached_block(block_cache *cache, cached_block *block,
|
|||||||
previous->notification_hook(previous->id, TRANSACTION_WRITTEN,
|
previous->notification_hook(previous->id, TRANSACTION_WRITTEN,
|
||||||
previous->notification_data);
|
previous->notification_data);
|
||||||
}
|
}
|
||||||
|
notify_transaction_listeners(previous, TRANSACTION_WRITTEN, false);
|
||||||
|
|
||||||
if (deleteTransaction) {
|
if (deleteTransaction) {
|
||||||
hash_remove(cache->transaction_hash, previous);
|
hash_remove(cache->transaction_hash, previous);
|
||||||
@@ -1054,6 +1065,8 @@ dump_transaction(int argc, char **argv)
|
|||||||
kprintf(" sub num block: %ld\n", transaction->sub_num_blocks);
|
kprintf(" sub num block: %ld\n", transaction->sub_num_blocks);
|
||||||
kprintf(" has sub: %d\n", transaction->has_sub_transaction);
|
kprintf(" has sub: %d\n", transaction->has_sub_transaction);
|
||||||
kprintf(" state: %s\n", transaction->open ? "open" : "closed");
|
kprintf(" state: %s\n", transaction->open ? "open" : "closed");
|
||||||
|
kprintf(" idle: %ld secs\n",
|
||||||
|
(system_time() - transaction->last_used) / 1000000);
|
||||||
|
|
||||||
if (!showBlocks)
|
if (!showBlocks)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1126,7 +1139,7 @@ block_writer(void *)
|
|||||||
|
|
||||||
block_cache *cache = NULL;
|
block_cache *cache = NULL;
|
||||||
while ((cache = get_next_block_cache(cache)) != NULL) {
|
while ((cache = get_next_block_cache(cache)) != NULL) {
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
const uint32 kMaxCount = 64;
|
const uint32 kMaxCount = 64;
|
||||||
cached_block *blocks[kMaxCount];
|
cached_block *blocks[kMaxCount];
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
@@ -1154,8 +1167,15 @@ block_writer(void *)
|
|||||||
while ((transaction = (cache_transaction *)hash_next(
|
while ((transaction = (cache_transaction *)hash_next(
|
||||||
cache->transaction_hash, &iterator)) != NULL
|
cache->transaction_hash, &iterator)) != NULL
|
||||||
&& count < kMaxCount) {
|
&& count < kMaxCount) {
|
||||||
if (transaction->open)
|
if (transaction->open) {
|
||||||
|
if (system_time() > transaction->last_used
|
||||||
|
+ kTransactionIdleTime) {
|
||||||
|
// transaction is open but idle
|
||||||
|
notify_transaction_listeners(transaction,
|
||||||
|
TRANSACTION_IDLE, false);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// sort blocks to speed up writing them back
|
// sort blocks to speed up writing them back
|
||||||
// TODO: ideally, this should be handled by the I/O scheduler
|
// TODO: ideally, this should be handled by the I/O scheduler
|
||||||
@@ -1223,7 +1243,7 @@ extern "C" int32
|
|||||||
cache_start_transaction(void *_cache)
|
cache_start_transaction(void *_cache)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
if (cache->last_transaction && cache->last_transaction->open) {
|
if (cache->last_transaction && cache->last_transaction->open) {
|
||||||
panic("last transaction (%ld) still open!\n",
|
panic("last transaction (%ld) still open!\n",
|
||||||
@@ -1250,7 +1270,7 @@ extern "C" status_t
|
|||||||
cache_sync_transaction(void *_cache, int32 id)
|
cache_sync_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
status_t status = B_ENTRY_NOT_FOUND;
|
status_t status = B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
TRACE(("cache_sync_transaction(id %ld)\n", id));
|
TRACE(("cache_sync_transaction(id %ld)\n", id));
|
||||||
@@ -1313,7 +1333,7 @@ cache_end_transaction(void *_cache, int32 id,
|
|||||||
transaction_notification_hook hook, void *data)
|
transaction_notification_hook hook, void *data)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("cache_end_transaction(id = %ld)\n", id));
|
TRACE(("cache_end_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
@@ -1328,7 +1348,7 @@ cache_end_transaction(void *_cache, int32 id,
|
|||||||
transaction->notification_hook = hook;
|
transaction->notification_hook = hook;
|
||||||
transaction->notification_data = data;
|
transaction->notification_data = data;
|
||||||
|
|
||||||
notify_transaction_listeners(transaction, TRANSACTION_ENDED);
|
notify_transaction_listeners(transaction, TRANSACTION_ENDED, true);
|
||||||
|
|
||||||
// iterate through all blocks and free the unchanged original contents
|
// iterate through all blocks and free the unchanged original contents
|
||||||
|
|
||||||
@@ -1369,7 +1389,7 @@ extern "C" status_t
|
|||||||
cache_abort_transaction(void *_cache, int32 id)
|
cache_abort_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("cache_abort_transaction(id = %ld)\n", id));
|
TRACE(("cache_abort_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
@@ -1380,7 +1400,7 @@ cache_abort_transaction(void *_cache, int32 id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
T(Abort(cache, transaction));
|
T(Abort(cache, transaction));
|
||||||
notify_transaction_listeners(transaction, TRANSACTION_ABORTED);
|
notify_transaction_listeners(transaction, TRANSACTION_ABORTED, true);
|
||||||
|
|
||||||
// iterate through all blocks and restore their original contents
|
// iterate through all blocks and restore their original contents
|
||||||
|
|
||||||
@@ -1420,7 +1440,7 @@ cache_detach_sub_transaction(void *_cache, int32 id,
|
|||||||
transaction_notification_hook hook, void *data)
|
transaction_notification_hook hook, void *data)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("cache_detach_sub_transaction(id = %ld)\n", id));
|
TRACE(("cache_detach_sub_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
@@ -1443,7 +1463,7 @@ cache_detach_sub_transaction(void *_cache, int32 id,
|
|||||||
transaction->notification_hook = hook;
|
transaction->notification_hook = hook;
|
||||||
transaction->notification_data = data;
|
transaction->notification_data = data;
|
||||||
|
|
||||||
notify_transaction_listeners(transaction, TRANSACTION_ENDED);
|
notify_transaction_listeners(transaction, TRANSACTION_ENDED, true);
|
||||||
|
|
||||||
// iterate through all blocks and free the unchanged original contents
|
// iterate through all blocks and free the unchanged original contents
|
||||||
|
|
||||||
@@ -1505,7 +1525,7 @@ extern "C" status_t
|
|||||||
cache_abort_sub_transaction(void *_cache, int32 id)
|
cache_abort_sub_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("cache_abort_sub_transaction(id = %ld)\n", id));
|
TRACE(("cache_abort_sub_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
@@ -1518,7 +1538,7 @@ cache_abort_sub_transaction(void *_cache, int32 id)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
T(Abort(cache, transaction));
|
T(Abort(cache, transaction));
|
||||||
notify_transaction_listeners(transaction, TRANSACTION_ABORTED);
|
notify_transaction_listeners(transaction, TRANSACTION_ABORTED, true);
|
||||||
|
|
||||||
// revert all changes back to the version of the parent
|
// revert all changes back to the version of the parent
|
||||||
|
|
||||||
@@ -1556,7 +1576,7 @@ extern "C" status_t
|
|||||||
cache_start_sub_transaction(void *_cache, int32 id)
|
cache_start_sub_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("cache_start_sub_transaction(id = %ld)\n", id));
|
TRACE(("cache_start_sub_transaction(id = %ld)\n", id));
|
||||||
|
|
||||||
@@ -1566,7 +1586,7 @@ cache_start_sub_transaction(void *_cache, int32 id)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_transaction_listeners(transaction, TRANSACTION_ENDED);
|
notify_transaction_listeners(transaction, TRANSACTION_ENDED, true);
|
||||||
|
|
||||||
// move all changed blocks up to the parent
|
// move all changed blocks up to the parent
|
||||||
|
|
||||||
@@ -1611,7 +1631,7 @@ cache_add_transaction_listener(void *_cache, int32 id,
|
|||||||
if (hook == NULL)
|
if (hook == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL) {
|
if (transaction == NULL) {
|
||||||
@@ -1633,7 +1653,7 @@ cache_remove_transaction_listener(void *_cache, int32 id,
|
|||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL)
|
if (transaction == NULL)
|
||||||
@@ -1660,7 +1680,7 @@ cache_next_block_in_transaction(void *_cache, int32 id, bool mainOnly,
|
|||||||
cached_block *block = (cached_block *)*_cookie;
|
cached_block *block = (cached_block *)*_cookie;
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL || !transaction->open)
|
if (transaction == NULL || !transaction->open)
|
||||||
@@ -1696,7 +1716,7 @@ extern "C" int32
|
|||||||
cache_blocks_in_transaction(void *_cache, int32 id)
|
cache_blocks_in_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL)
|
if (transaction == NULL)
|
||||||
@@ -1710,7 +1730,7 @@ extern "C" int32
|
|||||||
cache_blocks_in_main_transaction(void *_cache, int32 id)
|
cache_blocks_in_main_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL)
|
if (transaction == NULL)
|
||||||
@@ -1724,7 +1744,7 @@ extern "C" int32
|
|||||||
cache_blocks_in_sub_transaction(void *_cache, int32 id)
|
cache_blocks_in_sub_transaction(void *_cache, int32 id)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||||
if (transaction == NULL)
|
if (transaction == NULL)
|
||||||
@@ -1745,7 +1765,7 @@ block_cache_delete(void *_cache, bool allowWrites)
|
|||||||
if (allowWrites)
|
if (allowWrites)
|
||||||
block_cache_sync(cache);
|
block_cache_sync(cache);
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
// free all blocks
|
// free all blocks
|
||||||
|
|
||||||
@@ -1794,7 +1814,7 @@ block_cache_sync(void *_cache)
|
|||||||
// we will sync all dirty blocks to disk that have a completed
|
// we will sync all dirty blocks to disk that have a completed
|
||||||
// transaction or no transaction only
|
// transaction or no transaction only
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
hash_iterator iterator;
|
hash_iterator iterator;
|
||||||
hash_open(cache->hash, &iterator);
|
hash_open(cache->hash, &iterator);
|
||||||
|
|
||||||
@@ -1827,7 +1847,7 @@ block_cache_sync_etc(void *_cache, off_t blockNumber, size_t numBlocks)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
for (; numBlocks > 0; numBlocks--, blockNumber++) {
|
for (; numBlocks > 0; numBlocks--, blockNumber++) {
|
||||||
cached_block *block = (cached_block *)hash_lookup(cache->hash,
|
cached_block *block = (cached_block *)hash_lookup(cache->hash,
|
||||||
@@ -1853,7 +1873,7 @@ extern "C" status_t
|
|||||||
block_cache_make_writable(void *_cache, off_t blockNumber, int32 transaction)
|
block_cache_make_writable(void *_cache, off_t blockNumber, int32 transaction)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
if (cache->read_only)
|
if (cache->read_only)
|
||||||
panic("tried to make block writable on a read-only cache!");
|
panic("tried to make block writable on a read-only cache!");
|
||||||
@@ -1875,7 +1895,7 @@ block_cache_get_writable_etc(void *_cache, off_t blockNumber, off_t base,
|
|||||||
off_t length, int32 transaction)
|
off_t length, int32 transaction)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("block_cache_get_writable_etc(block = %Ld, transaction = %ld)\n",
|
TRACE(("block_cache_get_writable_etc(block = %Ld, transaction = %ld)\n",
|
||||||
blockNumber, transaction));
|
blockNumber, transaction));
|
||||||
@@ -1899,7 +1919,7 @@ extern "C" void *
|
|||||||
block_cache_get_empty(void *_cache, off_t blockNumber, int32 transaction)
|
block_cache_get_empty(void *_cache, off_t blockNumber, int32 transaction)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
TRACE(("block_cache_get_empty(block = %Ld, transaction = %ld)\n",
|
TRACE(("block_cache_get_empty(block = %Ld, transaction = %ld)\n",
|
||||||
blockNumber, transaction));
|
blockNumber, transaction));
|
||||||
@@ -1915,7 +1935,7 @@ extern "C" const void *
|
|||||||
block_cache_get_etc(void *_cache, off_t blockNumber, off_t base, off_t length)
|
block_cache_get_etc(void *_cache, off_t blockNumber, off_t base, off_t length)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
bool allocated;
|
bool allocated;
|
||||||
|
|
||||||
cached_block *block = get_cached_block(cache, blockNumber, &allocated);
|
cached_block *block = get_cached_block(cache, blockNumber, &allocated);
|
||||||
@@ -1952,7 +1972,7 @@ block_cache_set_dirty(void *_cache, off_t blockNumber, bool dirty,
|
|||||||
int32 transaction)
|
int32 transaction)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
cached_block *block = (cached_block *)hash_lookup(cache->hash,
|
cached_block *block = (cached_block *)hash_lookup(cache->hash,
|
||||||
&blockNumber);
|
&blockNumber);
|
||||||
@@ -1975,7 +1995,7 @@ extern "C" void
|
|||||||
block_cache_put(void *_cache, off_t blockNumber)
|
block_cache_put(void *_cache, off_t blockNumber)
|
||||||
{
|
{
|
||||||
block_cache *cache = (block_cache *)_cache;
|
block_cache *cache = (block_cache *)_cache;
|
||||||
BenaphoreLocker locker(&cache->lock);
|
RecursiveLocker locker(&cache->lock);
|
||||||
|
|
||||||
put_cached_block(cache, blockNumber);
|
put_cached_block(cache, blockNumber);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -52,20 +52,20 @@ typedef DoublyLinkedList<cached_block,
|
|||||||
&cached_block::link> > block_list;
|
&cached_block::link> > block_list;
|
||||||
|
|
||||||
struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
|
struct block_cache : DoublyLinkedListLinkImpl<block_cache> {
|
||||||
hash_table *hash;
|
hash_table *hash;
|
||||||
benaphore lock;
|
recursive_lock lock;
|
||||||
int fd;
|
int fd;
|
||||||
off_t max_blocks;
|
off_t max_blocks;
|
||||||
size_t block_size;
|
size_t block_size;
|
||||||
int32 next_transaction_id;
|
int32 next_transaction_id;
|
||||||
cache_transaction *last_transaction;
|
cache_transaction *last_transaction;
|
||||||
hash_table *transaction_hash;
|
hash_table *transaction_hash;
|
||||||
|
|
||||||
object_cache *buffer_cache;
|
object_cache *buffer_cache;
|
||||||
block_list unused_blocks;
|
block_list unused_blocks;
|
||||||
|
|
||||||
uint32 num_dirty_blocks;
|
uint32 num_dirty_blocks;
|
||||||
bool read_only;
|
bool read_only;
|
||||||
|
|
||||||
block_cache(int fd, off_t numBlocks, size_t blockSize, bool readOnly);
|
block_cache(int fd, off_t numBlocks, size_t blockSize, bool readOnly);
|
||||||
~block_cache();
|
~block_cache();
|
||||||
|
|||||||
Reference in New Issue
Block a user