List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:March 23 2009 7:17pm
Subject:bzr commit into mysql-6.0-falcon-team branch (vvaintroub:3070)
View as plain text  
#At file:///G:/bzr/mysql-6.0-falcon-team/ based on
revid:vvaintroub@stripped

 3070 Vladislav Vaintroub	2009-03-23 [merge]
      merge

    added:
      storage/falcon/TransactionState.cpp
      storage/falcon/TransactionState.h
    modified:
      storage/falcon/Connection.cpp
      storage/falcon/Database.cpp
      storage/falcon/Makefile.am
      storage/falcon/Record.cpp
      storage/falcon/Record.h
      storage/falcon/RecordVersion.cpp
      storage/falcon/RecordVersion.h
      storage/falcon/Table.cpp
      storage/falcon/Transaction.cpp
      storage/falcon/Transaction.h
      storage/falcon/TransactionManager.cpp
=== modified file 'storage/falcon/Connection.cpp'
--- a/storage/falcon/Connection.cpp	2009-02-23 22:42:36 +0000
+++ b/storage/falcon/Connection.cpp	2009-03-23 14:57:48 +0000
@@ -1718,7 +1718,7 @@ void Connection::detachDatabase()
 
 	try
 		{
-		if (transaction && transaction->state == Active)
+		if (transaction && transaction->getState() == Active)
 			transaction->rollback();
 		}
 	catch (SQLException &exception)

=== modified file 'storage/falcon/Database.cpp'
--- a/storage/falcon/Database.cpp	2009-03-09 12:12:14 +0000
+++ b/storage/falcon/Database.cpp	2009-03-23 14:57:48 +0000
@@ -1611,7 +1611,7 @@ void Database::shutdown()
 	
 	if (systemConnection && 
 		systemConnection->transaction && 
-		systemConnection->transaction->state == Active)
+		systemConnection->transaction->getState() == Active)
 		systemConnection->commit();
 		
 	if (repositoryManager)

=== modified file 'storage/falcon/Makefile.am'
--- a/storage/falcon/Makefile.am	2009-03-10 12:37:26 +0000
+++ b/storage/falcon/Makefile.am	2009-03-23 14:57:48 +0000
@@ -205,6 +205,7 @@ falcon_headers= Agent.h Alias.h Applicat
 		TimeStamp.h \
 		Transaction.h \
 		TransactionManager.h \
+		TransactionState.h \
 		Trigger.h \
 		TriggerRecord.h \
 		Types.h Unicode.h UnTable.h User.h UserRole.h \
@@ -389,6 +390,7 @@ falcon_sources= Agent.cpp Alias.cpp \
 		TimeStamp.cpp \
 		Transaction.cpp \
 		TransactionManager.cpp \
+		TransactionState.cpp \
 		Trigger.cpp \
 		Unicode.cpp UnTable.cpp User.cpp \
 		UserRole.cpp Validation.cpp Value.cpp ValueEx.cpp Values.cpp \

=== modified file 'storage/falcon/Record.cpp'
--- a/storage/falcon/Record.cpp	2009-03-07 01:37:19 +0000
+++ b/storage/falcon/Record.cpp	2009-03-23 14:57:48 +0000
@@ -536,6 +536,11 @@ Transaction* Record::getTransaction()
 	return NULL;
 }
 
+TransactionState* Record::getTransactionState() const
+{
+	return NULL;
+}
+
 bool Record::isSuperceded()
 {
 	return false;

=== modified file 'storage/falcon/Record.h'
--- a/storage/falcon/Record.h	2009-02-26 20:04:31 +0000
+++ b/storage/falcon/Record.h	2009-03-23 14:57:48 +0000
@@ -89,6 +89,7 @@ static const int recEndChain = 11;		// e
 class Format;
 class Table;
 class Transaction;
+class TransactionState;
 class Value;
 class Stream;
 class Database;
@@ -104,6 +105,7 @@ class Record
 {
 public:
 	virtual Transaction* getTransaction();
+	virtual TransactionState* getTransactionState() const;
 	virtual TransId	getTransactionId();
 	virtual int		getSavePointId();
 	virtual void	setSuperceded (bool flag);

=== modified file 'storage/falcon/RecordVersion.cpp'
--- a/storage/falcon/RecordVersion.cpp	2009-03-03 07:09:29 +0000
+++ b/storage/falcon/RecordVersion.cpp	2009-03-23 14:57:48 +0000
@@ -23,6 +23,7 @@
 #include "Configuration.h"
 #include "RecordVersion.h"
 #include "Transaction.h"
+#include "TransactionState.h"
 #include "TransactionManager.h"
 #include "Table.h"
 #include "Connection.h"
@@ -47,10 +48,16 @@ RecordVersion::RecordVersion(Table *tbl,
 {
 	virtualOffset = 0;
 	transaction   = trans;
+	transState    = trans->transactionState;
 	transactionId = transaction->transactionId;
 	savePointId   = transaction->curSavePointId;
 	superceded    = false;
 
+	// Add a use count on the transaction state to ensure it lives as long 
+	// as the record version object
+
+	transState->addRef();
+
 	if ((priorVersion = oldVersion))
 		{
 		priorVersion->addRef();
@@ -66,7 +73,7 @@ RecordVersion::RecordVersion(Table *tbl,
 		recordNumber = -1;
 }
 
-RecordVersion::RecordVersion(Database* database, Serialize *stream) : Record(database,
stream)
+RecordVersion::RecordVersion(Database* database, Serialize *stream) : Record(database,
stream), transState(NULL)
 {
 	// Reconstitute a record version and recursively restore all
 	// prior versions from 'stream'
@@ -104,6 +111,11 @@ RecordVersion::~RecordVersion()
 	
 	while (prior)
 		prior = prior->releaseNonRecursive();
+
+	// Release the use count on the transaction state object
+
+	if (transState)
+		transState->release();
 }
 
 // Release the priorRecord reference without doing it recursively.
@@ -143,7 +155,7 @@ Record* RecordVersion::fetchVersionRecur
 		{
 		if (IS_READ_COMMITTED(trans->isolationLevel))
 			{
-			int state = (recTransaction) ? recTransaction->state : 0;
+			int state = (recTransaction) ? recTransaction->transactionState->state : 0;
 			
 			if (!transaction || state == Committed || recTransaction == trans)
 				return (getRecordData()) ? this : NULL;
@@ -295,6 +307,11 @@ Transaction* RecordVersion::getTransacti
 	return transaction;
 }
 
+TransactionState* RecordVersion::getTransactionState() const
+{
+	return transState;
+}
+
 bool RecordVersion::isSuperceded()
 {
 	return superceded;

=== modified file 'storage/falcon/RecordVersion.h'
--- a/storage/falcon/RecordVersion.h	2009-01-14 22:33:44 +0000
+++ b/storage/falcon/RecordVersion.h	2009-03-23 14:57:48 +0000
@@ -27,6 +27,7 @@
 #include "Record.h"
 
 class Transaction;
+class TransactionState;
 class SyncObject;
 
 class RecordVersion : public Record  
@@ -37,6 +38,7 @@ public:
 
 	virtual bool		isSuperceded();
 	virtual Transaction* getTransaction();
+	virtual TransactionState* getTransactionState() const;
 	virtual TransId		getTransactionId();
 	virtual int			getSavePointId();
 	virtual void		setSuperceded (bool flag);
@@ -73,6 +75,9 @@ public:
 	TransId			transactionId;
 	int				savePointId;
 	bool			superceded;
+
+private:
+	TransactionState *transState;
 };
 
 #endif // !defined(AFX_RECORDVERSION_H__84FD1965_A97F_11D2_AB5C_0000C01D2301__INCLUDED_)

=== modified file 'storage/falcon/Table.cpp'
--- a/storage/falcon/Table.cpp	2009-03-09 12:12:14 +0000
+++ b/storage/falcon/Table.cpp	2009-03-23 14:57:48 +0000
@@ -2661,7 +2661,7 @@ bool Table::checkUniqueRecordVersion(int
 				syncPrior.unlock(); // release lock before wait
 				syncUnique->unlock(); // release lock before wait
 
-				state = transaction->getRelativeState(activeTransaction,
+				state = transaction->getRelativeState(activeTransaction->transactionState,
 						activeTransaction->transactionId, WAIT_IF_ACTIVE);
 
 				if (state != Deadlock)
@@ -3768,7 +3768,7 @@ bool Table::validateUpdate(int32 recordN
 		
 		Transaction *transaction = record->getTransaction();
 		
-		if (!transaction || transaction->state == Committed)
+		if (!transaction || transaction->getState() == Committed)
 			{
 			SET_RECORD_ACTIVE(record, false);
 			record->release(REC_HISTORY);

=== modified file 'storage/falcon/Transaction.cpp'
--- a/storage/falcon/Transaction.cpp	2009-03-05 09:20:35 +0000
+++ b/storage/falcon/Transaction.cpp	2009-03-23 14:57:48 +0000
@@ -20,6 +20,7 @@
 #include <memory.h>
 #include "Engine.h"
 #include "Transaction.h"
+#include "TransactionState.h"
 #include "Configuration.h"
 #include "Database.h"
 #include "Dbb.h"
@@ -89,12 +90,12 @@ Transaction::Transaction(Connection *cnc
 	freeSavePoints = NULL;
 	useCount = 1;
 	syncObject.setName("Transaction::syncObject");
-	syncIsActive.setName("Transaction::syncActive");
 	syncDeferredIndexes.setName("Transaction::syncDeferredIndexes");
 	syncRecords.setName("Transaction::syncRecords");
 	syncSavepoints.setName("Transaction::syncSavepoints");
 	firstRecord = NULL;
 	lastRecord = NULL;
+	transactionState = new TransactionState();
 	initialize(cnct, seq);
 }
 
@@ -112,14 +113,14 @@ void Transaction::initialize(Connection*
 	transactionManager = database->transactionManager;
 	systemTransaction = database->systemConnection == connection;
 	transactionId = seq;
-	commitId = 0;
+	transactionState->transactionId = seq;
+	transactionState->commitId = 0;
 	chillPoint = &firstRecord;
 	commitTriggers = false;
 	hasUpdates = false;
 	hasLocks = false;
 	writePending = true;
 	pendingPageWrites = false;
-	waitingFor = NULL;
 	curSavePointId = 0;
 	deferredIndexes = NULL;
 	backloggedRecords = NULL;
@@ -143,7 +144,7 @@ void Transaction::initialize(Connection*
 	
 	if (seq == 0)
 		{
-		state = Available;
+		transactionState->state = Available;
 		systemTransaction = false;
 		writePending = false;
 
@@ -159,21 +160,21 @@ void Transaction::initialize(Connection*
 	startTime = database->deltaTime;
 	blockingRecord = NULL;
 	thread = Thread::getThread("Transaction::initialize");
-	syncIsActive.lock(NULL, Exclusive);
-	state = Active;
+	transactionState->syncIsActive.lock(NULL, Exclusive);
+	transactionState->state = Active;
 }
 
 Transaction::~Transaction()
 {
 	Tdelete++;
 
-	if (state == Active)
+	if (transactionState->state == Active)
 		{
 		Log::debug("Deleting apparently active transaction %d\n", transactionId);
 		ASSERT(false);
 		
-		if (syncIsActive.ourExclusiveLock())
-			syncIsActive.unlock();
+		if (transactionState->syncIsActive.ourExclusiveLock())
+			transactionState->syncIsActive.unlock();
 		}
 
 	if (inList)
@@ -196,6 +197,9 @@ Transaction::~Transaction()
 	
 	if (deferredIndexes)
 		releaseDeferredIndexes();
+
+	if (transactionState)
+		transactionState->release();
 }
 
 void Transaction::commit()
@@ -217,7 +221,7 @@ void Transaction::commit()
 	Log::log(LogXARecovery, "%d: Commit %sTransaction %d\n", 
 		database->deltaTime, (systemTransaction ? "System " : ""),  transactionId);
 
-	if (state == Active)
+	if (transactionState->state == Active)
 		{
 		Sync sync(&syncDeferredIndexes, "Transaction::commit(1)");
 		sync.lock(Shared);
@@ -279,11 +283,11 @@ void Transaction::commit()
 
 	// Set the commit transition id for this transaction
 
-	commitId = INTERLOCKED_INCREMENT(transactionManager->transactionSequence);
+	transactionState->commitId =
INTERLOCKED_INCREMENT(transactionManager->transactionSequence);
 
 	transactionManager->activeTransactions.remove(this);
 	transactionManager->committedTransactions.append(this);
-	state = Committed;
+	transactionState->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
@@ -298,7 +302,7 @@ void Transaction::commit()
 	syncCommitted.unlock();
 	syncActiveTransactions.unlock();
 	
-	syncIsActive.unlock(); // signal waiting transactions
+	transactionState->syncIsActive.unlock(); // signal waiting transactions
 	
 	// signal a gopher to start processing this transaction
 
@@ -350,10 +354,11 @@ void Transaction::commitNoUpdates(void)
 	
 	connection = NULL;
 	transactionId = 0;
+	transactionState->transactionId = 0;
 	writePending = false;
-	state = Available;
+	transactionState->state = Available;
 	syncActiveTransactions.unlock();
-	syncIsActive.unlock();
+	transactionState->syncIsActive.unlock();
 	release();
 }
 
@@ -445,8 +450,8 @@ void Transaction::rollback()
 	inList = false;
 	transactionManager->activeTransactions.remove(this);
 	syncActiveTransactions.unlock();
-	state = RolledBack;
-	syncIsActive.unlock();
+	transactionState->state = RolledBack;
+	transactionState->syncIsActive.unlock();
 
 	// Finish the SerialLogTransaction and signal a gopher
 
@@ -463,7 +468,7 @@ void Transaction::rollback()
 
 void Transaction::prepare(int xidLen, const UCHAR *xidPtr)
 {
-	if (state != Active)
+	if (transactionState->state != Active)
 		throw SQLEXCEPTION (RUNTIME_ERROR, "transaction is not active");
 
 	Log::log(LogXARecovery, "Prepare transaction %d: xidLen = %d\n", transactionId, xidLen);
@@ -478,7 +483,7 @@ void Transaction::prepare(int xidLen, co
 		}
 		
 	database->pageWriter->waitForWrites(this);
-	state = Limbo;
+	transactionState->state = Limbo;
 
 	// Flush a prepare record to the serial log
 
@@ -591,8 +596,9 @@ void Transaction::thaw(DeferredIndex * d
 void Transaction::addRecord(RecordVersion * record)
 {
 	ASSERT(record->recordNumber >= 0);
+
 	hasUpdates = true;
-	
+
 	if (record->state == recLock)
 		hasLocks = true;
 	else if (record->state == recDeleted)
@@ -715,19 +721,34 @@ bool Transaction::visible(Transaction * 
 	if (!transaction)
 		return true;
 
+    return visible(transaction->transactionState, forWhat);
+}
+
+
+/***
+@brief		Determine if changes by another transaction are visible to this.
+@details	This function is called for Consistent-Read transactions to determine
+			if the sent trans was committed before this transaction started.  If not,
+			it is invisible to this transaction.
+***/
+
+bool Transaction::visible(const TransactionState* transState, int forWhat) const
+{
+	ASSERT(transState != NULL);
+
 	// If we're the transaction in question, consider us committed
 
-	if (transId == transactionId)
+	if (transactionState == transState)
 		return true;
 
 	// If we're the system transaction, just use the state of the other transaction
 
 	if (database->systemConnection->transaction == this)
-		return transaction->state == Committed;
+		return transState->state == Committed;
 
 	// If the other transaction is not yet committed, the trans is not visible.
 
-	if (transaction->state != Committed)
+	if (transState->state != Committed)
 		return false;
 
 	// The other transaction is committed.  
@@ -744,12 +765,13 @@ bool Transaction::visible(Transaction * 
 	// If the other transaction committed after we started then it is not
 	// be visible to us
 
-	if (transaction->commitId > transactionId)
+	if (transState->commitId > transactionId)
 		return false;
 
 	return true;
 }
 
+
 /***
 @brief		Determine if there is a need to lock this record for update.
 ***/
@@ -765,12 +787,12 @@ bool Transaction::needToLock(Record* rec
 		 candidate != NULL;
 		 candidate = candidate->getPriorVersion())
 		{
-		Transaction *transaction = candidate->getTransaction();
-		TransId transId = candidate->getTransactionId();
+		TransactionState* transState = candidate->getTransactionState();
+		ASSERT(transState != NULL);
 
-		if (visible(transaction, transId, FOR_WRITING))
+		if (visible(transState, FOR_WRITING))
 			if (candidate->state == recDeleted)
-				if (!transaction || transaction->state == Committed)
+				if (transState->state == Committed)
 					return false; // Committed and deleted
 				else
 					return true; // Just in case this rolls back.
@@ -832,24 +854,30 @@ State Transaction::getRelativeState(Reco
 		}
 
 	blockingRecord = record;
-	State state = getRelativeState(record->getTransaction(),
record->getTransactionId(), flags);
+	State state = getRelativeState(record->getTransactionState(),
record->getTransactionId(), flags);
 	blockingRecord = NULL;
 
 	return state;
 }
 
+
 /***
 @brief		Get the relative state between this transaction and another.
 ***/
 
-State Transaction::getRelativeState(Transaction *transaction, TransId transId, uint32
flags)
+State Transaction::getRelativeState(TransactionState* transState, TransId transId, uint32
flags)
 {
+	// Note: The structure of this method is still based on the
+	// original getRelativeState() - should be carefully rewritten
+
 	if (transactionId == transId)
 		return Us;
 
-	// A record may still have the transId even after the trans itself has been deleted.
-	
-	if (!transaction)
+	// The following if test replaces the original if (!transaction)
+	// This could be improved by combining it with the last if test
+	// at the end of this function.
+
+	if (transState->state == Committed && transState->commitId <
transactionId)
 		{
 		// All calls to getRelativeState are for the purpose of writing.
 		// So only ConsistentRead can get CommittedInvisible.
@@ -869,13 +897,13 @@ State Transaction::getRelativeState(Tran
 		return CommittedVisible;
 		}
 
-	if (transaction->isActive())
+	if (transState->isActive())
 		{
 		if (flags & DO_NOT_WAIT)
 			return Active;
 
 		bool isDeadlock;
-		waitForTransaction(transaction, 0 , &isDeadlock);
+		waitForTransaction(transState, 0 , &isDeadlock);
 
 		if (isDeadlock)
 			return Deadlock;
@@ -883,20 +911,21 @@ State Transaction::getRelativeState(Tran
 		return WasActive;			// caller will need to re-fetch
 		}
 
-	if (transaction->state == Committed)
+	if (transState->state == Committed)
 		{
 		// Return CommittedVisible if the other trans has a lower TransId and 
 		// it was committed when we started.
 		
-		if (visible (transaction, transId, FOR_WRITING))
+		if (visible (transState, FOR_WRITING))
 			return CommittedVisible;
 
 		return CommittedInvisible;
 		}
 
-	return (State) transaction->state;
+	return (State) transState->state;
 }
 
+
 void Transaction::dropTable(Table* table)
 {
 	releaseDeferredIndexes(table);
@@ -942,7 +971,7 @@ bool Transaction::hasRecords(Table* tabl
 void Transaction::writeComplete(void)
 {
 	ASSERT(writePending);
-	ASSERT(state == Committed);
+	ASSERT(transactionState->state == Committed);
 	releaseDeferredIndexes();
 
 //	Log::log(LogXARecovery, "%d: WriteComplete %sTransaction %d\n", 
@@ -959,6 +988,7 @@ bool Transaction::waitForTransaction(Tra
 
 }
 
+
 // Wait for transaction, unless it would lead to deadlock.
 // Returns the state of transation.
 //
@@ -971,50 +1001,66 @@ bool Transaction::waitForTransaction(Tra
 // use inline assembly or intrinsics to generate memory barrier instead of 
 // volatile. 
 
-State Transaction::waitForTransaction(Transaction *transaction, TransId transId,
+State Transaction::waitForTransaction(TransactionState* transState, TransId transId,
 										bool *deadlock)
 {
+	ASSERT(transState != NULL);
+
 	*deadlock = false;
 	State state;
 
-	if(transaction)
-		transaction->addRef();
+	// Increase the use count on the transaction state object to ensure
+	// the object the waitingFor pointer refers to does not get deleted
+
+	if(transState)
+		transState->addRef();
 
 	Sync syncActiveTransactions(&transactionManager->activeTransactions.syncObject,
 		"Transaction::waitForTransaction(1)");
 	syncActiveTransactions.lock(Shared);
 
-	if (!transaction)
+	// If a transaction state object is not given, locate it by searching
+	// for the transaction in the active list
+
+	if (!transState)
 		{
+		Transaction* transaction; 
+
 		// transaction parameter is not given, find transaction using its ID.
 		for (transaction = transactionManager->activeTransactions.first; transaction;
 			 transaction = transaction->next)
 			{
 			if (transaction->transactionId == transId)
 				{
-				transaction->addRef();
 				break;
 				}
 			}
+
+		// If the transaction is not found in the active list it is committed
+
+		if (!transaction)
+			return Committed;
+
+		transState = transaction->transactionState;
+		transState->addRef();
 		}
 
-	if (!transaction)
-		return Committed;
+	ASSERT(transState != NULL);
 
-	if (transaction->state == Available || transaction->state == Committed)
+	if (transState->state == Available || transState->state == Committed)
 	{
-		state = (State)transaction->state;
-		transaction->release();
+		state = (State)transState->state;
+		transState->release();
 		return state;
 	}
 
 
-	if (!COMPARE_EXCHANGE_POINTER(&waitingFor, NULL, transaction))
+	if (!COMPARE_EXCHANGE_POINTER(&transactionState->waitingFor, NULL, transState))
 		FATAL("waitingFor was not NULL");
 
-	volatile Transaction *trans;
-	for (trans = transaction->waitingFor; trans; trans = trans->waitingFor)
-		if (trans == this)
+	volatile TransactionState *trans;
+	for (trans = transState->waitingFor; trans; trans = trans->waitingFor)
+		if (trans == transactionState)
 			{
 			*deadlock = true;
 			break;
@@ -1025,40 +1071,24 @@ State Transaction::waitForTransaction(Tr
 		try
 			{
 			syncActiveTransactions.unlock();
-			transaction->waitForTransaction();
+			transState->waitForTransaction();
 			}
 		catch(...)
 			{
-			if (!COMPARE_EXCHANGE_POINTER(&waitingFor, transaction, NULL))
-				FATAL("waitingFor was not %p",transaction);
+			if (!COMPARE_EXCHANGE_POINTER(&transactionState->waitingFor, transState, NULL))
+				FATAL("waitingFor was not %p", transState);
 			throw;
 			}
 		}
 
-	if (!COMPARE_EXCHANGE_POINTER(&waitingFor, transaction, NULL))
-		FATAL("waitingFor was not %p",transaction);
+	if (!COMPARE_EXCHANGE_POINTER(&transactionState->waitingFor, transState, NULL))
+		FATAL("waitingFor was not %p", transState);
 
-	state = (State)transaction->state;
-	transaction->release();
+	state = (State)transState->state;
 
-	return state;
-}
+	transState->release();
 
-void Transaction::waitForTransaction()
-{
-	/***
-	Thread *exclusiveThread = syncActive.getExclusiveThread();
-	
-	if (exclusiveThread)
-		{
-		char buffer[1024];
-		connection->getCurrentStatement(buffer, sizeof(buffer));
-		Log::debug("Blocking on %d: %s\n", exclusiveThread->threadId, buffer);
-		}
-	***/
-	
-	Sync sync(&syncIsActive, "Transaction::waitForTransaction(2)");
-	sync.lock(Shared, falcon_lock_wait_timeout * 1000);
+	return state;
 }
 
 void Transaction::addRef()
@@ -1339,7 +1369,7 @@ void Transaction::releaseRecordLocks(voi
 void Transaction::print(void)
 {
 	Log::debug("  %p Id %d, state %d, updates %d, wrtPend %d, records %d\n",
-			this, transactionId, state, hasUpdates, writePending, 
+			this, transactionId, transactionState->state, hasUpdates, writePending, 
 			firstRecord != NULL);
 }
 
@@ -1411,10 +1441,10 @@ void Transaction::getInfo(InfoTable* inf
 	// Need to decide if we want to include the startEvent and endEvent
 	// in this table.
 
-	if (!(state == Available))
+	if (!(transactionState->state == Available))
 		{
 		int n = 0;
-		infoTable->putString(n++, stateNames[state]);
+		infoTable->putString(n++, stateNames[transactionState->state]);
 		infoTable->putInt(n++, mySqlThreadId);
 		infoTable->putInt(n++, transactionId);
 		infoTable->putInt(n++, hasUpdates);
@@ -1422,7 +1452,7 @@ void Transaction::getInfo(InfoTable* inf
 		infoTable->putInt(n++, 0);  // Number of dependencies, will be removed
 		infoTable->putInt(n++, 0); //  was oldestActive);
 		infoTable->putInt(n++, firstRecord != NULL);
-		infoTable->putInt(n++, (waitingFor) ? waitingFor->transactionId : 0);
+		infoTable->putInt(n++, (transactionState->waitingFor) ?
transactionState->waitingFor->transactionId : 0);
 		
 		char buffer[512];
 		
@@ -1557,5 +1587,5 @@ void Transaction::validateRecords(void)
 
 bool Transaction::committedBefore(TransId transactionId)
 {
-	return (commitId && commitId < transactionId);
+	return (transactionState->commitId && transactionState->commitId <
transactionId);
 }

=== modified file 'storage/falcon/Transaction.h'
--- a/storage/falcon/Transaction.h	2009-03-07 01:37:19 +0000
+++ b/storage/falcon/Transaction.h	2009-03-23 14:57:48 +0000
@@ -27,6 +27,7 @@
 #include "SyncObject.h"
 #include "SerialLog.h"
 #include "SavePoint.h"
+#include "TransactionState.h"
 
 static const int NO_TRANSACTION = 0;
 
@@ -44,27 +45,6 @@ class InfoTable;
 class Thread;
 class TransactionManager;
 
-// Transaction States
-
-enum State {
-	Active,					// 0
-	Limbo,					// 1
-	Committed,				// 2
-	RolledBack,				// 3
-
-	// The following are 'relative states'.  See getRelativeState()
-
-	Us,						// 4
-	CommittedVisible,		// 5
-	CommittedInvisible,		// 6
-	WasActive,				// 7
-	Deadlock,				// 8
-	
-	// And the remaining are for transactions pending reuse
-	
-	Available,				// 9
-	Initializing			// 10
-	};
 
 struct TransState {
 	Transaction	*transaction;
@@ -87,12 +67,13 @@ public:
 	Transaction(Connection *connection, TransId seq);
 
 	State		getRelativeState(Record* record, uint32 flags);
-	State		getRelativeState (Transaction *transaction, TransId transId, uint32 flags);
+	State		getRelativeState (TransactionState* ts, TransId transId, uint32 flags);
 	void		removeRecordNoLock (RecordVersion *record);
 	void		removeRecord(RecordVersion *record);
 	void		removeRecord (RecordVersion *record, RecordVersion **ptr);
 	void		commitRecords();
 	bool		visible (Transaction *transaction, TransId transId, int forWhat);
+	bool		visible(const TransactionState* transState, int forWhat) const;
 	bool		needToLock(Record* record);
 	void		addRecord (RecordVersion *record);
 	void		prepare(int xidLength, const UCHAR *xid);
@@ -100,9 +81,9 @@ public:
 	void		commit();
 	void		release();
 	void		addRef();
-	void		waitForTransaction();
+	//void		waitForTransaction();
 	bool		waitForTransaction (TransId transId);
-	State		waitForTransaction (Transaction *transaction, TransId transId, bool *deadlock);
+	State		waitForTransaction (TransactionState* ts, TransId transId, bool *deadlock);
 	void		dropTable(Table* table);
 	void		truncateTable(Table* table);
 	bool		hasRecords(Table* table);
@@ -134,19 +115,22 @@ public:
 
 	inline bool isActive()
 		{
-		return state == Active || state == Limbo;
+		return transactionState->state == Active || transactionState->state == Limbo;
+		}
+
+	State getState() const
+		{
+		return static_cast<State>(transactionState->state);
 		}
 
 	Connection		*connection;
 	Database		*database;
 	TransactionManager	*transactionManager;
 	TransId			transactionId;  // used also as startEvent by dep.mgr.
-	TransId			commitId;       // used as commitEvent by dep.mgr.
 	TransId			blockedBy;
 	int				curSavePointId;
 	Transaction		*next;			// next in database
 	Transaction		*prior;			// next in database
-	volatile	Transaction		*waitingFor;
 	SavePoint		*savePoints;
 	SavePoint		*freeSavePoints;
 	SavePoint		localSavePoints[LOCAL_SAVE_POINTS];
@@ -167,7 +151,6 @@ public:
 	bool			pendingPageWrites;
 	bool			hasLocks;
 	SyncObject		syncObject;
-	SyncObject		syncIsActive;		// locked while transaction is active
 	SyncObject		syncDeferredIndexes;
 	SyncObject		syncRecords;
 	SyncObject		syncSavepoints;
@@ -183,8 +166,8 @@ public:
 	uint32			deletedRecords;		// active deleted records (exclusive of backllogged ones)
 	RecordVersion	**chillPoint;		// points to a pointer to the first non-chilled record
 	int				scanIndexCount;
+	TransactionState* transactionState;
 
-	volatile INTERLOCK_TYPE	state;
 	volatile INTERLOCK_TYPE	useCount;
 	volatile INTERLOCK_TYPE	inList;
 

=== modified file 'storage/falcon/TransactionManager.cpp'
--- a/storage/falcon/TransactionManager.cpp	2009-03-18 13:31:34 +0000
+++ b/storage/falcon/TransactionManager.cpp	2009-03-23 14:57:48 +0000
@@ -19,6 +19,7 @@
 #include "Engine.h"
 #include "TransactionManager.h"
 #include "Transaction.h"
+#include "TransactionState.h"
 #include "Sync.h"
 #include "Interlock.h"
 #include "SQLError.h"
@@ -40,6 +41,11 @@ static const char THIS_FILE[]=__FILE__;
 volatile int Talloc = 0;  // Temp. will be removed. Used for tracing
 volatile int Tdelete = 0; // new and delete of trans objects.
 
+// These are for debugging to trac number of object allocations
+extern volatile INTERLOCK_TYPE TSalloc;
+extern volatile INTERLOCK_TYPE TSdelete;
+
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -54,7 +60,7 @@ TransactionManager::TransactionManager(D
 	priorCommitted = 0;
 	priorRolledBack = 0;
 	rolledBackTransaction = new Transaction(database->systemConnection, 0);
-	rolledBackTransaction->state = RolledBack;
+	rolledBackTransaction->transactionState->state = RolledBack;
 	rolledBackTransaction->inList = false;
 	syncObject.setName("TransactionManager::syncObject");
 	activeTransactions.syncObject.setName("TransactionManager::activeTransactions");
@@ -68,7 +74,7 @@ TransactionManager::~TransactionManager(
 	for (Transaction *transaction; (transaction = activeTransactions.first);)
 		{
 		transaction->inList = false;
-		transaction->state = Committed;
+		transaction->transactionState->state = Committed;
 		activeTransactions.first = transaction->next;
 		transaction->release();
 		}
@@ -113,8 +119,8 @@ Transaction* TransactionManager::startTr
 	Transaction *transaction;
 
 	for(transaction = activeTransactions.first; transaction; transaction =
transaction->next)
-		if (transaction->state == Available)
-			if (COMPARE_EXCHANGE(&transaction->state, Available, Initializing))
+		if (transaction->transactionState->state == Available)
+			if (COMPARE_EXCHANGE(&transaction->transactionState->state, Available,
Initializing))
 				{
 				transaction->initialize(connection, INTERLOCKED_INCREMENT(transactionSequence));
 				return transaction;
@@ -214,7 +220,7 @@ void TransactionManager::commitByXid(int
 		again = false;
 		
 		for (Transaction *transaction = activeTransactions.first; transaction; transaction =
transaction->next)
-			if (transaction->state == Limbo && transaction->isXidEqual(xidLength,
xid))
+			if (transaction->getState() == Limbo &&
transaction->isXidEqual(xidLength, xid))
 				{
 				sync.unlock();
 				transaction->commit();
@@ -235,7 +241,7 @@ void TransactionManager::rollbackByXid(i
 		again = false;
 		
 		for (Transaction *transaction = activeTransactions.first; transaction; transaction =
transaction->next)
-			if (transaction->state == Limbo && transaction->isXidEqual(xidLength,
xid))
+			if (transaction->getState() == Limbo &&
transaction->isXidEqual(xidLength, xid))
 				{
 				sync.unlock();
 				transaction->rollback();
@@ -324,8 +330,8 @@ void TransactionManager::purgeTransactio
 	Transaction* transaction = committedTransactions.first;
 
 	while ((transaction != NULL) &&
-		   (transaction->state == Committed) &&
-		   (transaction->commitId <= oldestActive) &&
+		   (transaction->getState() == Committed) &&
+		   (transaction->transactionState->commitId <= oldestActive) &&
 		   !transaction->writePending)
 		{
 		transaction->commitRecords();
@@ -365,10 +371,10 @@ void TransactionManager::getSummaryInfo(
 	
 	for (transaction = activeTransactions.first; transaction; transaction =
transaction->next)
 		{
-		if (transaction->state == Active)
+		if (transaction->getState() == Active)
 			++numberActive;
 			
-		if (transaction->state == Committed)
+		if (transaction->getState() == Committed)
 			++numberPendingCommit;
 		}
 	syncActive.unlock();
@@ -398,13 +404,13 @@ void TransactionManager::reportStatistic
 	time_t maxTime = 0;
 	
 	for (transaction = activeTransactions.first; transaction; transaction =
transaction->next)
-		if (transaction->state == Active)
+		if (transaction->getState() == Active)
 			{
 			++active;
 			time_t ageTime = database->deltaTime - transaction->startTime;
 			maxTime = MAX(ageTime, maxTime);
 			}
-		else if (transaction->state == Available)
+		else if (transaction->getState() == Available)
 			{
 			++available;
 			}
@@ -455,7 +461,7 @@ Transaction* TransactionManager::findTra
 
 void TransactionManager::removeTransaction(Transaction* transaction)
 {
-	if (transaction->state == Committed)
+	if (transaction->getState() == Committed)
 		{
 		Sync sync(&committedTransactions.syncObject,
"TransactionManager::removeTransaction(1)");
 		sync.lock(Exclusive);
@@ -488,7 +494,7 @@ void TransactionManager::printBlockage(v
 	sync.lock (Shared);
 
 	for (Transaction *trans = activeTransactions.first; trans; trans = trans->next)
-		if (trans->state == Active && !trans->waitingFor)
+		if (trans->getState() == Active &&
!trans->transactionState->waitingFor)
 			trans->printBlocking(0);
 
 	Synchronize::freezeSystem();
@@ -497,6 +503,6 @@ void TransactionManager::printBlockage(v
 void TransactionManager::printBlocking(Transaction* transaction, int level)
 {
 	for (Transaction *trans = activeTransactions.first; trans; trans = trans->next)
-		if (trans->state == Active && trans->waitingFor == transaction)
+		if (trans->getState() == Active && trans->transactionState->waitingFor
== transaction->transactionState)
 			trans->printBlocking(level);
 }

=== added file 'storage/falcon/TransactionState.cpp'
--- a/storage/falcon/TransactionState.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/falcon/TransactionState.cpp	2009-03-23 14:57:48 +0000
@@ -0,0 +1,48 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+
+#include "TransactionState.h"
+#include "Interlock.h"
+#include "Sync.h"
+
+extern uint		falcon_lock_wait_timeout;
+
+TransactionState::TransactionState() : commitId(0), waitingFor(NULL), useCount(1)
+{
+	syncIsActive.setName("TransactionState::syncIaActive");
+}
+
+
+void TransactionState::waitForTransaction()
+{
+	Sync sync(&syncIsActive, "TransactionState::waitForTransaction");
+	sync.lock(Shared, falcon_lock_wait_timeout * 1000);
+}
+
+
+void TransactionState::addRef()
+{
+	INTERLOCKED_INCREMENT(useCount);
+}
+
+
+void TransactionState::release()
+{
+	ASSERT(useCount > 0);
+
+	if (INTERLOCKED_DECREMENT(useCount) == 0)
+		delete this;
+}

=== added file 'storage/falcon/TransactionState.h'
--- a/storage/falcon/TransactionState.h	1970-01-01 00:00:00 +0000
+++ b/storage/falcon/TransactionState.h	2009-03-23 14:57:48 +0000
@@ -0,0 +1,79 @@
+/* Copyright (C) 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#if !defined(TRANSACTION_STATE_H)
+#define TRANSACTION_STATE_H
+
+#include "Engine.h"
+#include "SyncObject.h"
+
+// Transaction States
+
+enum State {
+	Active,					// 0
+	Limbo,					// 1
+	Committed,				// 2
+	RolledBack,				// 3
+
+	// The following are 'relative states'.  See getRelativeState()
+
+	Us,						// 4
+	CommittedVisible,		// 5
+	CommittedInvisible,		// 6
+	WasActive,				// 7
+	Deadlock,				// 8
+	
+	// And the remaining are for transactions pending reuse
+	
+	Available,				// 9
+	Initializing			// 10
+	};
+
+
+// TransactionState stores the main state information for a Transaction.
+// The reason for having this as a separate class instead of having it
+// stored in the Transaction object is that we want to be able to purge
+// transaction objects earlier than when record versions are scavanged. 
+// To be able to do that we let the TransactionState object live as long
+// as there is RecordVersions refering to it while we purge the Transaction 
+// objects earlier. 
+
+class TransactionState
+{
+public:
+	TransactionState();
+
+	void waitForTransaction();
+
+	bool isActive() const
+	    {
+		return state == Active || state == Limbo;
+	    }
+
+	void addRef();
+	void release();
+
+public:
+	TransId			transactionId;       // used also as startEvent by dep.mgr.
+	TransId			commitId;            // used as commitEvent by dep.mgr.
+	volatile		INTERLOCK_TYPE state;
+	SyncObject 		syncIsActive;
+	volatile TransactionState* waitingFor; // Used for deadlock detection
+
+private:
+	volatile INTERLOCK_TYPE useCount;
+};
+
+#endif


Attachment: [text/bzr-bundle] bzr/vvaintroub@mysql.com-20090323181718-dmzfhsgx1cl0pfal.bundle
Thread
bzr commit into mysql-6.0-falcon-team branch (vvaintroub:3070)Vladislav Vaintroub23 Mar 2009