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:
parent
16d8ff2dad
commit
3c78c04589
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue