List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:December 15 2008 11:59am
Subject:bzr commit into mysql-6.0-falcon-team branch (vvaintroub:2937)
View as plain text  
#At file:///G:/bzr/mysql-6.0-falcon/

 2937 Vladislav Vaintroub	2008-12-15 [merge]
      merge from 6.0-falcon-team
modified:
  .bzr-mysql/default.conf
  mysql-test/suite/falcon/r/falcon_bug_32398.result
  mysql-test/suite/falcon/t/disabled.def
  mysql-test/suite/falcon/t/falcon_bug_32398.test
  storage/falcon/Transaction.cpp
  storage/falcon/Transaction.h
  storage/falcon/TransactionManager.cpp
  storage/falcon/TransactionManager.h
  storage/falcon/TransformLib/StringTransform.cpp
  storage/falcon/ha_falcon.cpp

=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	2008-12-09 20:23:30 +0000
+++ b/.bzr-mysql/default.conf	2008-12-11 10:57:28 +0000
@@ -1,5 +1,5 @@
 [MYSQL]
-tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-falcon
+tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-falcon-team
 post_commit_to = commits@stripped
 post_push_to = commits@stripped
-tree_name = mysql-6.0-falcon
+tree_name = mysql-6.0-falcon-team

=== modified file 'mysql-test/suite/falcon/r/falcon_bug_32398.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_32398.result	2008-04-10 11:28:11 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_32398.result	2008-12-15 08:36:44 +0000
@@ -1,7 +1,20 @@
-CREATE TABLESPACE ts1 ADD DATAFILE 'test/ts1.fts' ENGINE=falcon;
-ERROR HY000: Incorrect arguments to DATAFILE
-CREATE TABLESPACE ts1 ADD DATAFILE 'TEST_DIR/master-data/test/ts1.fts'
-ENGINE=falcon;
-ERROR HY000: Incorrect arguments to DATAFILE
-CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.fts' ENGINE=falcon;
-DROP TABLESPACE ts1 ENGINE=falcon;
+*** Bug #32398 ***
+SET @@storage_engine = 'Falcon';
+CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.fts' ENGINE=Falcon;
+CREATE TABLESPACE ts2 ADD DATAFILE 'ts2.MYD' ENGINE=Falcon;
+CREATE TABLESPACE ts3 ADD DATAFILE 'ts3' ENGINE=Falcon;
+CREATE TABLESPACE ts4 ADD DATAFILE 'ts4test' ENGINE=Falcon;
+CREATE TABLESPACE ts5 ADD DATAFILE '' ENGINE=Falcon;
+ERROR HY000: Malformed file path ''
+SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES;
+TABLESPACE_NAME	FILE_NAME
+FALCON_USER	falcon_user.fts
+FALCON_TEMPORARY	falcon_temporary.fts
+ts1	ts1.fts
+ts2	ts2.MYD.fts
+ts3	ts3.fts
+ts4	ts4test.fts
+DROP TABLESPACE ts1 ENGINE=Falcon;
+DROP TABLESPACE ts2 ENGINE=Falcon;
+DROP TABLESPACE ts3 ENGINE=Falcon;
+DROP TABLESPACE ts4 ENGINE=Falcon;

=== modified file 'mysql-test/suite/falcon/t/disabled.def'
--- a/mysql-test/suite/falcon/t/disabled.def	2008-12-10 16:55:09 +0000
+++ b/mysql-test/suite/falcon/t/disabled.def	2008-12-15 08:36:44 +0000
@@ -10,5 +10,4 @@
 #
 ##############################################################################
 
-falcon_bug_32398 : Bug#32398 2008-08-28 HF HF disabled until new fix for this bug is developed
 falcon_bug_28095 : Bug#40636 2008-12-10 hky Disabled until soft server restart works reliable

=== modified file 'mysql-test/suite/falcon/t/falcon_bug_32398.test'
--- a/mysql-test/suite/falcon/t/falcon_bug_32398.test	2008-04-10 11:28:11 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_32398.test	2008-12-15 08:36:44 +0000
@@ -1,14 +1,35 @@
 --source include/have_falcon.inc
 
 #
-# BUG#32398 - Falcon: tablespace file can be table file
+# Bug #32398: Falcon: tablespace file can be table file
 #
-#CREATE TABLE t1(a INT) DATA DIRECTORY='mysql';
---error ER_WRONG_ARGUMENTS
-CREATE TABLESPACE ts1 ADD DATAFILE 'test/ts1.fts' ENGINE=falcon;
---replace_result $MYSQLTEST_VARDIR TEST_DIR
---error ER_WRONG_ARGUMENTS
-eval CREATE TABLESPACE ts1 ADD DATAFILE '$MYSQLTEST_VARDIR/master-data/test/ts1.fts'
-ENGINE=falcon;
-CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.fts' ENGINE=falcon;
-DROP TABLESPACE ts1 ENGINE=falcon;
+--echo *** Bug #32398 ***
+
+# ----------------------------------------------------- #
+# --- Initialisation                                --- #
+# ----------------------------------------------------- #
+let $engine = 'Falcon';
+eval SET @@storage_engine = $engine;
+
+# ----------------------------------------------------- #
+# --- Test                                          --- #
+# ----------------------------------------------------- #
+CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.fts' ENGINE=Falcon;
+CREATE TABLESPACE ts2 ADD DATAFILE 'ts2.MYD' ENGINE=Falcon;
+CREATE TABLESPACE ts3 ADD DATAFILE 'ts3' ENGINE=Falcon;
+CREATE TABLESPACE ts4 ADD DATAFILE 'ts4test' ENGINE=Falcon;
+--error ER_BAD_PATH
+CREATE TABLESPACE ts5 ADD DATAFILE '' ENGINE=Falcon;
+
+# ----------------------------------------------------- #
+# --- Check                                         --- #
+# ----------------------------------------------------- #
+SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES;
+
+# ----------------------------------------------------- #
+# --- Final cleanup                                 --- #
+# ----------------------------------------------------- #
+DROP TABLESPACE ts1 ENGINE=Falcon;
+DROP TABLESPACE ts2 ENGINE=Falcon;
+DROP TABLESPACE ts3 ENGINE=Falcon;
+DROP TABLESPACE ts4 ENGINE=Falcon;

=== modified file 'storage/falcon/Transaction.cpp'
--- a/storage/falcon/Transaction.cpp	2008-11-20 17:05:50 +0000
+++ b/storage/falcon/Transaction.cpp	2008-12-09 23:11:13 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (C) 2006 MySQL AB, 2008 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
@@ -49,6 +49,10 @@
 
 extern uint		falcon_lock_wait_timeout;
 
+extern volatile int Talloc;   // These are temporary for debug tracing
+extern volatile int Tdelete;  // of number of allocated transaction objects.
+
+
 static const char *stateNames [] = {
 	"Active",
 	"Limbo",
@@ -78,8 +82,8 @@ static const char THIS_FILE[]=__FILE__;
 
 Transaction::Transaction(Connection *cnct, TransId seq)
 {
-	states = NULL;
-	statesAllocated = 0;
+	Talloc++;
+
 	savePoints = NULL;
 	freeSavePoints = NULL;
 	useCount = 1;
@@ -90,7 +94,6 @@ Transaction::Transaction(Connection *cnc
 	syncSavepoints.setName("Transaction::syncSavepoints");
 	firstRecord = NULL;
 	lastRecord = NULL;
-	dependencies = 0;
 	initialize(cnct, seq);
 }
 
@@ -101,7 +104,6 @@ void Transaction::initialize(Connection*
 	ASSERT(savePoints == NULL);
 	ASSERT(freeSavePoints == NULL);
 	ASSERT(firstRecord == NULL);
-	ASSERT(dependencies == 0);
 	connection = cnct;
 	isolationLevel = connection->isolationLevel;
 	mySqlThreadId = connection->mySqlThreadId;
@@ -109,6 +111,7 @@ void Transaction::initialize(Connection*
 	TransactionManager *transactionManager = database->transactionManager;
 	systemTransaction = database->systemConnection == connection;
 	transactionId = seq;
+	commitId = 0;
 	chillPoint = &firstRecord;
 	commitTriggers = false;
 	hasUpdates = false;
@@ -132,7 +135,6 @@ void Transaction::initialize(Connection*
 	debugThawedRecords = 0;
 	debugThawedBytes = 0;
 	committedRecords = 0;
-	numberStates = 0;
 	blockedBy = 0;
 	deletedRecords = 0;
 	inList = true;
@@ -160,46 +162,13 @@ void Transaction::initialize(Connection*
 	syncIsActive.lock(NULL, Exclusive);
 	Transaction *oldest = transactionManager->findOldest();
 	oldestActive = (oldest) ? oldest->transactionId : transactionId;
-	int count = transactionManager->activeTransactions.count;
-	
-	if (count > statesAllocated)
-		{
-		delete [] states;
-		statesAllocated = count;
-		states = new TransState[statesAllocated];
-		}
-
-	if (count)
-		for (Transaction *transaction = transactionManager->activeTransactions.first; transaction; transaction = transaction->next)
-			if (transaction->isActive() && 
-				 !transaction->systemTransaction &&
-				 transaction->transactionId < transactionId)
-				{
-				Sync syncDependency(&transaction->syncObject, "Transaction::initialize(2)");
-				syncDependency.lock(Shared);
-
-				if (transaction->isActive() && 
-					 !transaction->systemTransaction &&
-					 transaction->transactionId < transactionId)
-					{
-					transaction->addRef();
-					INTERLOCKED_INCREMENT(transaction->dependencies);
-					TransState *state = states + numberStates;
-					state->transaction = transaction;
-					state->transactionId = transaction->transactionId;
-					state->state = transaction->state;
-					++numberStates;
-					ASSERT(transaction->transactionId == state->transactionId);
-					}
-				}
-
 	state = Active;
 }
 
 Transaction::~Transaction()
 {
-	ASSERT(dependencies == 0);
-	
+	Tdelete++;
+
 	if (state == Active)
 		{
 		Log::debug("Deleting apparently active transaction %d\n", transactionId);
@@ -212,7 +181,6 @@ Transaction::~Transaction()
 	if (inList)
 		database->transactionManager->removeTransaction(this);
 
-	delete [] states;
 	delete [] xid;
 	delete backloggedRecords;
 	chillPoint = &firstRecord;
@@ -244,7 +212,6 @@ void Transaction::commit()
 	if (!hasUpdates)
 		{
 		commitNoUpdates();
-		
 		return;
 		}
 
@@ -297,7 +264,6 @@ void Transaction::commit()
 	}
 	syncRec.unlock();
 
-	releaseDependencies();
 	database->flushInversion(this);
 
 	// Transfer transaction from active list to committed list, set committed state
@@ -308,10 +274,21 @@ void Transaction::commit()
 	syncActiveTransactions.lock(Exclusive);
 	syncCommitted.lock(Exclusive);
 
+	// Set the commit transition id for this transaction
+
+    commitId = INTERLOCKED_INCREMENT(transactionManager->transactionSequence);
+
 	transactionManager->activeTransactions.remove(this);
 	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();
 	
@@ -324,9 +301,6 @@ void Transaction::commit()
 	xidLength = 0;
 	
 	// If there's no reason to stick around, just go away
-	
-	if ((dependencies == 0) && !writePending)
-		commitRecords();
 
 	connection = NULL;
 	
@@ -352,7 +326,6 @@ void Transaction::commitNoUpdates(void)
 
 	Sync syncActiveTransactions(&transactionManager->activeTransactions.syncObject, "Transaction::commitNoUpdates(2)");
 	syncActiveTransactions.lock(Shared);
-	releaseDependencies();
 
 	if (xid)
 		{
@@ -363,10 +336,7 @@ void Transaction::commitNoUpdates(void)
 	
 	Sync sync(&syncObject, "Transaction::commitNoUpdates(3)");
 	sync.lock(Exclusive);
-	
-	if (dependencies)
-		transactionManager->expungeTransaction(this);
-	
+
 	// If there's no reason to stick around, just go away
 	
 	connection = NULL;
@@ -441,7 +411,6 @@ void Transaction::rollback()
 
 	ASSERT(writePending);
 	writePending = false;
-	releaseDependencies();
 	
 	if (hasUpdates)
 		database->serialLog->preCommit(this);
@@ -458,11 +427,7 @@ void Transaction::rollback()
 	Sync syncActiveTransactions (&transactionManager->activeTransactions.syncObject, "Transaction::rollback(active)");
 	syncActiveTransactions.lock (Exclusive);
 	++transactionManager->rolledBack;
-	
-	while (dependencies)
-		transactionManager->expungeTransaction(this);
-		
-	ASSERT(dependencies == 0);
+
 	inList = false;
 	transactionManager->activeTransactions.remove(this);
 	syncActiveTransactions.unlock();
@@ -472,20 +437,6 @@ void Transaction::rollback()
 }
 
 
-void Transaction::expungeTransaction(Transaction * transaction)
-{
-	ASSERT(states != NULL || numberStates == 0);
-	
-	for (TransState *s = states, *end = s + numberStates; s < end; ++s)
-		if (s->transaction == transaction)
-			{
-			if (COMPARE_EXCHANGE_POINTER(&s->transaction, transaction, NULL))
-				transaction->releaseDependency();
-
-			break;
-			}
-}
-
 void Transaction::prepare(int xidLen, const UCHAR *xidPtr)
 {
 	if (state != Active)
@@ -750,11 +701,11 @@ bool Transaction::visible(Transaction * 
 	if (transId > transactionId)
 		return false;
 
-	// If the transaction was active when we started, use it's state at that point
+	// If the other transaction committed after we started then it should not
+	// be visible to us
 
-	for (int n = 0; n < numberStates; ++n)
-		if (states [n].transactionId == transId)
-			return false;
+	if (transaction->commitId > transactionId)
+		return false;
 
 	return true;
 }
@@ -790,26 +741,6 @@ bool Transaction::needToLock(Record* rec
 	return false;
 }
 
-void Transaction::releaseDependencies()
-{
-	if (!numberStates)
-		return;
-
-	for (TransState *state = states, *end = states + numberStates; state < end; ++state)
-		{
-		Transaction *transaction = state->transaction;
-
-		if (transaction)
-			{
-			if (COMPARE_EXCHANGE_POINTER(&state->transaction, transaction, NULL))
-				{
-				ASSERT(transaction->transactionId == state->transactionId || transaction->transactionId == 0);
-				ASSERT(transaction->state != Initializing);
-				transaction->releaseDependency();
-				}
-			}
-		}
-}
 
 /*
  *  Transaction is fully mature and about to go away.
@@ -852,6 +783,14 @@ void Transaction::commitRecords()
 
 State Transaction::getRelativeState(Record* record, uint32 flags)
 {
+	// If this is a Record object it has no assosiated transaction
+	// and is always visible
+	
+	if (!record->isVersion())
+		{
+		return CommittedVisible;
+		}
+
 	blockingRecord = record;
 	State state = getRelativeState(record->getTransaction(), record->getTransactionId(), flags);
 	blockingRecord = NULL;
@@ -880,14 +819,22 @@ State Transaction::getRelativeState(Tran
 			// If the transaction is no longer around, and the record is,
 			// then it must be committed.
 
+			// Check if the transaction started after us.
+			// With the old dependency manager this test might have been
+			// hit but with the new dependency manager this will never 
+			// happen. Still leave it in until further evaluation.
+
 			if (transactionId < transId)
 				return CommittedInvisible;
 
 			// Be sure it was not active when we started.
 
-			for (int n = 0; n < numberStates; ++n)
-				if (states [n].transactionId == transId)
-					return CommittedInvisible;
+			// The dependency manager ensures that transactions that were
+			// active at the time this transaction started will not be
+			// deleted at least not until also we are committed.
+			// Since the transaction pointer is NULL here,
+			// the transaction is not deleted and hence was not active at
+			// the time we started.
 			}
 
 		return CommittedVisible;
@@ -962,9 +909,6 @@ void Transaction::writeComplete(void)
 	ASSERT(writePending);
 	ASSERT(state == Committed);
 	releaseDeferredIndexes();
-	
-	if (dependencies == 0)
-		commitRecords();
 
 //	Log::log(LogXARecovery, "%d: WriteComplete %sTransaction %d\n", 
 // 	database->deltaTime, (systemTransaction ? "System " : ""),  transactionId);
@@ -1371,9 +1315,9 @@ void Transaction::releaseRecordLocks(voi
 
 void Transaction::print(void)
 {
-	Log::debug("  %p Id %d, state %d, updates %d, wrtPend %d, states %d, dependencies %d, records %d\n",
+	Log::debug("  %p Id %d, state %d, updates %d, wrtPend %d, records %d\n",
 			this, transactionId, state, hasUpdates, writePending, 
-			numberStates, dependencies, firstRecord != NULL);
+			firstRecord != NULL);
 }
 
 void Transaction::printBlocking(int level)
@@ -1439,7 +1383,12 @@ void Transaction::printBlocking(int leve
 
 void Transaction::getInfo(InfoTable* infoTable)
 {
-	if (!(state == Available && dependencies == 0))
+	// NOTE: The field for number of dependencies will be removed in
+	// a follow-up patch.
+	// Need to decide if we want to include the startEvent and endEvent
+	// in this table.
+
+	if (!(state == Available))
 		{
 		int n = 0;
 		infoTable->putString(n++, stateNames[state]);
@@ -1447,7 +1396,7 @@ void Transaction::getInfo(InfoTable* inf
 		infoTable->putInt(n++, transactionId);
 		infoTable->putInt(n++, hasUpdates);
 		infoTable->putInt(n++, writePending);
-		infoTable->putInt(n++, dependencies);
+		infoTable->putInt(n++, 0);  // Number of dependencies, will be removed
 		infoTable->putInt(n++, oldestActive);
 		infoTable->putInt(n++, firstRecord != NULL);
 		infoTable->putInt(n++, (waitingFor) ? waitingFor->transactionId : 0);
@@ -1464,17 +1413,6 @@ void Transaction::getInfo(InfoTable* inf
 		}
 }
 
-void Transaction::releaseDependency(void)
-{
-	ASSERT(useCount >= 2);
-	ASSERT(dependencies > 0);
-	INTERLOCKED_DECREMENT(dependencies);
-
-	if ((dependencies == 0) && !writePending && firstRecord)
-		commitRecords();
-	releaseCommittedTransaction();
-}
-
 void Transaction::fullyCommitted(void)
 {
 	ASSERT(inList);
@@ -1488,22 +1426,13 @@ void Transaction::fullyCommitted(void)
 
 void Transaction::releaseCommittedTransaction(void)
 {
-	release();
+	// 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.
 
-	if ((useCount == 1) && (state == Committed) && (dependencies == 0) && !writePending)
-		if (COMPARE_EXCHANGE(&inList, (INTERLOCK_TYPE) true, (INTERLOCK_TYPE) false))
-			database->transactionManager->removeCommittedTransaction(this);
+	release();
 }
 
-void Transaction::validateDependencies(bool noDependencies)
-{
-	for (TransState *state = states, *end = states + numberStates; state < end; ++state)
-		if (state->transaction)
-			{
-			ASSERT(!noDependencies);
-			ASSERT(state->transaction->transactionId == state->transactionId);
-			}
-}
 
 void Transaction::printBlockage(void)
 {

=== modified file 'storage/falcon/Transaction.h'
--- a/storage/falcon/Transaction.h	2008-10-02 23:20:47 +0000
+++ b/storage/falcon/Transaction.h	2008-12-03 13:20:17 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (C) 2006 MySQL AB, 2008 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
@@ -90,9 +90,7 @@ public:
 	void		removeRecordNoLock (RecordVersion *record);
 	void		removeRecord(RecordVersion *record);
 	void		removeRecord (RecordVersion *record, RecordVersion **ptr);
-	void		expungeTransaction (Transaction *transaction);
 	void		commitRecords();
-	void		releaseDependencies();
 	bool		visible (Transaction *transaction, TransId transId, int forWhat);
 	bool		needToLock(Record* record);
 	void		addRecord (RecordVersion *record);
@@ -108,7 +106,6 @@ public:
 	void		truncateTable(Table* table);
 	bool		hasRecords(Table* table);
 	void		writeComplete(void);
-	void		releaseDependency(void);
 	int			createSavepoint();
 	void		releaseSavepoint(int savepointId);
 	void		releaseSavepoints(void);
@@ -127,7 +124,6 @@ public:
 	void		fullyCommitted(void);
 	void		releaseCommittedTransaction(void);
 	void		commitNoUpdates(void);
-	void		validateDependencies(bool noDependencies);
 	void		validateRecords(void);
 	void		printBlocking(int level);
 	void		releaseDeferredIndexes(void);
@@ -141,7 +137,8 @@ public:
 
 	Connection		*connection;
 	Database		*database;
-	TransId			transactionId;
+	TransId			transactionId;  // used also as startEvent by dep.mgr.
+	TransId         commitId;       // used as commitEvent by dep.mgr.
 	TransId			oldestActive;
 	TransId			blockedBy;
 	int				curSavePointId;
@@ -157,12 +154,10 @@ public:
 	Bitmap			*backloggedRecords;
 	time_t			startTime;
 	int				deferredIndexCount;
-	int				statesAllocated;
 	int				isolationLevel;
 	int				xidLength;
 	int				mySqlThreadId;
 	UCHAR			*xid;
-	TransState		*states;
 	bool			commitTriggers;
 	bool			systemTransaction;
 	bool			hasUpdates;
@@ -187,9 +182,7 @@ public:
 	RecordVersion	**chillPoint;		// points to a pointer to the first non-chilled record
 	int				scanIndexCount;
 
-	volatile int			numberStates;
 	volatile INTERLOCK_TYPE	state;
-	volatile INTERLOCK_TYPE	dependencies;
 	volatile INTERLOCK_TYPE	useCount;
 	volatile INTERLOCK_TYPE	inList;
 

=== modified file 'storage/falcon/TransactionManager.cpp'
--- a/storage/falcon/TransactionManager.cpp	2008-10-24 10:20:10 +0000
+++ b/storage/falcon/TransactionManager.cpp	2008-12-10 15:53:21 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (C) 2006 MySQL AB, 2008 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
@@ -15,6 +15,7 @@
 
 
 #include <memory.h>
+#include <limits.h>
 #include "Engine.h"
 #include "TransactionManager.h"
 #include "Transaction.h"
@@ -31,11 +32,16 @@
 
 static const int EXTRA_TRANSACTIONS = 10;
 
+static TransId OLD = 0;  // Temporary for debugging
+
 #ifdef _DEBUG
 #undef THIS_FILE
 static const char THIS_FILE[]=__FILE__;
 #endif
 
+volatile int Talloc = 0;  // Temp. will be removed. Used for tracing
+volatile int Tdelete = 0; // new and delete of trans objects.
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -108,42 +114,65 @@ Transaction* TransactionManager::findOld
 	return oldest;
 }
 
+
+TransId TransactionManager::findOldestInActiveList() const
+{
+	// Find the transaction id of the oldest active transaction in the 
+	// active transaction list. If the list is empty, the
+	// latest allocated transaction id will be returned.
+	// This method assumes that the caller have set at least a shared lock
+	// on the active list.
+
+	// Note: Here we operate on a transaction list where we allow 
+	// non-locking transaction allocations and de-allocations from so be 
+	// careful when updating this method.
+
+	// NOTE: This needs to be updated when we allow transaction id to wrap
+
+	TransId oldest = transactionSequence;
+	
+	for (Transaction *transaction = activeTransactions.first; transaction; transaction = transaction->next)
+		{
+		TransId transId = transaction->transactionId;
+		if (transaction->isActive() && (transId != 0 && transId < oldest))
+			oldest = transId;
+		}
+	
+	return oldest;
+}
+
+
 Transaction* TransactionManager::startTransaction(Connection* connection)
 {
+	// Go through the active transaction list to check if there are any
+	// transaction objects in state "Available" that can be re-used.
+	// Note that this is done using a shared lock on the active transaction
+	// list.
+
 	Sync sync (&activeTransactions.syncObject, "TransactionManager::startTransaction");
-	sync.lock (Shared);
+	sync.lock(Shared);
 	Transaction *transaction;
 
-	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
-		if (transaction->state == Available && transaction->dependencies == 0)
+	for(transaction = activeTransactions.first; transaction; transaction = transaction->next)
+		if (transaction->state == Available)
 			if (COMPARE_EXCHANGE(&transaction->state, Available, Initializing))
 				{
-				// Check again that the dependencies are zero. The transaction
-				// object might have been re-use between the previous if-test
-				// and the actual change of state
-
-				if (transaction->dependencies != 0)
-					{
-					// Return the transaction object back to the list
-
-					transaction->state = Available;
-					}
-				else
-					{
-					ASSERT(transaction->dependencies == 0);
-					transaction->initialize(connection, INTERLOCKED_INCREMENT(transactionSequence));
-
-					return transaction;
-					}
+				transaction->initialize(connection, INTERLOCKED_INCREMENT(transactionSequence));
+				return transaction;
 				}
 
 	sync.unlock();
+
+	// We did not find an available transaction object to re-use, 
+	// so we allocate a new and add to the active list
+
 	sync.lock(Exclusive);
 
-	transaction = new Transaction (connection, INTERLOCKED_INCREMENT(transactionSequence));
+	transaction = new Transaction(connection, INTERLOCKED_INCREMENT(transactionSequence));
 	activeTransactions.append(transaction);
 
-	// And, just for yucks, add another 10 Available transactions
+	// Since we have acquired the exclusive lock on the active transaction
+	// list we allocate some extra transaction objects for future use
 
 	for (int n = 0; n < EXTRA_TRANSACTIONS; ++n)
 		{
@@ -300,32 +329,70 @@ void TransactionManager::getTransactionI
 		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);
-	
+
+	purgeTransactionsWithLocks();
+
+}
+
+
+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
+
+	TransId oldestActive = findOldestInActiveList();
+
+	ASSERT(oldestActive >= OLD);   // Temporary for debugging
+	OLD = oldestActive;            // Please ignore
+
 	// Check for any fully mature transactions to ditch
-	
-	for (Transaction *transaction, *next = committedTransactions.first; (transaction = next);)
+  
+    Transaction* transaction = committedTransactions.first;
+
+    while ((transaction != NULL) &&
+		   (transaction->state == Committed) &&
+		   (transaction->commitId < oldestActive) &&
+		   !transaction->writePending)
 		{
-		next = transaction->next;
+		transaction->commitRecords();
 
-		if ((transaction->state == Committed) && 
-			(transaction->dependencies == 0) && 
-			!transaction->writePending)
+		if (COMPARE_EXCHANGE(&transaction->inList, (INTERLOCK_TYPE) true, (INTERLOCK_TYPE) false))
 			{
-			transaction->commitRecords();
+			committedTransactions.remove(transaction);
+			transaction->release();
+			}
+		else
+			{
+			// If the compare and exchange operation failed we re-try this transaction on the next call
 
-			if (COMPARE_EXCHANGE(&transaction->inList, (INTERLOCK_TYPE) true, (INTERLOCK_TYPE) false))
-				{
-				committedTransactions.remove(transaction);
-				transaction->release();
-				}
+			break;
 			}
+
+		transaction = committedTransactions.first;
 		}
 }
 
+
 void TransactionManager::getSummaryInfo(InfoTable* infoTable)
 {
 	Sync syncActive (&activeTransactions.syncObject, "TransactionManager::getSummaryInfo(2)");
@@ -374,7 +441,6 @@ void TransactionManager::reportStatistic
 	Transaction *transaction;
 	int active = 0;
 	int available = 0;
-	int dependencies = 0;
 	time_t maxTime = 0;
 	
 	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
@@ -387,9 +453,6 @@ void TransactionManager::reportStatistic
 		else if (transaction->state == Available)
 			{
 			++available;
-			
-			if (transaction->dependencies)
-				++dependencies;
 			}
 			
 	int pendingCleanup = committedTransactions.count;
@@ -399,8 +462,8 @@ void TransactionManager::reportStatistic
 	priorRolledBack = rolledBack;
 	
 	if ((active || numberCommitted || numberRolledBack) && Log::isActive(LogInfo))
-		Log::log (LogInfo, "%d: Transactions: %d committed, %d rolled back, %d active, %d/%d available, %d post-commit, oldest %d seconds\n",
-				  database->deltaTime, numberCommitted, numberRolledBack, active, available, dependencies, pendingCleanup, maxTime);
+		Log::log (LogInfo, "%d: Transactions: %d committed, %d rolled back, %d active, %d available, %d post-commit, oldest %d seconds\n",
+				  database->deltaTime, numberCommitted, numberRolledBack, active, available, pendingCleanup, maxTime);
 }
 
 void TransactionManager::removeCommittedTransaction(Transaction* transaction)
@@ -412,16 +475,6 @@ void TransactionManager::removeCommitted
 	transaction->release();
 }
 
-void TransactionManager::expungeTransaction(Transaction *transaction)
-{
-	Sync syncActiveTrans(&activeTransactions.syncObject, "TransactionManager::removeTransaction");
-	syncActiveTrans.lock(Shared);
-
-	for (Transaction *trans = activeTransactions.first; trans; trans = trans->next)
-		if ((trans->state != Available && trans->state != Initializing))
-			 //&& trans->transactionId > transaction->transactionId)
-			trans->expungeTransaction(transaction);
-}
 
 Transaction* TransactionManager::findTransaction(TransId transactionId)
 {
@@ -445,24 +498,6 @@ Transaction* TransactionManager::findTra
 	return NULL;
 }
 
-void TransactionManager::validateDependencies(void)
-{
-	Sync syncActive(&activeTransactions.syncObject, "TransactionManager::validateDepedendencies(1)");
-	syncActive.lock(Shared);
-	Transaction *transaction;
-
-	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
-		if (transaction->isActive())
-			transaction->validateDependencies(false);
-			
-	syncActive.unlock();
-
-	Sync syncCommitted(&committedTransactions.syncObject, "TransactionManager::validateDepedendencies(2)");
-	syncCommitted.lock(Shared);
-
-	for (transaction = committedTransactions.first; transaction; transaction = transaction->next)
-		transaction->validateDependencies(true);
-}
 
 void TransactionManager::removeTransaction(Transaction* transaction)
 {

=== modified file 'storage/falcon/TransactionManager.h'
--- a/storage/falcon/TransactionManager.h	2008-08-11 13:22:53 +0000
+++ b/storage/falcon/TransactionManager.h	2008-12-09 09:01:41 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (C) 2006 MySQL AB, 2008 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
@@ -40,13 +40,13 @@ public:
 	void			rollbackByXid(int xidLength, const UCHAR* xid);
 	void			print(void);
 	Transaction*	findOldest(void);
+	TransId			findOldestInActiveList() const;
 	void			getTransactionInfo(InfoTable* infoTable);
 	void			purgeTransactions();
+	void			purgeTransactionsWithLocks();
 	void			getSummaryInfo(InfoTable* infoTable);
 	void			reportStatistics(void);
-	void			expungeTransaction(Transaction *transaction);
 	Transaction* 	findTransaction(TransId transactionId);
-	void 			validateDependencies(void);
 	void			removeCommittedTransaction(Transaction* transaction);
 	void			removeTransaction(Transaction* transaction);
 	void			printBlockage(void);

=== modified file 'storage/falcon/TransformLib/StringTransform.cpp'
--- a/storage/falcon/TransformLib/StringTransform.cpp	2007-09-20 15:44:25 +0000
+++ b/storage/falcon/TransformLib/StringTransform.cpp	2008-12-10 14:11:41 +0000
@@ -39,7 +39,7 @@ StringTransform::StringTransform()
 
 StringTransform::~StringTransform()
 {
-	delete data;
+	delete [] data;
 }
 
 StringTransform::StringTransform(const char *string, bool copyFlag) 

=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp	2008-12-01 22:18:34 +0000
+++ b/storage/falcon/ha_falcon.cpp	2008-12-15 08:36:44 +0000
@@ -2105,7 +2105,8 @@ int StorageInterface::alter_tablespace(h
 {
 	DBUG_ENTER("NfsStorageEngine::alter_tablespace");
 	int ret = 0;
-
+	const char *data_file_name= ts_info->data_file_name;
+	char buff[FN_REFLEN];
 	/*
 	CREATE TABLESPACE tablespace
 		ADD DATAFILE 'file'
@@ -2125,28 +2126,30 @@ int StorageInterface::alter_tablespace(h
 	for NDB only.
 	*/
 
-        /*
-           Sergey Vojtovich is to reconsider this code
-
-	if (ts_info->data_file_name)
+	if (data_file_name)
 		{
-		char buff[FN_REFLEN];
-		size_t dirname_part_length;
-		dirname_part(buff, ts_info->data_file_name, &dirname_part_length);
-		fn_format(buff, buff, mysql_real_data_home, "",
-			MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
-		if (test_if_data_home_dir(buff))
+		size_t length= strlen(data_file_name);
+		if (length <= 4 || strcmp(data_file_name + length - 4, ".fts"))
 			{
-			my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATAFILE");
-			DBUG_RETURN(1);
+			if (!length || length > FN_REFLEN - 5)
+				{
+				my_error(ER_BAD_PATH, MYF(0), data_file_name);
+				DBUG_RETURN(1);
+				}
+			memcpy(buff, data_file_name, length);
+			buff[length]= '.';
+			buff[length + 1]= 'f';
+			buff[length + 2]= 't';
+			buff[length + 3]= 's';
+			buff[length + 4]= '\0';
+			data_file_name= buff;
 			}
 		}
-        */
 
 	switch (ts_info->ts_cmd_type)
 		{
 		case CREATE_TABLESPACE:
-			ret = storageHandler->createTablespace(	ts_info->tablespace_name, ts_info->data_file_name, ts_info->ts_comment);
+			ret = storageHandler->createTablespace(	ts_info->tablespace_name, data_file_name, ts_info->ts_comment);
 			break;
 
 		case DROP_TABLESPACE:
@@ -3673,7 +3676,7 @@ static MYSQL_SYSVAR_UINT(allocation_exte
 static MYSQL_SYSVAR_ULONGLONG(page_cache_size, falcon_page_cache_size,
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
   "The amount of memory to be used for the database page cache.",
-  NULL, NULL, LL(4)<<20, LL(2)<<20, (ulonglong) ~0, LL(1)<<20);
+  NULL, NULL, LL(4)<<20, LL(2)<<20, (ulonglong) max_memory_address, LL(1)<<20);
 
 static MYSQL_THDVAR_BOOL(consistent_read, PLUGIN_VAR_OPCMDARG,
    "Enable Consistent Read Mode for Repeatable Reads",

Thread
bzr commit into mysql-6.0-falcon-team branch (vvaintroub:2937)Vladislav Vaintroub15 Dec