Resolved a TODO in Journal::Lock() that Urias reminded me about:

* BFS now uses a transaction listener that flushes the current transaction
  in case it is idle; before, transactions would always be kept open when
  they weren't large, so that the block writer could not write back the blocks
  (they were busy from its POV).
* This solves the described problem of the screen resolution not being written
  back even after minutes of inactivity.
* Renamed _TransactionNotify() to _TransactionWritten() to differentiate it
  a bit more from the new _TransactionListener().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24738 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-04-02 09:46:34 +00:00
parent 16d8ff2dad
commit 3c78c04589
2 changed files with 44 additions and 15 deletions

View File

@ -531,8 +531,8 @@ Journal::ReplayLog()
the log start pointer as needed. Note, the transactions may not be the log start pointer as needed. Note, the transactions may not be
completed in the order they were written. completed in the order they were written.
*/ */
void /*static*/ void
Journal::_TransactionNotify(int32 transactionID, int32 event, void *_logEntry) Journal::_TransactionWritten(int32 transactionID, int32 event, void *_logEntry)
{ {
LogEntry *logEntry = (LogEntry *)_logEntry; LogEntry *logEntry = (LogEntry *)_logEntry;
@ -577,13 +577,27 @@ Journal::_TransactionNotify(int32 transactionID, int32 event, void *_logEntry)
status_t status = journal->fVolume->WriteSuperBlock(); status_t status = journal->fVolume->WriteSuperBlock();
if (status != B_OK) { if (status != B_OK) {
FATAL(("_BlockNotify: could not write back super block: %s\n", FATAL(("_TransactionWritten: could not write back super block: %s\n",
strerror(status))); strerror(status)));
} }
} }
} }
/*! Listens to TRANSACTION_IDLE events, and flushes the log when that happens */
/*static*/ void
Journal::_TransactionListener(int32 transactionID, int32 event, void *_journal)
{
if (event != TRANSACTION_IDLE)
return;
// The current transaction seems to be idle - flush it
Journal *journal = (Journal *)_journal;
journal->_FlushLog();
}
/*! Writes the blocks that are part of current transaction into the log, /*! Writes the blocks that are part of current transaction into the log,
and ends the current transaction. and ends the current transaction.
If the current transaction is too large to fit into the log, it will If the current transaction is too large to fit into the log, it will
@ -763,11 +777,11 @@ Journal::_WriteTransactionToLog()
if (detached) { if (detached) {
fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(), fTransactionID = cache_detach_sub_transaction(fVolume->BlockCache(),
fTransactionID, _TransactionNotify, logEntry); fTransactionID, _TransactionWritten, logEntry);
fUnwrittenTransactions = 1; fUnwrittenTransactions = 1;
} else { } else {
cache_end_transaction(fVolume->BlockCache(), fTransactionID, cache_end_transaction(fVolume->BlockCache(), fTransactionID,
_TransactionNotify, logEntry); _TransactionWritten, logEntry);
fUnwrittenTransactions = 0; fUnwrittenTransactions = 0;
} }
@ -775,8 +789,11 @@ Journal::_WriteTransactionToLog()
} }
/*! Flushes the current log entry to disk. If \a flushBlocks is \c true it will
also write back all dirty blocks for this volume.
*/
status_t status_t
Journal::FlushLogAndBlocks() Journal::_FlushLog(bool flushBlocks)
{ {
status_t status = fLock.Lock(); status_t status = fLock.Lock();
if (status != B_OK) if (status != B_OK)
@ -796,13 +813,24 @@ Journal::FlushLogAndBlocks()
FATAL(("writing current log entry failed: %s\n", strerror(status))); FATAL(("writing current log entry failed: %s\n", strerror(status)));
} }
status = fVolume->FlushDevice(); if (flushBlocks)
status = fVolume->FlushDevice();
fLock.Unlock(); fLock.Unlock();
return status; return status;
} }
/*! Flushes the current log entry to disk, and also writes back all dirty
blocks for this volume (completing all open transactions).
*/
status_t
Journal::FlushLogAndBlocks()
{
return _FlushLog(true);
}
status_t status_t
Journal::Lock(Transaction *owner) Journal::Lock(Transaction *owner)
{ {
@ -810,12 +838,6 @@ Journal::Lock(Transaction *owner)
if (status != B_OK) if (status != B_OK)
return status; return status;
/* ToDo:
// if the last transaction is older than 2 secs, start a new one
if (fTransactionsInEntry != 0 && system_time() - fTimestamp > 2000000L)
WriteLogEntry();
*/
if (fLock.OwnerCount() > 1) { if (fLock.OwnerCount() > 1) {
// we'll just use the current transaction again // we'll just use the current transaction again
return B_OK; return B_OK;
@ -842,6 +864,9 @@ Journal::Lock(Transaction *owner)
return fTransactionID; return fTransactionID;
} }
cache_add_transaction_listener(fVolume->BlockCache(), fTransactionID,
_TransactionListener, this);
return B_OK; return B_OK;
} }
@ -867,7 +892,7 @@ Journal::_TransactionSize() const
{ {
int32 count = cache_blocks_in_transaction(fVolume->BlockCache(), int32 count = cache_blocks_in_transaction(fVolume->BlockCache(),
fTransactionID); fTransactionID);
if (count < 0) if (count <= 0)
return 0; return 0;
// take the number of array blocks in this transaction into account // take the number of array blocks in this transaction into account

View File

@ -52,13 +52,17 @@ class Journal {
private: private:
bool _HasSubTransaction() { return fHasSubtransaction; } bool _HasSubTransaction() { return fHasSubtransaction; }
status_t _FlushLog(bool flushBlocks = false);
uint32 _TransactionSize() const; uint32 _TransactionSize() const;
status_t _WriteTransactionToLog(); status_t _WriteTransactionToLog();
status_t _CheckRunArray(const run_array *array); status_t _CheckRunArray(const run_array *array);
status_t _ReplayRunArray(int32 *start); status_t _ReplayRunArray(int32 *start);
status_t _TransactionDone(bool success); status_t _TransactionDone(bool success);
static void _TransactionNotify(int32 transactionID, int32 event,
static void _TransactionWritten(int32 transactionID, int32 event,
void *_logEntry); void *_logEntry);
static void _TransactionListener(int32 transactionID, int32 event,
void *_journal);
Volume *fVolume; Volume *fVolume;
RecursiveLock fLock; RecursiveLock fLock;