Implemented basic sub transaction support - seems to work so far, but I haven't

tested it heavily yet.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14432 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-10-19 16:49:01 +00:00
parent ca7c5a9e13
commit 9a99234b1a
2 changed files with 34 additions and 34 deletions

View File

@ -300,7 +300,7 @@ Journal::Journal(Volume *volume)
fLogSize(volume->Log().length), fLogSize(volume->Log().length),
fMaxTransactionSize(fLogSize / 4 - 5), fMaxTransactionSize(fLogSize / 4 - 5),
fUsed(0), fUsed(0),
fTransactionsInEntry(0) fUnwrittenTransactions(0)
{ {
if (fMaxTransactionSize > fLogSize / 2) if (fMaxTransactionSize > fLogSize / 2)
fMaxTransactionSize = fLogSize / 2 - 5; fMaxTransactionSize = fLogSize / 2 - 5;
@ -501,13 +501,12 @@ Journal::_blockNotify(int32 transactionID, void *arg)
status_t status_t
Journal::WriteLogEntry() Journal::_WriteTransactionToLog()
{ {
// ToDo: in case of a failure, we need a backup plan like writing all // ToDo: in case of a failure, we need a backup plan like writing all
// changed blocks back to disk immediately // changed blocks back to disk immediately
fTransactionsInEntry = 0; fUnwrittenTransactions = 0;
fHasChangedBlocks = false;
int32 blockShift = fVolume->BlockShift(); int32 blockShift = fVolume->BlockShift();
off_t logOffset = fVolume->ToBlock(fVolume->Log()) << blockShift; off_t logOffset = fVolume->ToBlock(fVolume->Log()) << blockShift;
@ -679,8 +678,8 @@ Journal::FlushLogAndBlocks()
// write the current log entry to disk // write the current log entry to disk
if (fTransactionID != -1 /*&& TransactionSize() != 0*/) { if (fUnwrittenTransactions != 0 && _TransactionSize() != 0) {
status = WriteLogEntry(); status = _WriteTransactionToLog();
if (status < B_OK) if (status < B_OK)
FATAL(("writing current log entry failed: %s\n", strerror(status))); FATAL(("writing current log entry failed: %s\n", strerror(status)));
} }
@ -712,7 +711,12 @@ Journal::Lock(Transaction *owner)
fOwner = owner; fOwner = owner;
fTransactionID = cache_start_transaction(fVolume->BlockCache()); if (fUnwrittenTransactions > 0) {
// start a sub transaction
cache_start_sub_transaction(fVolume->BlockCache(), fTransactionID);
} else
fTransactionID = cache_start_transaction(fVolume->BlockCache());
if (fTransactionID < B_OK) { if (fTransactionID < B_OK) {
fLock.Unlock(); fLock.Unlock();
return fTransactionID; return fTransactionID;
@ -730,7 +734,6 @@ Journal::Unlock(Transaction *owner, bool success)
// ToDo: what about failing transactions that do not unlock? // ToDo: what about failing transactions that do not unlock?
_TransactionDone(success); _TransactionDone(success);
fTransactionID = -1;
fTimestamp = system_time(); fTimestamp = system_time();
fOwner = NULL; fOwner = NULL;
} }
@ -739,40 +742,38 @@ Journal::Unlock(Transaction *owner, bool success)
} }
uint32
Journal::_TransactionSize() const
{
int32 count = cache_blocks_in_transaction(fVolume->BlockCache(), fTransactionID);
if (count < 0)
return 0;
return count;
}
status_t status_t
Journal::_TransactionDone(bool success) Journal::_TransactionDone(bool success)
{ {
if (!success) { if (!success) {
cache_abort_transaction(fVolume->BlockCache(), fTransactionID); if (_HasSubTransaction())
return B_OK; cache_abort_sub_transaction(fVolume->BlockCache(), fTransactionID);
} else
cache_abort_transaction(fVolume->BlockCache(), fTransactionID);
// ToDo:
/*
if (!success && fTransactionsInEntry == 0) {
// we can safely abort the transaction
sorted_array *array = fArray.Array();
if (array != NULL) {
// release the lock for all blocks in the array (we don't need
// to be notified when they are actually written to disk)
for (int32 i = 0; i < array->count; i++)
release_block(fVolume->Device(), array->values[i]);
}
fUnwrittenTransactions--;
return B_OK; return B_OK;
} }
// Up to a maximum size, we will just batch several // Up to a maximum size, we will just batch several
// transactions together to improve speed // transactions together to improve speed
if (TransactionSize() < fMaxTransactionSize) { if (_TransactionSize() < fMaxTransactionSize) {
fTransactionsInEntry++; fUnwrittenTransactions++;
fHasChangedBlocks = false;
return B_OK; return B_OK;
} }
*/
return WriteLogEntry(); return _WriteTransactionToLog();
} }
@ -785,7 +786,6 @@ Journal::LogBlocks(off_t blockNumber, const uint8 *buffer, size_t numBlocks)
if (TransactionSize() + numBlocks + 1 > fLogSize) if (TransactionSize() + numBlocks + 1 > fLogSize)
return B_DEVICE_FULL; return B_DEVICE_FULL;
fHasChangedBlocks = true;
int32 blockSize = fVolume->BlockSize(); int32 blockSize = fVolume->BlockSize();
for (;numBlocks-- > 0; blockNumber++, buffer += blockSize) { for (;numBlocks-- > 0; blockNumber++, buffer += blockSize) {

View File

@ -49,11 +49,9 @@ class Journal {
status_t ReplayLog(); status_t ReplayLog();
status_t WriteLogEntry();
status_t LogBlocks(off_t blockNumber, const uint8 *buffer, size_t numBlocks); status_t LogBlocks(off_t blockNumber, const uint8 *buffer, size_t numBlocks);
Transaction *CurrentTransaction() const { return fOwner; } Transaction *CurrentTransaction() const { return fOwner; }
// uint32 TransactionSize() const { return fArray.CountItems() + fArray.BlocksUsed(); }
status_t FlushLogAndBlocks(); status_t FlushLogAndBlocks();
Volume *GetVolume() const { return fVolume; } Volume *GetVolume() const { return fVolume; }
@ -62,6 +60,9 @@ class Journal {
inline uint32 FreeLogBlocks() const; inline uint32 FreeLogBlocks() const;
private: private:
bool _HasSubTransaction() { return fUnwrittenTransactions > 1; }
uint32 _TransactionSize() const;
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);
@ -71,10 +72,9 @@ class Journal {
RecursiveLock fLock; RecursiveLock fLock;
Transaction *fOwner; Transaction *fOwner;
uint32 fLogSize, fMaxTransactionSize, fUsed; uint32 fLogSize, fMaxTransactionSize, fUsed;
int32 fTransactionsInEntry; int32 fUnwrittenTransactions;
SimpleLock fEntriesLock; SimpleLock fEntriesLock;
LogEntryList fEntries; LogEntryList fEntries;
bool fHasChangedBlocks;
bigtime_t fTimestamp; bigtime_t fTimestamp;
int32 fTransactionID; int32 fTransactionID;
}; };