#At file:///home/os136802/mysql/develop/repo/falcon-newdeps3-purgetrans/ based on revid:olav@stripped
2741 Olav Sandstaa 2008-12-08
WL#4654 New transaction dependency manager for Falcon
In the initial implementation of the new dependency manager all calls to
Transaction::commitRecords() and purging of old transaction objects was done by the scavenger.
This patch extends this task to be done also on every commit (in future: only commit of
non-read-only transactions) by calling a new version of TransactionManager::purgeTransactions()
that does not set the locks on the active and committed transaction list but relies on that
the caller has set these locks.
The reason for adding the call to this code in Transaction::commit() is that this is one
of the few places in the code where we have a lock on both the active and the commited transaction
lists.
modified:
storage/falcon/Transaction.cpp
storage/falcon/TransactionManager.cpp
storage/falcon/TransactionManager.h
per-file messages:
storage/falcon/Transaction.cpp
Call the TransactionManager::purgeTransactionWithLocks() from commit. Will now check for transaction objects to be ready to be "purged" and call Transaction::commitRecords() on every commit (of non-read-only) transactions instead of waiting for the scavenger to do this.
storage/falcon/TransactionManager.cpp
Implemented a new version of TransactionManager::purgeTransactions which expect that the caller
have set the necessary locks on the active and committed transaction list.
storage/falcon/TransactionManager.h
Implemented a new version of TransactionManager::purgeTransactions() that relies on that the
caller have set the necessary locks on the active and committed transaction lists.
=== modified file 'storage/falcon/Transaction.cpp'
=== modified file 'storage/falcon/Transaction.cpp'
--- a/storage/falcon/Transaction.cpp 2008-12-03 13:20:17 +0000
+++ b/storage/falcon/Transaction.cpp 2008-12-08 11:28:35 +0000
@@ -292,6 +292,13 @@
transactionManager->committedTransactions.append(this);
state = Committed;
+ // This is one of the few points where we have an exclusive lock on both the
+ // active and committed transaction list. Although this has nothing to do
+ // with the commit of this transaction we use the opportunity to clean up
+ // old transaction objects
+
+ transactionManager->purgeTransactionsWithLocks();
+
syncCommitted.unlock();
syncActiveTransactions.unlock();
@@ -305,16 +312,6 @@
// If there's no reason to stick around, just go away
- // NOTE: This call to commitRecords() is temporarily commented out.
- // A call to commitRecords() are taken care of in
- // TransactionManager::purgeTransactions().
- // It is likely that this call will be totally removed in one of the
- // next patches as I do not think it is ever called here due to
- // still having pending writes - but I will investigate this further
-
- //if ((dependencies == 0) && !writePending)
- // commitRecords();
-
connection = NULL;
// Add ourselves to the list of lingering committed transactions
@@ -926,17 +923,6 @@
ASSERT(state == Committed);
releaseDeferredIndexes();
- // NOTE: This call to commitRecords() is temporarily commented out.
- // A call to commitRecords() are taken care of in
- // TransactionManager::purgeTransactions().
- // We might want to include a call to commitRecords() her but in
- // order to perform the "dependencies == 0" check with the new
- // dependency manager we should probably have to do a shared lock
- // on the activelist. Need to experiment with this a bit.
-
- //if (dependencies == 0)
- // commitRecords();
-
// Log::log(LogXARecovery, "%d: WriteComplete %sTransaction %d\n",
// database->deltaTime, (systemTransaction ? "System " : ""), transactionId);
@@ -1453,21 +1439,11 @@
void Transaction::releaseCommittedTransaction(void)
{
+ // NOTE: consider to just move the call to release() to where this method is called.
+ // Leave it in here in case we want to check for being able to delete the transaction
+ // object here.
+
release();
-
- // NOTE: This is commented out due to in order to replacing the
- // "dependencies == 0" test we have to lock the active transaction list.
- // This should have no effect on Falcon due to that the if test will
- // never evaluate to true when called from Transaction::fullyCommitted().
- // Only when called from Transaction::releaseDependency() (which now is
- // deleted) would the if test occasionally be true.
- // The "removeCommittedTransaction" funcionality will be taken care
- // of by TransactionManager::purgeTransaction.
- // This code will likely be removed by a follow-up patch.
-
- //if ((useCount == 1) && (state == Committed) && (dependencies == 0) && !writePending)
- // if (COMPARE_EXCHANGE(&inList, (INTERLOCK_TYPE) true, (INTERLOCK_TYPE) false))
- // database->transactionManager->removeCommittedTransaction(this);
}
=== modified file 'storage/falcon/TransactionManager.cpp'
--- a/storage/falcon/TransactionManager.cpp 2008-12-03 13:20:17 +0000
+++ b/storage/falcon/TransactionManager.cpp 2008-12-08 11:28:35 +0000
@@ -15,7 +15,7 @@
#include <memory.h>
-#include <stdio.h> // Temporarily, will be removed before falcon-team tree
+#include <stdio.h>
#include <limits.h>
#include "Engine.h"
#include "TransactionManager.h"
@@ -271,15 +271,37 @@
transaction->getInfo(infoTable);
}
+
void TransactionManager::purgeTransactions()
{
+ // This method is called by the scavenger to clean up old committed
+ // transactions.
+
+ // To purge the committed transaction list requires at least
+ // a shared lock on the active transaction list and an exclusive
+ // lock on the committed transaction list
+
Sync syncActive(&activeTransactions.syncObject, "TransactionManager::purgeTransaction");
syncActive.lock(Shared);
-
+
Sync syncCommitted(&committedTransactions.syncObject, "Transaction::purgeTransactions");
syncCommitted.lock(Exclusive);
- fprintf(stderr, "TM::purgeTransactions: active=%d committed=%d alloc=%d delete=%d diff=%d\n", activeTransactions.count, committedTransactions.count, Talloc, Tdelete, (Talloc-Tdelete));
+ fprintf(stderr, "TM::purgeTransactions: BEFORE: active=%d committed=%d alloc=%d delete=%d diff=%d\n", activeTransactions.count, committedTransactions.count, Talloc, Tdelete, (Talloc-Tdelete));
+
+ purgeTransactionsWithLocks();
+
+ fprintf(stderr, "TM::purgeTransactions: AFTER : active=%d committed=%d alloc=%d delete=%d diff=%d\n", activeTransactions.count, committedTransactions.count, Talloc, Tdelete, (Talloc-Tdelete));
+}
+
+
+void TransactionManager::purgeTransactionsWithLocks()
+{
+ // Removes old committed transaction from the committed transaction list
+ // that no longer is visible by any currently active transactions.
+ // Note that this method relies on that the caller have at least a
+ // shared lock on the active transaction list and an exclusive lock on
+ // the committed transaction list
// Find the transaction id of the oldest active transaction
@@ -289,7 +311,6 @@
{
oldestActive = activeTransactions.first->transactionId;
}
- syncActive.unlock();
// Check for any fully mature transactions to ditch
@@ -307,6 +328,12 @@
committedTransactions.remove(transaction);
transaction->release();
}
+ else
+ {
+ // If the compare and exchange operation failed we re-try this transaction on the next call
+
+ break;
+ }
transaction = committedTransactions.first;
}
=== modified file 'storage/falcon/TransactionManager.h'
--- a/storage/falcon/TransactionManager.h 2008-12-03 13:20:17 +0000
+++ b/storage/falcon/TransactionManager.h 2008-12-08 11:28:35 +0000
@@ -42,6 +42,7 @@
Transaction* findOldest(void);
void getTransactionInfo(InfoTable* infoTable);
void purgeTransactions();
+ void purgeTransactionsWithLocks();
void getSummaryInfo(InfoTable* infoTable);
void reportStatistics(void);
Transaction* findTransaction(TransId transactionId);

Content reproduced on this site is the property of the respective copyright holders. It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.