List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:August 27 2008 9:50am
Subject:bzr commit into mysql-6.0 branch (vvaintroub:2781)
View as plain text  
#At file:///C:/bzr/mysql-6.0-falcon/

 2781 Vladislav Vaintroub	2008-08-27 [merge]
      merge 6.0-falcon-team -> 6.0-falcon
modified:
  configure.in
  mysql-test/include/have_falcon.inc
  mysql-test/suite/falcon/r/falcon_bug_22165.result
  mysql-test/suite/falcon/t/falcon_bug_22165.test
  storage/falcon/BackLog.cpp
  storage/falcon/CMakeLists.txt
  storage/falcon/Configuration.cpp
  storage/falcon/IO.cpp
  storage/falcon/Index.cpp
  storage/falcon/Index2RootPage.cpp
  storage/falcon/IndexRootPage.cpp
  storage/falcon/Interlock.h
  storage/falcon/MemMgr.cpp
  storage/falcon/RepositoryVolume.cpp
  storage/falcon/Statement.cpp
  storage/falcon/StorageDatabase.cpp
  storage/falcon/StorageDatabase.h
  storage/falcon/StorageTable.cpp
  storage/falcon/StorageTable.h
  storage/falcon/StorageTableShare.cpp
  storage/falcon/StorageTableShare.h
  storage/falcon/Table.cpp
  storage/falcon/Table.h
  storage/falcon/TableSpace.cpp
  storage/falcon/Transaction.cpp
  storage/falcon/Transaction.h
  storage/falcon/TransactionManager.cpp
  storage/falcon/ha_falcon.cpp
  storage/falcon/ha_falcon.h
  storage/falcon/plug.in

=== modified file 'configure.in'
--- a/configure.in	2008-08-26 06:52:00 +0000
+++ b/configure.in	2008-08-27 09:49:44 +0000
@@ -1797,6 +1797,9 @@ if test "x$mysql_cv_gcc_atomic_builtins"
             [Define to 1 if compiler provides atomic builtins.])
 fi
 
+# Check if we have the atomic_* functions on Solaris
+AC_CHECK_FUNC(atomic_cas_32, AC_DEFINE([HAVE_SOLARIS_ATOMIC], [1], [Define to 1 if Solaris support atomic functions.]))
+
 # Force static compilation to avoid linking problems/get more speed
 AC_ARG_WITH(mysqld-ldflags,
     [  --with-mysqld-ldflags   Extra linking arguments for mysqld],

=== modified file 'mysql-test/include/have_falcon.inc'
--- a/mysql-test/include/have_falcon.inc	2008-03-30 13:57:32 +0000
+++ b/mysql-test/include/have_falcon.inc	2008-08-15 11:06:08 +0000
@@ -1,5 +1,18 @@
+##
+## Checks for the presence of the Falcon storage engine (plugin)
+## by querying the INFORMATION_SCHEMA.ENGINES table.
+##
+## If Falcon is not available, the test using this include file
+## is skipped.
+##
+
+# Do not echo these statements to test results
 --disable_query_log
-# Ignore errors when trying to install the Falcon plugin
---require r/true.require
-SELECT (support = 'YES' OR support = 'DEFAULT' OR support = 'ENABLED') AS `TRUE` FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'Falcon';
+
+# Check if Falcon is available
+let $have_falcon = `SELECT (support = 'YES' OR support = 'DEFAULT' OR support = 'ENABLED') AS 'HAVE_FALCON' FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'Falcon'`;
+if (!$have_falcon)
+{
+  skip Test needs the Falcon storage engine;
+}
 --enable_query_log

=== modified file 'mysql-test/suite/falcon/r/falcon_bug_22165.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_22165.result	2008-08-04 15:53:52 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_22165.result	2008-08-21 13:18:06 +0000
@@ -16,7 +16,10 @@ while v < 10 do
 START TRANSACTION;
 INSERT INTO t1 (a, b) VALUES (v, 'a');
 UPDATE t1 SET c = current_timestamp WHERE a = v;
-COMMIT;
+IF (v < 5)  
+THEN COMMIT;
+ELSE ROLLBACK; 
+END IF;
 SET v = v + 1;
 end while;
 end//

=== modified file 'mysql-test/suite/falcon/t/falcon_bug_22165.test'
--- a/mysql-test/suite/falcon/t/falcon_bug_22165.test	2008-08-04 15:53:52 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_22165.test	2008-08-21 13:18:06 +0000
@@ -30,7 +30,10 @@ begin
     START TRANSACTION;
     INSERT INTO t1 (a, b) VALUES (v, 'a');
     UPDATE t1 SET c = current_timestamp WHERE a = v;
-    COMMIT;
+	IF (v < 5)  
+	  	THEN COMMIT;
+	  	ELSE ROLLBACK; 
+ 	END IF;
     SET v = v + 1;
   end while;
 end//
@@ -57,7 +60,7 @@ while ($i)
   --reap
   connection conn2;
   --reap
-  
+
   dec $i;
 }
 --enable_query_log

=== modified file 'storage/falcon/BackLog.cpp'
--- a/storage/falcon/BackLog.cpp	2008-07-17 13:52:17 +0000
+++ b/storage/falcon/BackLog.cpp	2008-08-18 20:17:15 +0000
@@ -37,7 +37,9 @@ BackLog::BackLog(Database *db, const cha
 {
 	database = db;
 	dbb = new Dbb(database->dbb, 0);
+#ifndef FALCONDB
 	dbb->createPath(fileName);
+#endif
 	dbb->create(fileName, dbb->pageSize, 0, HdrTableSpace, 0, NULL);
 	dbb->noLog = true;
 	dbb->tableSpaceId = -1;

=== modified file 'storage/falcon/CMakeLists.txt'
--- a/storage/falcon/CMakeLists.txt	2008-08-26 18:57:58 +0000
+++ b/storage/falcon/CMakeLists.txt	2008-08-27 09:49:44 +0000
@@ -23,13 +23,11 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
                     . TransformLib
                     ${CMAKE_SOURCE_DIR}/extra/yassl/include
                     ${CMAKE_SOURCE_DIR}/zlib)
-IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR
-   CMAKE_GENERATOR MATCHES "Visual Studio 8")
+IF(MSVC)
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
   SET(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /EHsc")
   SET(CMAKE_CXX_FLAGS_DEBUG_INIT "${CMAKE_CXX_FLAGS_DEBUG_INIT} /EHsc")
-ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR
-      CMAKE_GENERATOR MATCHES "Visual Studio 8")
+ENDIF(MSVC)
 
 SET(FALCON_SOURCES 
 		Agent.cpp 

=== modified file 'storage/falcon/Configuration.cpp'
--- a/storage/falcon/Configuration.cpp	2008-07-17 13:52:17 +0000
+++ b/storage/falcon/Configuration.cpp	2008-08-19 14:27:42 +0000
@@ -151,8 +151,14 @@ Configuration::Configuration(const char 
 		
 		if (!scanDir.isDirectory())
 			{
-			//throw SQLEXCEPTION (RUNTIME_ERROR, "Invalid serial log directory path \"%s\"", falcon_serial_log_dir);
-			serialLogDir = "";
+			fprintf(stderr, 
+					"Falcon: The specified serial log directory, \"%s\", "
+					"does not exist.\n"
+					"Falcon: The serial log directory must be created by "
+					"the user before initializing Falcon.\n", 
+					falcon_serial_log_dir
+				);
+			throw SQLEXCEPTION (FILE_ACCESS_ERROR, "Invalid serial log directory path \"%s\"", falcon_serial_log_dir);
 			}
 		}
 #else

=== modified file 'storage/falcon/IO.cpp'
--- a/storage/falcon/IO.cpp	2008-08-14 16:34:43 +0000
+++ b/storage/falcon/IO.cpp	2008-08-18 20:17:15 +0000
@@ -411,13 +411,17 @@ void IO::declareFatalError()
 	fatalError = true;
 }
 
+
+#ifndef ENOSYS
+#define ENOSYS EEXIST
+#endif
+
+// Make sure parent directories for file exist
 void IO::createPath(const char *fileName)
 {
-	// First, better make sure directories exists
 	JString fname = getPath(fileName);
 
 	char directory [256], *q = directory;
-
 	for (const char *p = fname.getString(); *p;)
 		{
 		char c = *p++;
@@ -427,9 +431,14 @@ void IO::createPath(const char *fileName
 			*q = 0;
 			
 			if (q > directory && q [-1] != ':')
-				if (MKDIR (directory) && errno != EEXIST)
+				{
+				if (MKDIR (directory) && errno != EEXIST && errno != ENOSYS)
+					// ENOSYS is a Solaris speficic workaround, mkdir returns it
+					// on existing automounted NFS directories, instead
+					// of EEXIST.
 					throw SQLError (IO_ERROR, 
 					"can't create directory \"%s\"\n", directory);
+				}
 			}
 		*q++ = c;
 		}

=== modified file 'storage/falcon/Index.cpp'
--- a/storage/falcon/Index.cpp	2008-07-25 18:07:24 +0000
+++ b/storage/falcon/Index.cpp	2008-08-19 03:33:01 +0000
@@ -107,7 +107,6 @@ void Index::init(Table *tbl, const char 
 	DIHashTable = NULL;
 	DIHashTableCounts =  0;
 	DIHashTableSlotsUsed =  0;
-
 	syncDIHash.setName("Index::syncDIHash");
 	syncUnique.setName("Index::syncUnique");
 	deferredIndexes.syncObject.setName("Index::deferredIndexes.syncObject");

=== modified file 'storage/falcon/Index2RootPage.cpp'
--- a/storage/falcon/Index2RootPage.cpp	2008-03-27 06:09:29 +0000
+++ b/storage/falcon/Index2RootPage.cpp	2008-08-25 22:09:13 +0000
@@ -518,9 +518,9 @@ bool Index2RootPage::splitIndexPage(Dbb 
 		
 		leftPage->parentPage = bdb->pageNumber;
 		splitPage->parentPage = bdb->pageNumber;
-		Index2Page::logIndexPage(bdb, transId);
 		Index2Page::logIndexPage(splitBdb, transId);
 		Index2Page::logIndexPage(leftBdb, transId);
+		Index2Page::logIndexPage(bdb, transId);
 
 		splitBdb->release(REL_HISTORY);
 		leftBdb->release(REL_HISTORY);

=== modified file 'storage/falcon/IndexRootPage.cpp'
--- a/storage/falcon/IndexRootPage.cpp	2008-05-14 18:39:57 +0000
+++ b/storage/falcon/IndexRootPage.cpp	2008-08-25 22:09:13 +0000
@@ -552,12 +552,16 @@ bool IndexRootPage::splitIndexPage(Dbb *
 		page->addNode(dbb, &dummy, END_LEVEL);
 		page->addNode(dbb, &leftKey, leftBdb->pageNumber);
 		page->addNode(dbb, &splitKey, splitBdb->pageNumber);
-		
+
 		leftPage->parentPage = bdb->pageNumber;
 		splitPage->parentPage = bdb->pageNumber;
-		IndexPage::logIndexPage(bdb, transId);
+
+		// the order of adding these to the serial log is important.
+		// Recovery must write them in this order incase recovery itself crashes.
+
 		IndexPage::logIndexPage(splitBdb, transId);
 		IndexPage::logIndexPage(leftBdb, transId);
+		IndexPage::logIndexPage(bdb, transId);
 		
 		/***
 		IndexPage::printPage(bdb, false);

=== modified file 'storage/falcon/Interlock.h'
--- a/storage/falcon/Interlock.h	2008-07-10 09:27:51 +0000
+++ b/storage/falcon/Interlock.h	2008-08-21 11:23:44 +0000
@@ -396,7 +396,7 @@ inline INTERLOCK_TYPE interlockedAdd(vol
 	{
 		INTERLOCK_TYPE current= *addend;
 		INTERLOCK_TYPE ret= current + value;
-		if (COMPARE_EXCHANGE_POINTER(addend, current, ret))
+		if (COMPARE_EXCHANGE(addend, current, ret))
 			return ret;
 	}
 #endif

=== modified file 'storage/falcon/MemMgr.cpp'
--- a/storage/falcon/MemMgr.cpp	2008-08-12 22:21:35 +0000
+++ b/storage/falcon/MemMgr.cpp	2008-08-20 16:28:44 +0000
@@ -694,7 +694,7 @@ void MemMgr::corrupt(const char* text)
 #endif
 
 	MemMgrLogDump();
-	throw SQLError (BUG_CHECK, "memory is corrupt: %s", text);
+	FATAL("memory is corrupt: %s", text);
 }
 
 void* MemMgr::memoryIsExhausted(void)

=== modified file 'storage/falcon/RepositoryVolume.cpp'
--- a/storage/falcon/RepositoryVolume.cpp	2008-07-24 08:45:03 +0000
+++ b/storage/falcon/RepositoryVolume.cpp	2008-08-18 20:17:15 +0000
@@ -232,7 +232,9 @@ void RepositoryVolume::makeWritable()
 
 void RepositoryVolume::create()
 {
+#ifndef FALCONDB
 	IO::createPath (fileName);
+#endif
 	dbb->create(fileName, dbb->pageSize, 0, HdrRepositoryFile, 0, NULL);
 	Sync syncDDL(&database->syncSysDDL, "RepositoryVolume::create");
 	Transaction *transaction = database->getSystemTransaction();

=== modified file 'storage/falcon/Statement.cpp'
--- a/storage/falcon/Statement.cpp	2008-07-24 08:45:03 +0000
+++ b/storage/falcon/Statement.cpp	2008-08-18 05:45:29 +0000
@@ -144,7 +144,6 @@ Statement::Statement(Connection *pConnec
 	special = false;
 	active = false;
 	memset (&stats, 0, sizeof (stats));
-	syncObject.setName("Statement::syncObject");
 }
 
 Statement::~Statement()
@@ -2303,16 +2302,10 @@ void Statement::dropIndex(Syntax *syntax
 		throw SQLEXCEPTION (DDL_ERROR, "table %s.%s not defined", (const char*) tableName, schema);
 
 	checkAlterPriv (table);
-	Index *index = table->findIndex (name);
 
-	if (index)
-		{
 		Transaction *sysTransaction = database->getSystemTransaction();
-		table->dropIndex(index);
-		index->deleteIndex(sysTransaction); /* transaction */
-		delete index;
+	table->dropIndex(name, sysTransaction);
 		database->commitSystemTransaction();
-		}
 
 	Index::deleteIndex (database, schema, name);
 	database->commitSystemTransaction();

=== modified file 'storage/falcon/StorageDatabase.cpp'
--- a/storage/falcon/StorageDatabase.cpp	2008-07-24 08:45:03 +0000
+++ b/storage/falcon/StorageDatabase.cpp	2008-08-18 20:17:15 +0000
@@ -156,7 +156,9 @@ Connection* StorageDatabase::createDatab
 	try
 		{
 		masterConnection = getConnection();
+#ifndef FALCONDB
 		IO::createPath(filename);
+#endif
 		masterConnection->createDatabase(name, filename, ACCOUNT, PASSWORD, threads);
 		Statement *statement = masterConnection->createStatement();
 		
@@ -688,7 +690,7 @@ int StorageDatabase::updateRow(StorageCo
 	return 0;
 }
 
-int StorageDatabase::createIndex(StorageConnection *storageConnection, Table* table, const char* indexName, const char* sql)
+int StorageDatabase::createIndex(StorageConnection *storageConnection, Table* table, const char* sql)
 {
 	Connection *connection = storageConnection->connection;
 	Statement *statement = connection->createStatement();
@@ -713,7 +715,7 @@ int StorageDatabase::createIndex(Storage
 	return 0;
 }
 
-int StorageDatabase::dropIndex(StorageConnection *storageConnection, Table* table, const char* indexName, const char* sql)
+int StorageDatabase::dropIndex(StorageConnection *storageConnection, Table* table, const char* sql)
 {
 	Connection *connection = storageConnection->connection;
 	Statement *statement = connection->createStatement();
@@ -746,17 +748,6 @@ int StorageDatabase::renameTable(Storage
 		{
 		Database *database = connection->database;
 		Sequence *sequence = connection->findSequence(schemaName, table->name);
-		int numberIndexes = 0;
-		int firstIndex = 0;
-		Index *index;
-
-		for (index = table->indexes; index; index = index->next)
-			{
-			if (index->type == PrimaryKey)
-				firstIndex = 1;
-
-			++numberIndexes;
-			}
 
 		Sync syncDDL(&database->syncSysDDL, "StorageDatabase::renameTable(1)");
 		syncDDL.lock(Exclusive);
@@ -764,19 +755,6 @@ int StorageDatabase::renameTable(Storage
 		Sync syncTables(&database->syncTables, "StorageDatabase::renameTable(2)");
 		syncTables.lock(Exclusive);
 		
-		for (int n = firstIndex; n < numberIndexes; ++n)
-			{
-			char indexName[256];
-			sprintf(indexName, "%s$%d", (const char*) table->name, n);
-			Index *index = table->findIndex(indexName);
-
-			if (index)
-				{
-				sprintf(indexName, "%s$%d", tableName, n);
-				index->rename(indexName);
-				}
-			}
-
 		table->rename(schemaName, tableName);
 
 		if (sequence)

=== modified file 'storage/falcon/StorageDatabase.h'
--- a/storage/falcon/StorageDatabase.h	2008-07-24 08:45:03 +0000
+++ b/storage/falcon/StorageDatabase.h	2008-08-18 05:45:29 +0000
@@ -40,7 +40,7 @@ class IndexWalker;
 
 CLASS(Field);
 
-struct StorageIndexDesc;
+class StorageIndexDesc;
 struct StorageKey;
 struct StorageBlob;
 struct StorageSegment;
@@ -61,7 +61,6 @@ public:
 	int					savepointRollback(Connection* connection, int savePoint);
 	int					deleteTable(StorageConnection* storageConnection,StorageTableShare *tableShare);
 	int					truncateTable(StorageConnection* storageConnection, StorageTableShare *tableShare);
-	int					createIndex(StorageConnection *storageConnection, Table* table, StorageIndexDesc* indexDesc);
 	int					renameTable(StorageConnection* storageConnection, Table* table, const char* newName, const char *schemaName);
 	Bitmap*				indexScan(Index* index, StorageKey *lower, StorageKey *upper, int searchFlags, StorageConnection* storageConnection, Bitmap *bitmap);
 	IndexWalker*		indexPosition(Index* index, StorageKey* lower, StorageKey* upper, int searchFlags, StorageConnection* storageConnection);
@@ -74,8 +73,8 @@ public:
 	void				freeBlob(StorageBlob *blob);
 	void				close(void);
 	void				validateCache(void);
-	int					createIndex(StorageConnection* storageConnection, Table* table, const char* indexName, const char* sql);
-	int					dropIndex(StorageConnection* storageConnection, Table* table, const char* indexName, const char* sql);
+	int					createIndex(StorageConnection* storageConnection, Table* table, const char* sql);
+	int					dropIndex(StorageConnection* storageConnection, Table* table, const char* sql);
 	int					insert(Connection* connection, Table* table, Stream* stream);
 	
 	int					nextRow(StorageTable* storageTable, int recordNumber, bool lockForUpdate);

=== modified file 'storage/falcon/StorageTable.cpp'
--- a/storage/falcon/StorageTable.cpp	2008-08-11 13:22:53 +0000
+++ b/storage/falcon/StorageTable.cpp	2008-08-22 06:47:40 +0000
@@ -51,11 +51,13 @@ StorageTable::StorageTable(StorageConnec
 	upperBound = lowerBound = NULL;
 	record = NULL;
 	recordLocked = false;
-	haveTruncateLock = false;
+	indexesLocked = false;
 }
 
 StorageTable::~StorageTable(void)
 {
+	clearCurrentIndex();
+	
 	if (bitmap)
 		((Bitmap*) bitmap)->release();
 
@@ -94,12 +96,12 @@ int StorageTable::deleteTable(void)
 int StorageTable::truncateTable(void)
 {
 	clearRecord();
+	clearCurrentIndex();
+	
 	int ret = share->truncateTable(storageConnection);
 	return ret;
 }
 
-
-
 int StorageTable::insert(void)
 {
 	try
@@ -139,6 +141,16 @@ int StorageTable::updateRow(int recordNu
 	return 0;
 }
 
+int StorageTable::createIndex(StorageIndexDesc *indexDesc, const char *sql)
+{
+	return share->createIndex(storageConnection, indexDesc, sql);
+}
+
+int StorageTable::dropIndex(StorageIndexDesc *indexDesc, const char *sql)
+{
+	return share->dropIndex(storageConnection, indexDesc, sql);
+}
+
 int StorageTable::next(int recordNumber, bool lockForUpdate)
 {
 	recordLocked = false;
@@ -174,21 +186,51 @@ void StorageTable::transactionEnded(void
 {
 }
 
-int StorageTable::setIndex(int numberIndexes, int indexId, StorageIndexDesc* storageIndex)
+int StorageTable::setCurrentIndex(int indexId)
 {
-	if (!(currentIndex = share->getIndex(numberIndexes, indexId, storageIndex)))
+	if (!indexesLocked)
+		{
+		share->lockIndexes();
+		indexesLocked = true;
+		}
+	
+	if (!(currentIndex = share->getIndex(indexId)))
+{
+		clearCurrentIndex();
 		return StorageErrorNoIndex;
-
+		}
+		
 	upperBound = lowerBound = NULL;
 	searchFlags = 0;
+	return 0;
+}
 	
+int StorageTable::clearCurrentIndex()
+{
+	if (indexesLocked)
+		{
+		share->unlockIndexes();
+		indexesLocked = false;
+		}
+
+	currentIndex = NULL;
+	upperBound = lowerBound = NULL;
+	searchFlags = 0;
 	return 0;
 }
 
+int StorageTable::setIndex(StorageIndexDesc* indexDesc)
+{
+	return share->setIndex(indexDesc);
+}
+
 int StorageTable::indexScan(int indexOrder)
 {
 	if (!currentIndex)
+		{
+		clearCurrentIndex();
 		return StorageErrorNoIndex;
+		}
 	
 	int numberSegments = (upperBound) ?  upperBound->numberSegments : (lowerBound) ? lowerBound->numberSegments : 0;
 	
@@ -203,26 +245,16 @@ int StorageTable::indexScan(int indexOrd
 	return 0;
 }
 
-
 void StorageTable::clearBitmap(void)
 {
 	if (bitmap)
 		((Bitmap*) bitmap)->clear();
 }
 
-int StorageTable::setIndex(int indexId)
-{
-	if (!(currentIndex = share->getIndex(indexId)))
-		return StorageErrorNoIndex;
-	
-	upperBound = lowerBound = NULL;
-	searchFlags = 0;
-	
-	return 0;
-}
-
 void StorageTable::indexEnd(void)
 {
+	clearCurrentIndex();
+	
 	if (bitmap)
 		clearBitmap();
 	
@@ -236,7 +268,10 @@ void StorageTable::indexEnd(void)
 int StorageTable::setIndexBound(const unsigned char* key, int keyLength, int which)
 {
 	if (!currentIndex)
+		{
+		clearCurrentIndex();
 		return StorageErrorNoIndex;
+		}
 
 	if (which & LowerBound)
 		{

=== modified file 'storage/falcon/StorageTable.h'
--- a/storage/falcon/StorageTable.h	2008-08-11 13:22:53 +0000
+++ b/storage/falcon/StorageTable.h	2008-08-22 06:47:40 +0000
@@ -49,8 +49,7 @@ class Record;
 class SyncObject;
 class Format;
 class IndexWalker;
-
-struct StorageIndexDesc;
+class StorageIndexDesc;
 
 class StorageTable
 {
@@ -65,8 +64,6 @@ public:
 	void			clearAlter(void);
 	bool			setAlter(void);
 	
-
-	
 	virtual void	setConnection(StorageConnection* connection);
 	virtual void	clearIndexBounds(void);
 	virtual void	clearRecord(void);
@@ -78,9 +75,10 @@ public:
 	virtual int		deleteTable(void);
 	virtual int		deleteRow(int recordNumber);
 	virtual int		truncateTable(void);
-	virtual int		setIndex(int numberIndexes, int indexId, StorageIndexDesc* storageIndex);
 	virtual int		indexScan(int indexOrder);
-	virtual int		setIndex(int indexId);
+	virtual int		setCurrentIndex(int indexId);
+	virtual int		clearCurrentIndex();
+	virtual int		setIndex(StorageIndexDesc* indexDesc);
 	virtual void	indexEnd(void);
 	virtual int		setIndexBound(const unsigned char* key, int keyLength, int which);
 	virtual int		storeBlob(StorageBlob* blob);
@@ -96,6 +94,8 @@ public:
 	virtual int		fetch(int recordNumber, bool lockForUpdate);
 	
 	virtual int		updateRow(int recordNumber);
+	virtual int		createIndex(StorageIndexDesc *indexDesc, const char *sql);
+	virtual int		dropIndex(StorageIndexDesc *indexDesc, const char *sql);
 	virtual const unsigned char* getEncoding(int fieldIndex);
 	virtual const char*			 getName(void);
 	virtual const char*			 getSchemaName(void);
@@ -128,7 +128,7 @@ public:
 	Stream				insertStream;
 	int					searchFlags;
 	bool				recordLocked;
-	bool				haveTruncateLock;
+	bool				indexesLocked;
 };
 
 #endif

=== modified file 'storage/falcon/StorageTableShare.cpp'
--- a/storage/falcon/StorageTableShare.cpp	2008-08-04 15:53:52 +0000
+++ b/storage/falcon/StorageTableShare.cpp	2008-08-22 06:47:40 +0000
@@ -33,14 +33,11 @@
 #include "PreparedStatement.h"
 #include "ResultSet.h"
 #include "SQLException.h"
+#include "CmdGen.h"
 
 static const char *FALCON_TEMPORARY		= "/falcon_temporary";
 static const char *DB_ROOT				= ".fts";
 
-#ifndef ONLINE_ALTER
-//#define ONLINE_ALTER
-#endif
-
 #if defined(_WIN32) && MYSQL_VERSION_ID < 0x50100
 #define IS_SLASH(c)	(c == '/' || c == '\\')
 #else
@@ -52,6 +49,43 @@ static const char *DB_ROOT				= ".fts";
 static const char THIS_FILE[]=__FILE__;
 #endif
 
+StorageIndexDesc::StorageIndexDesc()
+{
+	id = 0;
+	unique = 0;
+	primaryKey = 0;
+	numberSegments = 0;
+	index = NULL;
+	segmentRecordCounts = NULL;
+	next = NULL;
+	name[0] = '\0';
+	rawName[0] = '\0';
+};
+
+StorageIndexDesc::StorageIndexDesc(const StorageIndexDesc *indexInfo)
+{
+	if (indexInfo)
+		*this = *indexInfo;
+	else
+		{
+		id = 0;
+		unique = 0;
+		primaryKey = 0;
+		numberSegments = 0;
+		segmentRecordCounts = NULL;
+		name[0] = '\0';
+		rawName[0] = '\0';
+		}
+		
+	index = NULL;
+	next = NULL;
+	prev = NULL;
+};
+
+StorageIndexDesc::~StorageIndexDesc(void)
+{
+}
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -63,13 +97,15 @@ StorageTableShare::StorageTableShare(Sto
 	impure = new UCHAR[lockSize];
 	initialized = false;
 	table = NULL;
-	indexes = NULL;
 	format = NULL;
 	syncObject = new SyncObject;
 	syncObject->setName("StorageTableShare::syncObject");
+	syncIndexes = new SyncObject;
+	syncIndexes->setName("StorageTableShare::syncIndexes");
 	sequence = NULL;
 	tempTable = tempTbl;
 	setPath(path);
+	indexes = NULL;
 
 	if (tempTable)
 		tableSpace = TEMPORARY_TABLESPACE;
@@ -82,18 +118,16 @@ StorageTableShare::StorageTableShare(Sto
 StorageTableShare::~StorageTableShare(void)
 {
 	delete syncObject;
+	delete syncIndexes;
 	delete [] impure;
 	
 	if (storageDatabase)
 		storageDatabase->release();
 		
-	if (indexes)
+	for (StorageIndexDesc *indexDesc; (indexDesc = indexes);)
 		{
-		for (int n = 0; n < numberIndexes; ++n)
-			delete indexes[n];
-			
-		delete [] indexes;
-		indexes = NULL;
+		indexes = indexDesc->next;
+		delete indexDesc;
 		}
 }
 
@@ -107,6 +141,16 @@ void StorageTableShare::unlock(void)
 	syncObject->unlock();
 }
 
+void StorageTableShare::lockIndexes(bool exclusiveLock)
+{
+	syncIndexes->lock(NULL, (exclusiveLock) ? Exclusive : Shared);
+}
+
+void StorageTableShare::unlockIndexes(void)
+{
+	syncIndexes->unlock();
+}
+
 int StorageTableShare::open(void)
 {
 	if (!table)
@@ -189,7 +233,7 @@ int StorageTableShare::truncateTable(Sto
 	return res;
 }
 
-void StorageTableShare::cleanupFieldName(const char* name, char* buffer, int bufferLength)
+const char* StorageTableShare::cleanupFieldName(const char* name, char* buffer, int bufferLength)
 {
 	char *q = buffer;
 	char *end = buffer + bufferLength - 1;
@@ -211,6 +255,8 @@ void StorageTableShare::cleanupFieldName
 		}
 
 	*q = 0;
+	
+	return buffer;
 }
 
 const char* StorageTableShare::cleanupTableName(const char* name, char* buffer, int bufferLength, char *schema, int schemaLength)
@@ -239,20 +285,96 @@ const char* StorageTableShare::cleanupTa
 	return buffer;
 }
 
-int StorageTableShare::createIndex(StorageConnection *storageConnection, const char* name, const char* sql)
+char* StorageTableShare::createIndexName(const char *rawName, char *indexName)
+{
+	char nameBuffer[indexNameSize];
+	cleanupFieldName(rawName, nameBuffer, sizeof(nameBuffer));
+	sprintf(indexName, "%s$%s", name.getString(), nameBuffer);
+	return indexName;
+}
+
+int StorageTableShare::createIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql)
 {
 	if (!table)
 		open();
 
-	return storageDatabase->createIndex(storageConnection, table, name, sql);
+	// Lock out other clients before locking the table
+	
+	Sync syncIndex(syncIndexes, "StorageTableShare::createIndex(1)");
+	syncIndex.lock(Exclusive);
+	
+	Sync syncObj(syncObject, "StorageTableShare::createIndex(2)");
+	syncObj.lock(Exclusive);
+	
+	int ret = storageDatabase->createIndex(storageConnection, table, sql);
+	
+	if (!ret)
+		ret = setIndex(indexDesc);
+		
+	return ret;
 }
 
-int StorageTableShare::dropIndex(StorageConnection *storageConnection, const char* name, const char* sql)
+void StorageTableShare::addIndex(StorageIndexDesc *indexDesc)
+{
+	if (!getIndex(indexDesc->id))
+		{
+		if (indexes)
+			{
+			indexDesc->next = indexes;
+			indexDesc->prev = NULL;
+			indexes->prev = indexDesc;
+			}
+		
+		indexes = indexDesc;
+		}
+}
+
+void StorageTableShare::deleteIndex(int indexId)
+{
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
+		if (indexDesc->id == indexId)
+			{
+			if (indexDesc->prev)
+				indexDesc->prev->next = indexDesc->next;
+			else
+				indexes = indexDesc->next;
+				
+			if (indexDesc->next)
+				indexDesc->next->prev = indexDesc->prev;
+				
+			delete indexDesc;	
+			break;
+			}
+}
+
+int StorageTableShare::dropIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql)
 {
 	if (!table)
 		open();
 
-	return storageDatabase->dropIndex(storageConnection, table, name, sql);
+	// Lock out other clients before locking the table
+
+	Sync syncIndex(syncIndexes, "StorageTableShare::dropIndex(1)");
+	syncIndex.lock(Exclusive);
+	
+	Sync syncObj(syncObject, "StorageTableShare::dropIndex(2)");
+	syncObj.lock(Exclusive);
+	
+	int ret = storageDatabase->dropIndex(storageConnection, table, sql);
+	
+	if (!ret)
+		deleteIndex(indexDesc->id);
+				
+	return ret;
+}
+
+void StorageTableShare::deleteIndexes()
+{
+	for (StorageIndexDesc *indexDesc; (indexDesc = indexes);)
+		{
+		indexes = indexDesc->next;
+		delete indexDesc;
+		}
 }
 
 int StorageTableShare::renameTable(StorageConnection *storageConnection, const char* newName)
@@ -274,72 +396,109 @@ int StorageTableShare::renameTable(Stora
 	return ret;
 }
 
-StorageIndexDesc* StorageTableShare::getIndex(int indexCount, int indexId, StorageIndexDesc* indexDesc)
+int StorageTableShare::setIndex(const StorageIndexDesc *indexInfo)
 {
-	// Rebuild array if indexes have been added or dropped
-	
-#ifdef ONLINE_ALTER
+	int ret = 0;
 
-	// TODO: This does not work. It should be done at the time of index creation
+	if (!getIndex(indexInfo->id))
+		{
+		StorageIndexDesc *indexDesc = new StorageIndexDesc(indexInfo);
+		addIndex(indexDesc);
 
-	if (indexes && (numberIndexes != indexCount))
+	// Find the corresponding Falcon index
+	
+	if (indexDesc->primaryKey)
+		indexDesc->index = table->primaryKey;
+	else
 		{
-		Sync sync(syncObject, "StorageTableShare::getIndex");
-		sync.lock(Exclusive);
-		StorageIndexDesc **oldIndexes = indexes;
-		StorageIndexDesc **newIndexes = new StorageIndexDesc*[indexCount];
-		memset(newIndexes, 0, indexCount * sizeof(StorageIndexDesc*));
+		char indexName[indexNameSize];
+			sprintf(indexName, "%s$%s", name.getString(), indexDesc->name);
+		indexDesc->index = table->findIndex(indexName);
+		}
+
+	if (indexDesc->index)
+		indexDesc->segmentRecordCounts = indexDesc->index->recordsPerSegment;
+	else
+		ret = StorageErrorNoIndex;
+		}
 		
-		for (int n = 0; n < numberIndexes; ++n)
-			newIndexes[n] = indexes[n];
+	return ret;
+}
+
+StorageIndexDesc* StorageTableShare::getIndex(int indexId)
+{
+	if (!indexes)
+		return NULL;
+			
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
+		if (indexDesc->id == indexId)
+			return indexDesc;
 		
-		indexes = newIndexes;
-		numberIndexes = indexCount;
-		delete [] oldIndexes;
-		}
-#endif
-	
+	return NULL;
+}
+
+StorageIndexDesc* StorageTableShare::getIndex(int indexId, StorageIndexDesc *indexDesc)
+{
 	if (!indexes)
-		{
-		indexes = new StorageIndexDesc*[indexCount];
-		memset(indexes, 0, indexCount * sizeof(StorageIndexDesc*));
-		numberIndexes = indexCount;
-		}
-	
-	if (indexId >= numberIndexes)
 		return NULL;
 	
-	StorageIndexDesc *index = indexes[indexId];
+	Sync sync(syncIndexes, "StorageTableShare::getIndex");
+	sync.lock(Shared);
 	
+	StorageIndexDesc *index = getIndex(indexId);
+			
 	if (index)
-		return index;
+		*indexDesc = *index;
+		
+	return index;
+}
 
-	indexes[indexId] = index = new StorageIndexDesc;
-	*index = *indexDesc;
+StorageIndexDesc* StorageTableShare::getIndex(const char *name)
+{
+	if (!indexes)
+		return NULL;
 	
-	if (indexDesc->primaryKey)
-		index->index = table->primaryKey;
-	else
-		{
-		char indexName[150];
-		sprintf(indexName, "%s$%d", (const char*) name, indexId);
-		index->index = storageDatabase->findIndex(table, indexName);
-		}
+	Sync sync(syncIndexes, "StorageTableShare::getIndex(name)");
+	sync.lock(Shared);
+	
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
+		if (indexDesc->name == name)
+			return indexDesc;
+			
+	return NULL;
+}
 
-	if (index->index)
-		index->segmentRecordCounts = index->index->recordsPerSegment;
-	else
-		index = NULL;
+int StorageTableShare::getIndexId(const char* schemaName, const char* indexName)
+{
+	if (!indexes)
+		return -1;
 	
-	return index;
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
+		{
+		Index *index = indexDesc->index;
+	
+		if (index)
+			if (strcmp(index->getIndexName(), indexName) == 0 &&
+				strcmp(index->getSchemaName(), schemaName) == 0)
+				return indexDesc->id;
+		}
+		
+	return -1;
 }
 
-StorageIndexDesc* StorageTableShare::getIndex(int indexId)
+int StorageTableShare::haveIndexes(int indexCount)
 {
-	if (!indexes || indexId >= numberIndexes)
-		return NULL;
+	if (!indexes)
+		return false;
 	
-	return indexes[indexId];
+	int n = 0;
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next, n++)
+		{
+		if (!indexDesc->index)
+			return false;
+		}
+
+	return (n == indexCount);
 }
 
 INT64 StorageTableShare::getSequenceValue(int delta)
@@ -363,38 +522,6 @@ int StorageTableShare::setSequenceValue(
 		sequence->update(value - current, NULL);
 
 	return 0;
-}
-
-int StorageTableShare::getIndexId(const char* schemaName, const char* indexName)
-{
-	if (indexes)
-		for (int n = 0; n < numberIndexes; ++n)
-			{
-			Index *index = indexes[n]->index;
-			
-			if (strcmp(index->getIndexName(), indexName) == 0 &&
-				strcmp(index->getSchemaName(), schemaName) == 0)
-				return n;
-			}
-		
-	return -1;
-}
-
-int StorageTableShare::haveIndexes(int indexCount)
-{
-	if (indexes == NULL)
-		return false;
-		
-#ifdef ONLINE_ALTER
-	if (indexCount != numberIndexes)
-		return false;
-#endif	
-	
-	for (int n = 0; n < numberIndexes; ++n)
-		if (indexes[n]== NULL)
-			return false;
-	
-	return true;
 }
 
 void StorageTableShare::setTablePath(const char* path, bool tmp)

=== modified file 'storage/falcon/StorageTableShare.h'
--- a/storage/falcon/StorageTableShare.h	2008-08-04 15:53:52 +0000
+++ b/storage/falcon/StorageTableShare.h	2008-08-22 06:47:40 +0000
@@ -26,6 +26,7 @@
 typedef __int64			INT64;
 
 static const int MaxIndexSegments	= 16;
+static const int indexNameSize		= 257;
 
 class StorageDatabase;
 class StorageConnection;
@@ -47,14 +48,25 @@ struct StorageSegment {
 	void			*mysql_charset;
 	};
 
-struct StorageIndexDesc {
+// StorageIndexDesc maps a server-side index to a Falcon index
+class StorageIndexDesc
+{
+public:
+	StorageIndexDesc();
+	StorageIndexDesc(const StorageIndexDesc *indexInfo);
+	virtual ~StorageIndexDesc(void);
+	
+	int			id;
 	int			unique;
 	int			primaryKey;
 	int			numberSegments;
-	const char	*name;
+	char		name[indexNameSize];		// clean name
+	char		rawName[indexNameSize];		// original name
 	Index		*index;
 	uint64		*segmentRecordCounts;
 	StorageSegment segments[MaxIndexSegments];
+	StorageIndexDesc *next;
+	StorageIndexDesc *prev;
 	};
 
 
@@ -95,22 +107,29 @@ public:
 	StorageTableShare(StorageHandler *handler, const char * path, const char *tableSpaceName, int lockSize, bool tempTbl);
 	virtual ~StorageTableShare(void);
 	
-	virtual void		lock(bool exclusiveLock);
+	virtual void		lock(bool exclusiveLock=false);
 	virtual void		unlock(void);
-	virtual int			createIndex(StorageConnection *storageConnection, const char* name, const char* sql);
-	virtual int			dropIndex(StorageConnection *storageConnection, const char* name, const char* sql);
+	virtual void		lockIndexes(bool exclusiveLock=false);
+	virtual void		unlockIndexes(void);
+	virtual int			createIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql);
+	virtual int			dropIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql);
+	virtual void		deleteIndexes();
 	virtual int			renameTable(StorageConnection *storageConnection, const char* newName);
 	virtual INT64		getSequenceValue(int delta);
 	virtual int			setSequenceValue(INT64 value);
 	virtual int			haveIndexes(int indexCount);
-	virtual void		cleanupFieldName(const char* name, char* buffer, int bufferLength);
+	virtual const char*	cleanupFieldName(const char* name, char* buffer, int bufferLength);
 	virtual void		setTablePath(const char* path, bool tempTable);
 	virtual void		registerCollation(const char* collationName, void* arg);
 
 	int					open(void);
-	StorageIndexDesc*	getIndex(int indexCount, int indexId, StorageIndexDesc* indexDesc);
+	void				addIndex(StorageIndexDesc *indexDesc);
+	void				deleteIndex(int indexId);
+	int					setIndex(const StorageIndexDesc* indexInfo);
+	void				clearIndex(StorageIndexDesc *indexDesc);
 	StorageIndexDesc*	getIndex(int indexId);
-
+	StorageIndexDesc*	getIndex(int indexId, StorageIndexDesc *indexDesc);
+	StorageIndexDesc*	getIndex(const char *name);
 	int					getIndexId(const char* schemaName, const char* indexName);
 	int					create(StorageConnection *storageConnection, const char* sql, int64 autoIncrementValue);
 	int					upgrade(StorageConnection *storageConnection, const char* sql, int64 autoIncrementValue);
@@ -129,6 +148,7 @@ public:
 
 	static const char*	getDefaultRoot(void);
 	static const char*	cleanupTableName(const char* name, char* buffer, int bufferLength, char *schema, int schemaLength);
+	char*				createIndexName(const char *rawName, char *indexName);
 	
 	JString				name;
 	JString				schemaName;
@@ -140,13 +160,13 @@ public:
 	unsigned char		*impure;
 	int					initialized;
 	SyncObject			*syncObject;
+	SyncObject			*syncIndexes;
 	StorageDatabase		*storageDatabase;
 	StorageHandler		*storageHandler;
 	Table				*table;
-	StorageIndexDesc	**indexes;
+	StorageIndexDesc	*indexes;
 	Sequence			*sequence;
 	Format				*format;						// format for insertion
-	int					numberIndexes;
 	bool				tempTable;
 	int getFieldId(const char* fieldName);
 };

=== modified file 'storage/falcon/Table.cpp'
--- a/storage/falcon/Table.cpp	2008-08-13 10:18:40 +0000
+++ b/storage/falcon/Table.cpp	2008-08-18 05:45:29 +0000
@@ -209,6 +209,34 @@ Index* Table::addIndex(const char * name
 	return index;
 }
 
+void Table::dropIndex(const char* indexName, Transaction* transaction)
+{
+	Sync sync(&syncObject, "Table::dropIndex");
+	sync.lock(Exclusive);
+	
+	Index *index = findIndex(indexName);
+		
+	if (index)
+		deleteIndex(index, transaction);
+}
+
+void Table::renameIndexes(const char *newTableName)
+{
+	for (Index *index = indexes; index; index = index->next)
+		{
+		if (index->type != PrimaryKey)
+			{
+
+			// Assume that index name is <table>$<index>
+
+			char newIndexName[256];
+			const char *p = strchr((const char*)index->name, '$');
+			sprintf(newIndexName, "%s%s", newTableName, (const char *)p);
+			index->rename(newIndexName);
+			}
+		}
+}
+
 const char* Table::getName()
 {
 	return name;
@@ -1706,6 +1734,19 @@ void Table::addIndex(Index * index)
 	*ptr = index;
 }
 
+void Table::dropIndex(Index *index)
+{
+	Sync sync(&syncObject, "Table::dropIndex");
+	sync.lock(Exclusive);
+
+	for (Index **ptr = &indexes; *ptr; ptr = &(*ptr)->next)
+		if (*ptr == index)
+			{
+			*ptr = index->next;
+			break;
+			}
+}
+
 void Table::addAttachment(TableAttachment * attachment)
 {
 	attachments.appendUnique(attachment);
@@ -2226,15 +2267,6 @@ void Table::dropTrigger(Trigger *trigger
 #endif
 }
 
-void Table::dropIndex(Index *index)
-{
-	for (Index **ptr = &indexes; *ptr; ptr = &(*ptr)->next)
-		if (*ptr == index)
-			{
-			*ptr = index->next;
-			break;
-			}
-}
 
 int Table::nextColumnId(int previous)
 {
@@ -3196,6 +3228,8 @@ void Table::rename(const char *newSchema
 		Index *primaryKey = getPrimaryKey();
 		database->renameTable(this, newSchema, newName);
 		
+		renameIndexes(newName);
+		
 		if (primaryKey)
 			primaryKey->rename(getPrimaryKeyName());
 		}
@@ -3491,7 +3525,7 @@ Record* Table::fetchForUpdate(Transactio
 
 				ASSERT(IS_CONSISTENT_READ(transaction->isolationLevel));
 				record->release();
-				Log::debug("Table::fetchForUpdate: Update Conflict: TransId=%d, RecordNumber=%d, Table %s.%s", 
+				Log::debug("Table::fetchForUpdate: Update Conflict: TransId=%d, RecordNumber=%d, Table %s.%s\n", 
 					transaction->transactionId, record->recordNumber, schemaName, name);
 				throw SQLError(UPDATE_CONFLICT, "update conflict in table %s.%s", schemaName, name);
 

=== modified file 'storage/falcon/Table.h'
--- a/storage/falcon/Table.h	2008-08-11 13:22:53 +0000
+++ b/storage/falcon/Table.h	2008-08-18 05:45:29 +0000
@@ -180,6 +180,8 @@ public:
 	void		create (const char *tableType, Transaction *transaction);
 	const char* getName();
 	Index*		addIndex (const char *name, int numberFields, int type);
+	void		dropIndex(const char* name, Transaction* transaction);
+	void		renameIndexes(const char *newTableName);
 	Field*		addField (const char *name, Type type, int length, int precision, int scale, int flags);
 	Field*		findField (const char *name);
 	int			getFormatVersion();

=== modified file 'storage/falcon/TableSpace.cpp'
--- a/storage/falcon/TableSpace.cpp	2008-07-17 13:52:17 +0000
+++ b/storage/falcon/TableSpace.cpp	2008-08-18 20:17:15 +0000
@@ -123,7 +123,9 @@ void TableSpace::open()
 
 void TableSpace::create()
 {
+#ifndef FALCONDB
 	dbb->createPath(filename);
+#endif
 	dbb->create(filename, dbb->pageSize, 0, HdrTableSpace, 0, NULL);
 	active = true;
 	dbb->flush();

=== modified file 'storage/falcon/Transaction.cpp'
--- a/storage/falcon/Transaction.cpp	2008-08-20 15:01:21 +0000
+++ b/storage/falcon/Transaction.cpp	2008-08-25 18:24:59 +0000
@@ -86,6 +86,7 @@ Transaction::Transaction(Connection *cnc
 	syncObject.setName("Transaction::syncObject");
 	syncActive.setName("Transaction::syncActive");
 	syncIndexes.setName("Transaction::syncIndexes");
+	syncRecords.setName("Transaction::syncRecords");
 	syncSavepoints.setName("Transaction::syncSavepoints");
 	firstRecord = NULL;
 	lastRecord = NULL;
@@ -216,20 +217,19 @@ Transaction::~Transaction()
 	delete backloggedRecords;
 	chillPoint = &firstRecord;
 
+	// We modify record list without locking.
+	// It is a destructor and if somebody accesses the list
+	// at this point, he is already lost.
 	for (RecordVersion *record; (record = firstRecord);)
 		{
-		removeRecord(record);
+		removeRecordNoLock(record);
 		}
+	firstRecord = NULL;
 	
 	releaseSavepoints();
 	
 	if (deferredIndexes)
-		{
-		Sync sync(&syncIndexes, "Transaction::~Transaction");
-		sync.lock(Exclusive);
-
 		releaseDeferredIndexes();
-		}
 }
 
 void Transaction::commit()
@@ -279,6 +279,8 @@ void Transaction::commit()
 
 	
 
+	Sync syncRec(&syncRecords,"Transaction::commit(1.5)");
+	syncRec.lock(Shared);
 	for (RecordVersion *record = firstRecord; record; record = record->nextInTrans)
 	{
 		Table * table = record->format->table;
@@ -295,7 +297,8 @@ void Transaction::commit()
 		if (record->state == recDeleted && table->cardinality > 0)
 			--table->cardinality;
 	}
-	
+	syncRec.unlock();
+
 	releaseDependencies();
 	database->flushInversion(this);
 
@@ -341,11 +344,7 @@ void Transaction::commitNoUpdates(void)
 	++transactionManager->committed;
 	
 	if (deferredIndexes)
-		{
-		Sync sync(&syncIndexes, "Transaction::commitNoUpdates(1)");
-		sync.lock(Exclusive);
 		releaseDeferredIndexes();
-		}
 
 	if (hasLocks)
 		releaseRecordLocks();
@@ -387,11 +386,7 @@ void Transaction::rollback()
 		throw SQLEXCEPTION (RUNTIME_ERROR, "transaction is not active");
 
 	if (deferredIndexes)
-		{
-		Sync sync(&syncIndexes, "Transaction::rollback(1)");
-		sync.lock(Exclusive);
 		releaseDeferredIndexes();
-		}
 		
 	releaseSavepoints();
 	TransactionManager *transactionManager = database->transactionManager;
@@ -403,6 +398,9 @@ void Transaction::rollback()
 	// Rollback pending record versions from newest to oldest in case
 	// there are multiple record versions on a prior record chain
 
+	Sync syncRec(&syncRecords, "Transaction::rollback(1.5)");
+	syncRec.lock(Exclusive);
+
 	while (firstRecord)
 		{
 		record = firstRecord;
@@ -428,6 +426,8 @@ void Transaction::rollback()
 		record->transaction = rollbackTransaction;
 		record->release();
 		}
+	firstRecord = NULL;
+	syncRec.unlock();
 
 	for (SavePoint *savePoint = savePoints; savePoint; savePoint = savePoint->next)
 		if (savePoint->backloggedRecords)
@@ -621,6 +621,8 @@ void Transaction::addRecord(RecordVersio
 
 	record->addRef();
 	
+	Sync syncRec(&syncRecords,"Transaction::addRecord");
+	syncRec.lock(Exclusive);
 	if ( (record->prevInTrans = lastRecord) )
 		lastRecord->nextInTrans = record;
 	else
@@ -628,6 +630,7 @@ void Transaction::addRecord(RecordVersio
 		
 	record->nextInTrans = NULL;
 	lastRecord = record;
+	syncRec.unlock();
 	
 	if (database->lowMemory && deletedRecords > MAX_LOW_MEMORY_RECORDS)
 		backlogRecords();
@@ -635,6 +638,12 @@ void Transaction::addRecord(RecordVersio
 
 void Transaction::removeRecord(RecordVersion *record)
 {
+	Sync syncRec(&syncRecords,"Transaction::removeRecord");
+	syncRec.lock(Exclusive);
+	removeRecordNoLock(record);
+}
+void Transaction::removeRecordNoLock(RecordVersion *record)
+{
 	RecordVersion **ptr;
 
 	if (record->nextInTrans)
@@ -800,6 +809,8 @@ void Transaction::releaseDependencies()
 
 void Transaction::commitRecords()
 {
+	Sync syncRec(&syncRecords,"Transaction::commitRecords");
+	syncRec.lock(Exclusive);
 	for (RecordVersion *recordList; (recordList = firstRecord);)
 		{
 		if (recordList && COMPARE_EXCHANGE_POINTER(&firstRecord, recordList, NULL))
@@ -903,13 +914,10 @@ State Transaction::getRelativeState(Tran
 
 void Transaction::dropTable(Table* table)
 {
-	Sync sync(&syncIndexes, "Transaction::dropTable");
-	sync.lock(Exclusive);
-
 	releaseDeferredIndexes(table);
 
-	// Keep exclusive lock to avoid race condition with writeComplete
-	
+	Sync syncRec(&syncRecords,"Transaction::dropTable(2)");
+	syncRec.lock(Exclusive);
 	for (RecordVersion **ptr = &firstRecord, *rec; (rec = *ptr);)
 		if (rec->format->table == table)
 			removeRecord(rec);
@@ -919,13 +927,9 @@ void Transaction::dropTable(Table* table
 
 void Transaction::truncateTable(Table* table)
 {
-	Sync sync(&syncIndexes, "Transaction::truncateTable");
-	sync.lock(Exclusive);
-
 	releaseDeferredIndexes(table);
-
-	// Keep exclusive lock to avoid race condition with writeComplete
-	
+	Sync syncRec(&syncRecords,"Transaction::truncateTable(2)");
+	syncRec.lock(Exclusive);
 	for (RecordVersion **ptr = &firstRecord, *rec; (rec = *ptr);)
 		if (rec->format->table == table)
 			removeRecord(rec);
@@ -935,9 +939,8 @@ void Transaction::truncateTable(Table* t
 
 bool Transaction::hasRecords(Table* table)
 {
-	// This lock is to avoid race with writeComplete
-	Sync sync(&syncIndexes, "Transaction::hasRecords");
-	sync.lock(Exclusive);
+	Sync syncRec(&syncRecords, "Transaction::hasRecords");
+	syncRec.lock(Shared);
 	for (RecordVersion *rec = firstRecord; rec; rec = rec->nextInTrans)
 		if (rec->format->table == table)
 			return true;
@@ -949,17 +952,12 @@ void Transaction::writeComplete(void)
 {
 	ASSERT(writePending);
 	ASSERT(state == Committed);
-	Sync sync(&syncIndexes, "Transaction::writeComplete");
-	sync.lock(Exclusive);
 	releaseDeferredIndexes();
-
-	// Keep the synIndexes lock to avoid a race condition with dropTable
 	
 	if (dependencies == 0)
 		commitRecords();
 
 	writePending = false;
-	sync.unlock();
 }
 
 bool Transaction::waitForTransaction(TransId transId)
@@ -1243,6 +1241,7 @@ void Transaction::rollbackSavepoint(int 
 
 	savePoint = savePoints;
 	
+
 	while (savePoint)
 		{
 		//validateRecords();
@@ -1251,6 +1250,8 @@ void Transaction::rollbackSavepoint(int 
 			break;
 
 		// Purge out records from this savepoint
+		Sync syncRec(&syncRecords,"Transaction::rollbackSavepoint(2)");
+		syncRec.lock(Exclusive);
 
 		RecordVersion *record = *savePoint->records;
 		RecordVersion *stack = NULL;
@@ -1290,6 +1291,7 @@ void Transaction::rollbackSavepoint(int 
 			rec->transaction = NULL;
 			rec->release();
 			}
+		syncRec.unlock();
 
 		// Handle any backlogged records
 		
@@ -1335,6 +1337,8 @@ void Transaction::releaseRecordLocks(voi
 	RecordVersion **ptr;
 	RecordVersion *record;
 
+	Sync syncRec(&syncRecords,"Transaction::releaseRecordLocks");
+	syncRec.lock(Exclusive);
 	for (ptr = &firstRecord; (record = *ptr);)
 		if (record->state == recLock)
 			{
@@ -1343,6 +1347,7 @@ void Transaction::releaseRecordLocks(voi
 			}
 		else
 			ptr = &record->nextInTrans;
+	syncRec.unlock();
 }
 
 void Transaction::print(void)
@@ -1360,6 +1365,8 @@ void Transaction::printBlocking(int leve
 	int deletes = 0;
 	RecordVersion *record;
 
+	Sync syncRec(&syncRecords,"Transaction::printBlocking");
+	syncRec.lock(Shared);
 	for (record = firstRecord; record; record = record->nextInTrans)
 		if (record->state == recLock)
 			++locks;
@@ -1407,7 +1414,7 @@ void Transaction::printBlocking(int leve
 				   record->recordNumber,
 				   what);
 		}
-
+	syncRec.unlock();
 	database->transactionManager->printBlocking(this, level);
 }
 
@@ -1445,14 +1452,7 @@ void Transaction::releaseDependency(void
 	INTERLOCKED_DECREMENT(dependencies);
 
 	if ((dependencies == 0) && !writePending && firstRecord)
-		{
-		// The Sync is to avoid a race with writeComplete().  It looks whacko, but does the trick
-		
-		Sync sync(&syncIndexes, "Transaction::releaseDependency");
-		sync.lock(Exclusive);
 		commitRecords();
-		}
-		
 	releaseCommittedTransaction();
 }
 
@@ -1497,6 +1497,8 @@ void Transaction::printBlockage(void)
 
 void Transaction::releaseDeferredIndexes(void)
 {
+	Sync sync(&syncIndexes, "Transaction::releaseDeferredIndexes");
+	sync.lock(Exclusive);
 	for (DeferredIndex *deferredIndex; (deferredIndex = deferredIndexes);)
 		{
 		ASSERT(deferredIndex->transaction == this);
@@ -1554,7 +1556,8 @@ void Transaction::backlogRecords(void)
 void Transaction::validateRecords(void)
 {
 	RecordVersion *record;
-	
+	Sync syncRec(&syncRecords,"Transaction::validateRecords");
+	syncRec.lock(Shared);
 	for (record = firstRecord; record && record->nextInTrans; record = record->nextInTrans)
 		;
 	

=== modified file 'storage/falcon/Transaction.h'
--- a/storage/falcon/Transaction.h	2008-08-11 13:22:53 +0000
+++ b/storage/falcon/Transaction.h	2008-08-25 18:24:59 +0000
@@ -87,7 +87,8 @@ public:
 
 	State		getRelativeState(Record* record, uint32 flags);
 	State		getRelativeState (Transaction *transaction, TransId transId, uint32 flags);
-	void		removeRecord (RecordVersion *record);
+	void		removeRecordNoLock (RecordVersion *record);
+	void		removeRecord(RecordVersion *record);
 	void		removeRecord (RecordVersion *record, RecordVersion **ptr);
 	void		expungeTransaction (Transaction *transaction);
 	void		commitRecords();
@@ -171,6 +172,7 @@ public:
 	SyncObject		syncObject;
 	SyncObject		syncActive;
 	SyncObject		syncIndexes;
+	SyncObject		syncRecords;
 	SyncObject		syncSavepoints;
 	uint64			totalRecordData;	// total bytes of record data for this transaction (unchilled + thawed)
 	uint32			totalRecords;		// total record count

=== modified file 'storage/falcon/TransactionManager.cpp'
--- a/storage/falcon/TransactionManager.cpp	2008-08-14 12:08:37 +0000
+++ b/storage/falcon/TransactionManager.cpp	2008-08-25 21:51:46 +0000
@@ -74,26 +74,25 @@ TransId TransactionManager::findOldestAc
 {
 	Sync syncCommitted(&committedTransactions.syncObject, "TransactionManager::findOldestActive(1)");
 	syncCommitted.lock(Shared);
-	TransId oldestActive = transactionSequence;
+	TransId oldestCommitted = transactionSequence;
 	
 	for (Transaction *trans = committedTransactions.first; trans; trans = trans->next)
-		oldestActive = MIN(trans->transactionId, oldestActive);
+		oldestCommitted = MIN(trans->transactionId, oldestCommitted);
 
 	syncCommitted.unlock();
-	Sync sync(&activeTransactions.syncObject, "TransactionManager::findOldestActive(2)");
-	sync.lock(Shared);
+
 	Transaction *oldest = findOldest();
 
 	if (oldest)
 		{
-		//Log::debug("Oldest transaction %d, oldest ancestor %d, oldest committed %d\n",  oldest->transactionId, oldest->oldestActive, oldestActive);
-					
-		return MIN(oldest->oldestActive, oldestActive);
+		//Log::debug("Oldest transaction %d, oldest ancestor %d, oldest committed %d\n",  oldest->transactionId, oldest->oldestActive, oldestCommitted);
+
+		return MIN(oldest->oldestActive, oldestCommitted);
 		}
 	
 	//Log::debug("No active, current %d, oldest committed %d\n", transactionSequence, oldestActive);
 	
-	return oldestActive;
+	return oldestCommitted;
 }
 
 Transaction* TransactionManager::findOldest(void)
@@ -247,16 +246,20 @@ void TransactionManager::rollbackByXid(i
 
 void TransactionManager::print(void)
 {
-	Sync sync (&activeTransactions.syncObject, "TransactionManager::print(1)");
-	sync.lock (Exclusive);
-	Sync committedTrans (&committedTransactions.syncObject, "TransactionManager::print(2)");
-	committedTrans.lock (Exclusive);
+	Sync syncActive (&activeTransactions.syncObject, "TransactionManager::print(1)");
+	syncActive.lock (Exclusive);
+
+	Sync syncCommitted (&committedTransactions.syncObject, "TransactionManager::print(2)");
+	syncCommitted.lock (Exclusive);
+
 	Transaction *transaction;
 	Log::debug("Active Transaction:\n");
 	
 	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
 		transaction->print();
-		
+
+	syncActive.unlock();
+
 	Log::debug("Committed Transaction:\n");
 	
 	for (transaction = committedTransactions.first; transaction; transaction = transaction->next)
@@ -266,15 +269,19 @@ void TransactionManager::print(void)
 
 void TransactionManager::getTransactionInfo(InfoTable* infoTable)
 {
-	Sync sync (&activeTransactions.syncObject, "TransactionManager::getTransactionInfo(1)");
-	sync.lock (Exclusive);
-	Sync committedTrans (&committedTransactions.syncObject, "TransactionManager::getTransactionInfo(2)");
-	committedTrans.lock (Exclusive);
+	Sync syncActive (&activeTransactions.syncObject, "TransactionManager::getTransactionInfo(2)");
+	syncActive.lock (Exclusive);
+
+	Sync syncCommitted (&committedTransactions.syncObject, "TransactionManager::getTransactionInfo(1)");
+	syncCommitted.lock (Exclusive);
+
 	Transaction *transaction;
 	
 	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
 		transaction->getInfo(infoTable);
-	
+
+	syncActive.unlock();
+
 	for (transaction = committedTransactions.first; transaction; transaction = transaction->next)
 		transaction->getInfo(infoTable);
 }
@@ -307,10 +314,12 @@ void TransactionManager::purgeTransactio
 
 void TransactionManager::getSummaryInfo(InfoTable* infoTable)
 {
-	Sync sync (&activeTransactions.syncObject, "TransactionManager::getSummaryInfo(1)");
-	sync.lock (Exclusive);
-	Sync committedTrans (&committedTransactions.syncObject, "TransactionManager::getSummaryInfo(2)");
-	committedTrans.lock (Exclusive);
+	Sync syncActive (&activeTransactions.syncObject, "TransactionManager::getSummaryInfo(2)");
+	syncActive.lock (Exclusive);
+
+	Sync syncCommitted (&committedTransactions.syncObject, "TransactionManager::getSummaryInfo(1)");
+	syncCommitted.lock (Exclusive);
+
 	int numberCommitted = committed;
 	int numberRolledBack = rolledBack;
 	int numberActive = 0;
@@ -327,14 +336,14 @@ void TransactionManager::getSummaryInfo(
 		if (transaction->state == Committed)
 			++numberPendingCommit;
 		}
+	syncActive.unlock();
 
 	for (transaction = committedTransactions.first; transaction; transaction = transaction->next)
 		if (transaction->writePending)
 			++numberPendingCompletion;
 	
-	committedTrans.unlock();
-	sync.unlock();
-	
+	syncCommitted.unlock();
+
 	int n = 0;
 	infoTable->putInt(n++, numberCommitted);
 	infoTable->putInt(n++, numberRolledBack);
@@ -402,15 +411,16 @@ void TransactionManager::expungeTransact
 
 Transaction* TransactionManager::findTransaction(TransId transactionId)
 {
-	Sync syncActiveTrans(&activeTransactions.syncObject, "TransactionManager::findTransaction(1)");
-	syncActiveTrans.lock(Shared);
+	Sync syncActive(&activeTransactions.syncObject, "TransactionManager::findTransaction(1)");
+	syncActive.lock(Shared);
 	Transaction *transaction;
 
 	for (transaction = activeTransactions.first; transaction; transaction = transaction->next)
 		if (transaction->transactionId == transactionId)
 			return transaction;
 	
-	syncActiveTrans.unlock();
+	syncActive.unlock();
+
 	Sync syncCommitted(&committedTransactions.syncObject, "TransactionManager::findTransaction(2)");
 	syncCommitted.lock(Shared);
 
@@ -418,20 +428,21 @@ Transaction* TransactionManager::findTra
 		if (transaction->transactionId == transactionId)
 			return transaction;
 	
-	return NULL;	
+	return NULL;
 }
 
 void TransactionManager::validateDependencies(void)
 {
-	Sync sync(&committedTransactions.syncObject, "TransactionManager::validateDepedendencies(1)");
-	sync.lock(Shared);
+	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);
 			
-	sync.unlock();
+	syncActive.unlock();
+
 	Sync syncCommitted(&committedTransactions.syncObject, "TransactionManager::validateDepedendencies(2)");
 	syncCommitted.lock(Shared);
 

=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp	2008-08-14 11:24:18 +0000
+++ b/storage/falcon/ha_falcon.cpp	2008-08-22 12:55:22 +0000
@@ -54,7 +54,7 @@
 #endif
 
 #ifndef ONLINE_ALTER
-//#define ONLINE_ALTER
+#define ONLINE_ALTER
 #endif
 
 #ifdef DEBUG_BACKLOG
@@ -216,13 +216,13 @@ int StorageInterface::falcon_init(void *
 		}
 	catch(SQLException &e)
 		{
-		sql_print_error("Falcon : exception '%s'during initialization",
+		sql_print_error("Falcon: Exception '%s' during initialization",
 			e.getText());
 		error = true;
 		}
 	catch(...)
 		{
-		sql_print_error(" Falcon : general exception in initialization");
+		sql_print_error(" Falcon: General exception in initialization");
 		error = true;
 		}
 
@@ -398,6 +398,7 @@ StorageInterface::StorageInterface(handl
 	ref_length = sizeof(lastRecord);
 	stats.records = 1000;
 	stats.data_file_length = 10000;
+	stats.index_file_length = 0;
 	tableLocked = false;
 	lockForUpdate = false;
 	storageTable = NULL;
@@ -424,6 +425,9 @@ StorageInterface::StorageInterface(handl
 
 StorageInterface::~StorageInterface(void)
 {
+	if (storageTable)
+		storageTable->clearCurrentIndex();
+
 	if (activeBlobs)
 		freeActiveBlobs();
 
@@ -482,6 +486,7 @@ int StorageInterface::open(const char *n
 
 		if (!storageShare->initialized)
 			{
+//			storageShare->lockIndexes(true);
 			storageShare->lock(true);
 
 			if (!storageShare->initialized)
@@ -505,6 +510,7 @@ int StorageInterface::open(const char *n
 				}
 
 			storageShare->unlock();
+//			storageShare->unlockIndexes();
 			}
 		}
 
@@ -535,6 +541,10 @@ StorageConnection* StorageInterface::get
 int StorageInterface::close(void)
 {
 	DBUG_ENTER("StorageInterface::close");
+
+	if (storageTable)
+		storageTable->clearCurrentIndex();
+
 	unmapFields();
 
 	// Temporarily comment out DTrace probes in Falcon, see bug #36403
@@ -672,23 +682,27 @@ void StorageInterface::getDemographics(v
 
 	stats.block_size = 4096;
 
+	storageShare->lockIndexes();
+
 	for (uint n = 0; n < table->s->keys; ++n)
 		{
 		KEY *key = table->s->key_info + n;
-		StorageIndexDesc *desc = storageShare->getIndex(n);
+		StorageIndexDesc *indexDesc = storageShare->getIndex(n);
 
-		if (desc)
+		if (indexDesc)
 			{
-			ha_rows rows = 1 << desc->numberSegments;
+			ha_rows rows = 1 << indexDesc->numberSegments;
 
 			for (uint segment = 0; segment < key->key_parts; ++segment, rows >>= 1)
 				{
-				ha_rows recordsPerSegment = (ha_rows) desc->segmentRecordCounts[segment];
+				ha_rows recordsPerSegment = (ha_rows)indexDesc->segmentRecordCounts[segment];
 				key->rec_per_key[segment] = (ulong) MAX(recordsPerSegment, rows);
 				}
 			}
 		}
 
+	storageShare->unlockIndexes();
+
 	DBUG_VOID_RETURN;
 }
 
@@ -832,7 +846,7 @@ int StorageInterface::create(const char 
 
 	for (n = 0; n < form->s->keys; ++n)
 		if (n != form->s->primary_key)
-			if ((ret = createIndex(schemaName, tableName, form->key_info + n, n)))
+			if ((ret = createIndex(schemaName, tableName, form, n)))
 				{
 				storageTable->deleteTable();
 
@@ -847,32 +861,42 @@ int StorageInterface::create(const char 
 int StorageInterface::add_index(TABLE* table_arg, KEY* key_info, uint num_of_keys)
 {
 	DBUG_ENTER("StorageInterface::add_index");
-	int ret = createIndex(storageTable->getSchemaName(), storageTable->getName(), key_info, table_arg->s->keys);
+	int ret = createIndex(storageTable->getSchemaName(), storageTable->getName(), table_arg, table_arg->s->keys);
 
 	DBUG_RETURN(ret);
 }
 
-int StorageInterface::createIndex(const char *schemaName, const char *tableName,
-                                 KEY *key, int indexNumber)
+int StorageInterface::createIndex(const char *schemaName, const char *tableName, TABLE *table, int indexId)
 {
+	KEY *key = table->key_info + indexId;
+	StorageIndexDesc indexDesc;
+	getKeyDesc(table, indexId, &indexDesc);
+	
+	char indexName[indexNameSize];
+	storageShare->createIndexName(indexDesc.name, indexName);
+
 	CmdGen gen;
 	const char *unique = (key->flags & HA_NOSAME) ? "unique " : "";
-	gen.gen("create %sindex \"%s$%d\" on %s.\"%s\" ", unique, tableName,
-	        indexNumber, schemaName, tableName);
+	gen.gen("create %sindex \"%s\" on %s.\"%s\" ", unique, indexName, schemaName, tableName);
 	genKeyFields(key, &gen);
 	const char *sql = gen.getString();
 
-	return storageTable->share->createIndex(storageConnection, key->name, sql);
+	return storageTable->createIndex(&indexDesc, sql);
 }
 
-int StorageInterface::dropIndex(const char *schemaName, const char *tableName,
-                                 KEY *key, int indexNumber)
+int StorageInterface::dropIndex(const char *schemaName, const char *tableName, TABLE *table, int indexId)
 {
+	StorageIndexDesc indexDesc;
+	getKeyDesc(table, indexId, &indexDesc);
+	
+	char indexName[indexNameSize];
+	storageShare->createIndexName(indexDesc.name, indexName);
+
 	CmdGen gen;
-	gen.gen("drop index %s.\"%s$%d\"", schemaName, tableName, indexNumber);
+	gen.gen("drop index %s.\"%s\"", schemaName, indexName);
 	const char *sql = gen.getString();
 
-	return storageTable->share->dropIndex(storageConnection, key->name, sql);
+	return storageTable->dropIndex(&indexDesc, sql);
 }
 
 #if 0
@@ -916,6 +940,8 @@ THR_LOCK_DATA **StorageInterface::store_
 		    && !(thd_tablespace_op(thd))
 		    &&  (sql_command != SQLCOM_ALTER_TABLE)
 		    &&  (sql_command != SQLCOM_DROP_TABLE)
+		    &&  (sql_command != SQLCOM_CREATE_INDEX)
+		    &&  (sql_command != SQLCOM_DROP_INDEX)
 		    &&  (sql_command != SQLCOM_TRUNCATE)
 		    &&  (sql_command != SQLCOM_OPTIMIZE)
 		    &&  (sql_command != SQLCOM_CREATE_TABLE)
@@ -963,6 +989,10 @@ int StorageInterface::delete_table(const
 
 	if (storageShare)
 		{
+		
+		// Lock out other clients before locking the table
+		
+		storageShare->lockIndexes(true);
 		storageShare->lock(true);
 
 		if (storageShare->initialized)
@@ -973,6 +1003,7 @@ int StorageInterface::delete_table(const
 			}
 
 		storageShare->unlock();
+		storageShare->unlockIndexes();
 		}
 
 	int res = storageTable->deleteTable();
@@ -1358,7 +1389,6 @@ int StorageInterface::index_read(uchar *
 		}
 }
 
-
 int StorageInterface::index_init(uint idx, bool sorted)
 {
 	DBUG_ENTER("StorageInterface::index_init");
@@ -1367,33 +1397,30 @@ int StorageInterface::index_init(uint id
 	haveStartKey = false;
 	haveEndKey = false;
 
-	if (!storageTable->setIndex(idx))
-		DBUG_RETURN(0);
-
-	StorageIndexDesc indexDesc;
-	getKeyDesc(table->key_info + idx, &indexDesc);
-
-	if (idx == table->s->primary_key)
-		indexDesc.primaryKey = true;
-
-	int ret = storageTable->setIndex(table->s->keys, idx, &indexDesc);
+	int ret = storageTable->setCurrentIndex(idx);
 
 	if (ret)
+		{
+		setIndex(table, idx);
+		ret = storageTable->setCurrentIndex(idx);
+		}
+		
+	if (ret)
 		DBUG_RETURN(error(ret));
 
-	DBUG_RETURN(0);
+	DBUG_RETURN(ret);
 }
 
-
 int StorageInterface::index_end(void)
 {
 	DBUG_ENTER("StorageInterface::index_end");
+	
 	storageTable->indexEnd();
+	
 	DBUG_RETURN(0);
 }
 
-ha_rows StorageInterface::records_in_range(uint indexId, key_range *lower,
-                                         key_range *upper)
+ha_rows StorageInterface::records_in_range(uint indexId, key_range *lower, key_range *upper)
 {
 	DBUG_ENTER("StorageInterface::records_in_range");
 
@@ -1406,9 +1433,9 @@ ha_rows StorageInterface::records_in_ran
 	if (!lower)
 		DBUG_RETURN(MAX(cardinality, 2));
 
-	StorageIndexDesc *index = storageShare->getIndex(indexId);
+	StorageIndexDesc indexDesc;
 
-	if (!index)
+	if (!storageShare->getIndex(indexId, &indexDesc))
 		DBUG_RETURN(MAX(cardinality, 2));
 
 	int numberSegments = 0;
@@ -1416,10 +1443,10 @@ ha_rows StorageInterface::records_in_ran
 	for (int map = lower->keypart_map; map; map >>= 1)
 		++numberSegments;
 
-	if (index->unique && numberSegments == index->numberSegments)
+	if (indexDesc.unique && numberSegments == indexDesc.numberSegments)
 		DBUG_RETURN(1);
 
-	ha_rows segmentRecords = (ha_rows) index->segmentRecordCounts[numberSegments - 1];
+	ha_rows segmentRecords = (ha_rows)indexDesc.segmentRecordCounts[numberSegments - 1];
 	ha_rows guestimate = cardinality;
 
 	if (lower->flag == HA_READ_KEY_EXACT)
@@ -1436,22 +1463,34 @@ ha_rows StorageInterface::records_in_ran
 	DBUG_RETURN(MAX(guestimate, 2));
 }
 
-
-void StorageInterface::getKeyDesc(KEY *keyInfo, StorageIndexDesc *indexInfo)
+void StorageInterface::getKeyDesc(TABLE *table, int indexId, StorageIndexDesc *indexDesc)
 {
+	KEY *keyInfo = table->key_info + indexId;
 	int numberKeys = keyInfo->key_parts;
-	indexInfo->numberSegments = numberKeys;
-	indexInfo->name = keyInfo->name;
-	indexInfo->unique = (keyInfo->flags & HA_NOSAME);
-	indexInfo->primaryKey = false;
+	char nameBuffer[indexNameSize];
+	
+	// Clean up the index name for internal use
+	
+	strncpy(indexDesc->rawName, (const char*)keyInfo->name, MIN(indexNameSize, (int)strlen(keyInfo->name)+1));
+	storageShare->cleanupFieldName(indexDesc->rawName, nameBuffer, sizeof(nameBuffer));
+	indexDesc->rawName[indexNameSize-1] = '\0';
+	
+	strncpy(indexDesc->name, (const char*)nameBuffer, MIN(indexNameSize, (int)strlen(nameBuffer)+1));
+	indexDesc->name[indexNameSize-1] = '\0';
+
+	indexDesc->id			  = indexId;
+	indexDesc->numberSegments = numberKeys;
+	indexDesc->unique		  = (keyInfo->flags & HA_NOSAME);
+	indexDesc->primaryKey	  = (table->s->primary_key == (uint)indexId);
 
 	for (int n = 0; n < numberKeys; ++n)
 		{
-		StorageSegment *segment = indexInfo->segments + n;
+		StorageSegment *segment = indexDesc->segments + n;
 		KEY_PART_INFO *part = keyInfo->key_part + n;
-		segment->offset = part->offset;
-		segment->length = part->length;
-		segment->type = part->field->key_type();
+		
+		segment->offset	= part->offset;
+		segment->length	= part->length;
+		segment->type	= part->field->key_type();
 		segment->nullBit = part->null_bit;
 		segment->isUnsigned = (part->field->flags & ENUM_FLAG) ?
 			true : ((Field_num*) part->field)->unsigned_flag;
@@ -1472,7 +1511,6 @@ void StorageInterface::getKeyDesc(KEY *k
 		}
 }
 
-
 int StorageInterface::rename_table(const char *from, const char *to)
 {
 	DBUG_ENTER("StorageInterface::rename_table");
@@ -1489,17 +1527,14 @@ int StorageInterface::rename_table(const
 		DBUG_RETURN(error(ret));
 
 	DBUG_RETURN(ret);
-
 }
 
-
 double StorageInterface::read_time(uint index, uint ranges, ha_rows rows)
 {
 	DBUG_ENTER("StorageInterface::read_time");
 	DBUG_RETURN(rows2double(rows / 3));
 }
 
-
 int StorageInterface::read_range_first(const key_range *start_key,
                                       const key_range *end_key,
                                       bool eq_range_arg, bool sorted)
@@ -1634,7 +1669,6 @@ int StorageInterface::index_next(uchar *
 		}
 }
 
-
 int StorageInterface::index_next_same(uchar *buf, const uchar *key, uint key_len)
 {
 	DBUG_ENTER("StorageInterface::index_next_same");
@@ -1654,7 +1688,6 @@ int StorageInterface::index_next_same(uc
 		}
 }
 
-
 double StorageInterface::scan_time(void)
 {
 	DBUG_ENTER("StorageInterface::scan_time");
@@ -1691,13 +1724,11 @@ bool StorageInterface::threadSwitch(THD*
 	return true;
 }
 
-
 int StorageInterface::threadSwitchError(void)
 {
 	return 1;
 }
 
-
 int StorageInterface::error(int storageError)
 {
 	DBUG_ENTER("StorageInterface::error");
@@ -1737,7 +1768,6 @@ int StorageInterface::error(int storageE
 	DBUG_RETURN(mySqlError);
 }
 
-
 int StorageInterface::getMySqlError(int storageError)
 {
 	switch (storageError)
@@ -1856,8 +1886,6 @@ int StorageInterface::reset()
 	DBUG_RETURN(0);
 }
 
- 
- 
 int StorageInterface::external_lock(THD *thd, int lock_type)
 {
 	DBUG_ENTER("StorageInterface::external_lock");
@@ -1873,7 +1901,10 @@ int StorageInterface::external_lock(THD 
 			storageConnection->releaseVerb();
 
 		if (storageTable)
+			{
 			storageTable->clearStatement();
+			storageTable->clearCurrentIndex();
+			}
 		}
 	else
 		{
@@ -1894,6 +1925,9 @@ int StorageInterface::external_lock(THD 
 
 				if (ret)
 					{
+					if (storageTable)
+						storageTable->clearCurrentIndex();
+						
 					DBUG_RETURN(error(ret));
 					}
 				}
@@ -1910,9 +1944,7 @@ int StorageInterface::external_lock(THD 
 			checkBinLog();
 			
 			if (storageConnection->startTransaction(isolation))
-				{
 				trans_register_ha(thd, true, falcon_hton);
-				}
 
 			if (storageConnection->markVerb())
 				trans_register_ha(thd, false, falcon_hton);
@@ -1922,9 +1954,7 @@ int StorageInterface::external_lock(THD 
 			checkBinLog();
 			
 			if (storageConnection->startImplicitTransaction(isolation))
-				{
 				trans_register_ha(thd, false, falcon_hton);
-				}
 			}
 
 		switch (thd_tx_isolation(mySqlThread))
@@ -1937,13 +1967,11 @@ int StorageInterface::external_lock(THD 
 				error(StorageWarningSerializable);
 				break;
 			}
-			
 		}
 
 	DBUG_RETURN(0);
 }
 
-
 void StorageInterface::get_auto_increment(ulonglong offset, ulonglong increment,
                                          ulonglong nb_desired_values,
                                          ulonglong *first_value,
@@ -1956,7 +1984,6 @@ void StorageInterface::get_auto_incremen
 	DBUG_VOID_RETURN;
 }
 
-
 const char *StorageInterface::index_type(uint key_number)
 {
   DBUG_ENTER("StorageInterface::index_type");
@@ -1971,7 +1998,6 @@ void StorageInterface::dropDatabase(hand
 	DBUG_VOID_RETURN;
 }
 
-
 void StorageInterface::freeActiveBlobs(void)
 {
 	for (StorageBlob *blob; (blob = activeBlobs); )
@@ -1983,14 +2009,12 @@ void StorageInterface::freeActiveBlobs(v
 		}
 }
 
-
 void StorageInterface::shutdown(handlerton *htons)
 {
 	if(storageHandler)
 		storageHandler->shutdownHandler();
 }
 
-
 int StorageInterface::panic(handlerton* hton, ha_panic_function flag)
 {
 	if(storageHandler)
@@ -1999,7 +2023,6 @@ int StorageInterface::panic(handlerton* 
 	return 0;
 }
 
-
 int StorageInterface::closeConnection(handlerton *hton, THD *thd)
 {
 	DBUG_ENTER("NfsStorageEngine::closeConnection");
@@ -2009,7 +2032,6 @@ int StorageInterface::closeConnection(ha
 	DBUG_RETURN(0);
 }
 
-
 int StorageInterface::alter_tablespace(handlerton* hton, THD* thd, st_alter_tablespace* ts_info)
 {
 	DBUG_ENTER("NfsStorageEngine::alter_tablespace");
@@ -2224,10 +2246,15 @@ int StorageInterface::addColumn(THD* thd
 
 int StorageInterface::addIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo, HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags)
 {
-	int ret;
+	int ret = 0;
 	const char *tableName = storageTable->getName();
 	const char *schemaName = storageTable->getSchemaName();
 
+	// Lock out other clients before locking the table
+	
+	storageShare->lockIndexes(true);
+	storageShare->lock(true);
+
 	// Find indexes to be added by comparing table and alteredTable
 
 	for (unsigned int n = 0; n < alteredTable->s->keys; n++)
@@ -2243,19 +2270,33 @@ int StorageInterface::addIndex(THD* thd,
 					break;
 					
 			if (tableKey >= tableEnd)
-				if ((ret = createIndex(schemaName, tableName, key, n)))
-					return (error(ret));
+				if ((ret = createIndex(schemaName, tableName, alteredTable, n)))
+					break;
 			}
 		}
-	return 0;
+		
+	// The server indexes may have been reordered, so remap to the Falcon indexes
+	
+	if (!ret)
+		remapIndexes(alteredTable);
+	
+	storageShare->unlock();
+	storageShare->unlockIndexes();
+	
+	return error(ret);
 }
 
 int StorageInterface::dropIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo, HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags)
 {
-	int ret;
+	int ret = 0;
 	const char *tableName = storageTable->getName();
 	const char *schemaName = storageTable->getSchemaName();
 	
+	// Lock out other clients before locking the table
+	
+	storageShare->lockIndexes(true);
+	storageShare->lock(true);
+	
 	// Find indexes to be dropped by comparing table and alteredTable
 	
 	for (unsigned int n = 0; n < table->s->keys; n++)
@@ -2271,12 +2312,20 @@ int StorageInterface::dropIndex(THD* thd
 					break;
 
 			if (alterKey >= alterEnd)
-				if ((ret = dropIndex(schemaName, tableName, key, n)))
-				return (error(ret));
+				if ((ret = dropIndex(schemaName, tableName, table, n)))
+					break;
 				}
 		}
 	
-	return 0;
+	// The server indexes have been reordered, so remap to the Falcon indexes
+	
+	if (!ret)
+		remapIndexes(alteredTable);
+	
+	storageShare->unlock();
+	storageShare->unlockIndexes();
+	
+	return error(ret);
 }
 
 uint StorageInterface::max_supported_key_length(void) const
@@ -2288,7 +2337,6 @@ uint StorageInterface::max_supported_key
 	return MAX_INDEX_KEY_LENGTH_4K;  // Default value.
 }
 
-
 uint StorageInterface::max_supported_key_part_length(void) const
 {
 	// Assume 4K page unless proven otherwise.
@@ -2298,7 +2346,6 @@ uint StorageInterface::max_supported_key
 	return MAX_INDEX_KEY_LENGTH_4K;  // Default for future sizes.
 }
 
-
 void StorageInterface::logger(int mask, const char* text, void* arg)
 {
 	if (mask & falcon_debug_mask)
@@ -2314,32 +2361,47 @@ void StorageInterface::logger(int mask, 
 		}
 }
 
+int StorageInterface::setIndex(TABLE *table, int indexId)
+{
+	StorageIndexDesc indexDesc;
+	getKeyDesc(table, indexId, &indexDesc);
+
+	return storageTable->setIndex(&indexDesc);
+}
+
 int StorageInterface::setIndexes(void)
 {
+	int ret = 0;
+	
 	if (!table || storageShare->haveIndexes(table->s->keys))
-		return 0;
+		return ret;
 
-	storageShare->lock(true);
+	storageShare->lockIndexes(true);
 
 	if (!storageShare->haveIndexes(table->s->keys))
-		{
-		StorageIndexDesc indexDesc;
-
 		for (uint n = 0; n < table->s->keys; ++n)
-			{
-			getKeyDesc(table->key_info + n, &indexDesc);
+			if ((ret = setIndex(table, n)))
+				break;
 
-			if (n == table->s->primary_key)
-				indexDesc.primaryKey = true;
+	storageShare->unlockIndexes();
 
-			int ret = storageTable->setIndex(table->s->keys, n, &indexDesc);
-			if (ret)
-				return ret;
-			}
-		}
+	return ret;
+}
 
-	storageShare->unlock();
-	return 0;
+int StorageInterface::remapIndexes(TABLE *table)
+{
+	int ret = 0;
+	
+	if (!table)
+		return ret;
+		
+	storageShare->deleteIndexes();
+
+	for (uint n = 0; n < table->s->keys; ++n)
+		if ((ret = setIndex(table, n)))
+			break;
+
+	return ret;
 }
 
 int StorageInterface::genTable(TABLE* table, CmdGen* gen)
@@ -2348,7 +2410,7 @@ int StorageInterface::genTable(TABLE* ta
 	const char *schemaName = storageTable->getSchemaName();
 	gen->gen("upgrade table \"%s\".\"%s\" (\n", schemaName, tableName);
 	const char *sep = "";
-	char nameBuffer[129];
+	char nameBuffer[256];
 
 	for (uint n = 0; n < table->s->fields; ++n)
 		{
@@ -2495,18 +2557,16 @@ int StorageInterface::genType(Field* fie
 	return 0;
 }
 
-
 void StorageInterface::genKeyFields(KEY* key, CmdGen* gen)
 {
 	const char *sep = "(";
-	char nameBuffer[129];
+	char nameBuffer[256];
 
 	for (uint n = 0; n < key->key_parts; ++n)
 		{
 		KEY_PART_INFO *part = key->key_part + n;
 		Field *field = part->field;
-		storageShare->cleanupFieldName(field->field_name, nameBuffer,
-										sizeof(nameBuffer));
+		storageShare->cleanupFieldName(field->field_name, nameBuffer, sizeof(nameBuffer));
 
 		if (part->key_part_flag & HA_PART_KEY_SEG)
 			gen->gen("%s\"%s\"(%d)", sep, nameBuffer, part->length);
@@ -2519,7 +2579,6 @@ void StorageInterface::genKeyFields(KEY*
 	gen->gen(")");
 }
 
-
 void StorageInterface::encodeRecord(uchar *buf, bool updateFlag)
 {
 	storageTable->preInsert();
@@ -3504,7 +3563,7 @@ void StorageInterface::mapFields(TABLE *
 	unmapFields();
 	fieldMap = new Field*[maxFields];
 	memset(fieldMap, 0, sizeof(fieldMap[0]) * maxFields);
-	char nameBuffer[129];
+	char nameBuffer[256];
 
 	for (uint n = 0; n < table->s->fields; ++n)
 		{

=== modified file 'storage/falcon/ha_falcon.h'
--- a/storage/falcon/ha_falcon.h	2008-07-29 10:45:39 +0000
+++ b/storage/falcon/ha_falcon.h	2008-08-22 06:47:40 +0000
@@ -29,7 +29,7 @@ static const int TRANSACTION_CONSISTENT_
 static const int TRANSACTION_SERIALIZABLE     = 16;	// Dirty reads, non-repeatable reads and phantom reads are prevented.
 
 struct st_table_share;
-struct StorageIndexDesc;
+class StorageIndexDesc;
 struct StorageBlob;
 
 class StorageInterface : public handler
@@ -113,15 +113,18 @@ public:
 	int				dropIndex(THD* thd, TABLE* alteredTable, HA_CREATE_INFO* createInfo, HA_ALTER_INFO* alterInfo, HA_ALTER_FLAGS* alterFlags);
 
 	void			getDemographics(void);
-	int				createIndex(const char *schemaName, const char *tableName, KEY *key, int indexNumber);
-	int				dropIndex(const char *schemaName, const char *tableName, KEY *key, int indexNumber);
-	void			getKeyDesc(KEY *keyInfo, StorageIndexDesc *indexInfo);
+//	int				createIndex(const char *schemaName, const char *tableName, KEY *key, int indexId);
+	int				createIndex(const char *schemaName, const char *tableName, TABLE *table, int indexId);
+	int				dropIndex(const char *schemaName, const char *tableName, TABLE *table, int indexId);
+	void			getKeyDesc(TABLE *table, int indexId, StorageIndexDesc *indexInfo);
 	void			startTransaction(void);
 	bool			threadSwitch(THD *newThread);
 	int				threadSwitchError(void);
 	int				error(int storageError);
 	void			freeActiveBlobs(void);
+	int				setIndex(TABLE *table, int indexId);
 	int				setIndexes(void);
+	int				remapIndexes(TABLE *table);
 	int				genTable(TABLE* table, CmdGen* gen);
 	int				genType(Field *field, CmdGen *gen);
 	void			genKeyFields(KEY *key, CmdGen *gen);

=== modified file 'storage/falcon/plug.in'
--- a/storage/falcon/plug.in	2008-08-12 21:50:50 +0000
+++ b/storage/falcon/plug.in	2008-08-20 13:27:29 +0000
@@ -19,6 +19,18 @@ volatile int target= 0;
 int compare= 1;
 int exchange= 2;
       ],[
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+  /* When compiling with Sun Studio compiler we need the Solaris atomic 
+     functions. These were first introduced in Solaris 10. */
+#if defined(HAVE_SOLARIS_ATOMIC)
+  return 0;
+#else 
+  /* Fail if the atomic functions are not available. Support for this
+     will be added when the fix for bug 37622 is completed. */
+#error Need Solaris atomic functions to use Sun Studio compiler
+#endif /* HAVE_SOLARIS_ATOMIC */
+#else
+  /* Use gcc style inline assembly when compiling with gcc */
   char ret;
   __asm__ __volatile__ (
 	  "membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore\n\t"
@@ -32,6 +44,7 @@ int exchange= 2;
 	  : "r" (&target), "0" (compare)
 	  : "memory", "cc"
 	  )
+#endif /* !__SUNPRO_C && !__SUNPRO_CC */
       ], falcon_supported_by_machine="yes", 
          falcon_supported_by_machine="no")
       ;;

Thread
bzr commit into mysql-6.0 branch (vvaintroub:2781) Vladislav Vaintroub27 Aug