* Brought the fs_shell block_cache implementation up to date, and incorporate

the fixes applied to the kernel version of it (most notably a correctly
  working block_cache_discard(), and cache_detach_sub_transaction()).
  Also switched to the new notification functions, even though it still works
  synchronously in the fs_shell.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28617 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-11-11 22:19:46 +00:00
parent edff846689
commit 8f1cb8fca2
2 changed files with 617 additions and 342 deletions

View File

@ -471,6 +471,61 @@ get_next_pending_event(cache_notification* notification, int32* _event)
}
static void
flush_pending_notifications(block_cache* cache)
{
ASSERT_LOCKED_MUTEX(&sCachesLock);
while (true) {
MutexLocker locker(sNotificationsLock);
cache_notification* notification = cache->pending_notifications.Head();
if (notification == NULL)
return;
bool deleteAfterEvent = false;
int32 event = -1;
if (!get_next_pending_event(notification, &event)) {
// remove the notification if this was the last pending event
cache->pending_notifications.Remove(notification);
deleteAfterEvent = notification->delete_after_event;
}
if (event >= 0) {
// Notify listener, we need to copy the notification, as it might
// be removed when we unlock the list.
cache_notification copy = *notification;
locker.Unlock();
copy.hook(copy.transaction_id, event, copy.data);
locker.Lock();
}
if (deleteAfterEvent)
delete notification;
}
}
/*! Flushes all pending notifications by calling the appropriate hook
functions.
Must not be called with a cache lock held.
*/
static void
flush_pending_notifications()
{
MutexLocker _(sCachesLock);
DoublyLinkedList<block_cache>::Iterator iterator = sCaches.GetIterator();
while (iterator.HasNext()) {
block_cache* cache = iterator.Next();
flush_pending_notifications(cache);
}
}
/*! Initializes the \a notification as specified. */
static void
set_notification(cache_transaction* transaction,
@ -563,61 +618,6 @@ notify_transaction_listeners(block_cache* cache, cache_transaction* transaction,
}
static void
flush_pending_notifications(block_cache* cache)
{
ASSERT_LOCKED_MUTEX(&sCachesLock);
while (true) {
MutexLocker locker(sNotificationsLock);
cache_notification* notification = cache->pending_notifications.Head();
if (notification == NULL)
return;
bool deleteAfterEvent = false;
int32 event = -1;
if (!get_next_pending_event(notification, &event)) {
// remove the notification if this was the last pending event
cache->pending_notifications.Remove(notification);
deleteAfterEvent = notification->delete_after_event;
}
if (event >= 0) {
// Notify listener, we need to copy the notification, as it might
// be removed when we unlock the list.
cache_notification copy = *notification;
locker.Unlock();
copy.hook(copy.transaction_id, event, copy.data);
locker.Lock();
}
if (deleteAfterEvent)
delete notification;
}
}
/*! Flushes all pending notifications by calling the appropriate hook
functions.
Must not be called with a cache lock held.
*/
static void
flush_pending_notifications()
{
MutexLocker _(sCachesLock);
DoublyLinkedList<block_cache>::Iterator iterator = sCaches.GetIterator();
while (iterator.HasNext()) {
block_cache* cache = iterator.Next();
flush_pending_notifications(cache);
}
}
/*! Removes and deletes all listeners that are still monitoring this
transaction.
*/
@ -1218,7 +1218,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base,
cache_transaction* transaction = block->transaction;
if (transaction != NULL && transaction->id != transactionID) {
// ToDo: we have to wait here until the other transaction is done.
// TODO: we have to wait here until the other transaction is done.
// Maybe we should even panic, since we can't prevent any deadlocks.
panic("get_writable_cached_block(): asked to get busy writable block (transaction %ld)\n", block->transaction->id);
put_cached_block(cache, block);
@ -2594,7 +2594,7 @@ block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction)
if (cache->read_only)
panic("tried to make block writable on a read-only cache!");
// ToDo: this can be done better!
// TODO: this can be done better!
void* block = get_writable_cached_block(cache, blockNumber,
blockNumber, 1, transaction, false);
if (block != NULL) {

File diff suppressed because it is too large Load Diff