MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Christopher Powers Date:August 18 2008 5:03pm
Subject:bzr push into mysql-6.0-falcon branch (cpowers:2786 to 2787) Bug#38039
Bug#38041 Bug#38043 Bug#38044
View as plain text  
 2787 Christopher Powers	2008-08-18
      Bug#38044 Falcon crash in StorageTable::compareKey at StorageTable.cpp:412
      Bug#38043 Deadlock between server and falcon when executing concurrent ALTER + DML
      Bug#38039 Assertion lockState == 0 failed in StorageTableShare::deleteTable SyncObject
      Bug#38041 Bizarre errors when ALTER ADD/DROP KEY on Falcon tables
      
      Improved index synchronization in the StorageInterface:
      - Falcon internal indexes no longer dependent upon server index id
      - Client connections lock StorageTableShare::syncIndexes to protect indexes across calls into StorageInterface
      - Changes to StorageTableShare::indexes are now protected by exclusive lock
modified:
  storage/falcon/DenseArray.h
  storage/falcon/Index.cpp
  storage/falcon/Index.h
  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/Transaction.cpp
  storage/falcon/ha_falcon.cpp
  storage/falcon/ha_falcon.h

 2786 Vladislav Vaintroub	2008-08-15 [merge]
      merge
modified:
  mysql-test/include/have_falcon.inc

=== modified file 'storage/falcon/DenseArray.h'
--- a/storage/falcon/DenseArray.h	2007-11-30 18:19:43 +0000
+++ b/storage/falcon/DenseArray.h	2008-08-18 05:45:29 +0000
@@ -47,17 +47,35 @@ public:
 		if (newLength < length)
 			return;
 			
+		T *newVector = new T[newLength];
+		T *oldVector = vector;
+		memcpy((void*) newVector, (void*) vector, length * sizeof(T));
+		memset((void*) (newVector + length), 0, (newLength - length) * sizeof(T));
+		vector = newVector;
+		int oldLength = length;
+		length = newLength;
+		memset((void*) oldVector, 0xbc, oldLength * sizeof(T));
+		delete [] oldVector;
+		
+		/**		
 		T *oldVector = vector;
 		vector = new T[newLength];
 		memcpy((void*) vector, (void*) oldVector, length * sizeof(T));
 		memset((void*) (vector + length), 0, (newLength - length) * sizeof(T));
 		length = newLength;
+		**/
 		};
 	
 	void zap ()
 		{
 		memset((void*) vector, 0, length * sizeof(T));
 		};
+		
+	void zap (uint n)
+		{
+		if (n < length)
+			memset(vector + n, 0, sizeof(T));
+		}
 	
 	T get (uint index)
 		{

=== 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-18 05:45:29 +0000
@@ -45,6 +45,7 @@
 #include "RSet.h"
 #include "WalkIndex.h"
 #include "WalkDeferred.h"
+// #include "Interlock.h" // debug
 
 #define SEGMENT_BYTE(segment,count)		((indexVersion >= INDEX_VERSION_1) ? count - segment : segment)
 #define PAD_BYTE(field)					((indexVersion >= INDEX_VERSION_1) ? field->indexPadByte : 0)
@@ -107,14 +108,20 @@ 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");
+
+	/*** debug
+	useCount = 1;
+	syncObject.setName("Index::syncObject");
+	***/
 }
 
 Index::~Index()
 {
+	// ASSERT(useCount <= 2); // debug
+	
 	if (deferredIndexes.first)
 		{
 		Sync sync(&deferredIndexes.syncObject, "Index::~Index");
@@ -1139,3 +1146,35 @@ void Index::scanDIHash(IndexKey* scanKey
 			}
 		}
 }
+
+#if 0 //debug
+void Index::lock(bool exclusiveLock)
+{
+	syncObject.lock(NULL, (exclusiveLock) ? Exclusive : Shared);
+}
+
+void Index::unlock(void)
+{
+	syncObject.unlock();
+}
+
+void Index::addRef()
+{
+	INTERLOCKED_INCREMENT(useCount);
+}
+
+void Index::release()
+{
+	ASSERT (useCount > 0);
+
+	if (INTERLOCKED_DECREMENT(useCount) == 0)
+		{
+		/*** debugging only
+		int cnt = useCount;
+		Table *t = table;
+		const char *tableName = table->name;
+		***/
+		//delete this; // disabled for debug
+		}
+}
+#endif

=== modified file 'storage/falcon/Index.h'
--- a/storage/falcon/Index.h	2008-05-02 22:09:28 +0000
+++ b/storage/falcon/Index.h	2008-08-18 05:45:29 +0000
@@ -26,6 +26,7 @@
 
 #include "Types.h"
 #include "Queue.h"
+//#include "SyncObject.h" // debug
 
 static const int INDEX_VERSION_0		= 0;
 static const int INDEX_VERSION_1		= 1;
@@ -128,6 +129,15 @@ public:
 	Index(Table *tbl, const char *indexName, int indexType, int id, int numberFields);
 	virtual ~Index();
 
+	/*** debug
+	virtual void	lock(bool exclusiveLock);
+	virtual void	unlock(void);
+	void			release();
+	void			addRef();
+	SyncObject	syncObject; // debug
+	volatile INTERLOCK_TYPE useCount;
+	***/
+
 	Table		*table;
 	Database	*database;
 	Dbb			*dbb;

=== 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 05:45:29 +0000
@@ -688,7 +688,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 +713,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 +746,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 +753,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-18 05:45:29 +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();
 
@@ -98,8 +100,6 @@ int StorageTable::truncateTable(void)
 	return ret;
 }
 
-
-
 int StorageTable::insert(void)
 {
 	try
@@ -139,6 +139,16 @@ int StorageTable::updateRow(int recordNu
 	return 0;
 }
 
+int StorageTable::createIndex(StorageIndexDesc *indexDesc, int indexCount, const char *sql)
+{
+	return share->createIndex(storageConnection, indexDesc, indexCount, 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 +184,66 @@ 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;
+		}
+		
+	/*** debug
+	if (currentIndex->index)
+		currentIndex->index->addRef();
+	else
+		currentIndex->index = NULL;
+	***/
 
 	upperBound = lowerBound = NULL;
 	searchFlags = 0;
+	return 0;
+}
+	
+int StorageTable::clearCurrentIndex()
+{
+	/*** debug
+	if (currentIndex)
+		if (currentIndex->index)
+			currentIndex->index->release();
+		else
+			currentIndex->index = NULL;
+	***/
 	
+	if (indexesLocked)
+		{
+		share->unlockIndexes();
+		indexesLocked = false;
+		}
+
+	currentIndex = NULL;
+	upperBound = lowerBound = NULL;
+	searchFlags = 0;
 	return 0;
 }
 
+int StorageTable::setIndex(int indexCount, StorageIndexDesc* indexDesc)
+{
+	return share->setIndex(indexCount, indexDesc);
+}
+
 int StorageTable::indexScan(int indexOrder)
 {
 	if (!currentIndex)
+		{
+		clearCurrentIndex();
 		return StorageErrorNoIndex;
+		}
 	
 	int numberSegments = (upperBound) ?  upperBound->numberSegments : (lowerBound) ? lowerBound->numberSegments : 0;
 	
@@ -203,26 +258,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 +281,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-18 05:45:29 +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(int indexCount, 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, int indexCount, 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-18 05:45:29 +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
@@ -63,13 +60,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);
+	numberIndexes = 0;
 
 	if (tempTable)
 		tableSpace = TEMPORARY_TABLESPACE;
@@ -82,29 +81,37 @@ StorageTableShare::StorageTableShare(Sto
 StorageTableShare::~StorageTableShare(void)
 {
 	delete syncObject;
+	delete syncIndexes;
 	delete [] impure;
 	
 	if (storageDatabase)
 		storageDatabase->release();
 		
-	if (indexes)
-		{
-		for (int n = 0; n < numberIndexes; ++n)
-			delete indexes[n];
-			
-		delete [] indexes;
-		indexes = NULL;
-		}
+	for (uint n = 0; n < indexes.length; n++)
+		if (indexes.vector[n])
+			delete indexes.get(n);
 }
 
 void StorageTableShare::lock(bool exclusiveLock)
 {
-	syncObject->lock(NULL, (exclusiveLock) ? Exclusive : Shared);
+	//syncObject->lock(NULL, (exclusiveLock) ? Exclusive : Shared);
+	syncIndexes->lock(NULL, (exclusiveLock) ? Exclusive : Shared);
 }
 
 void StorageTableShare::unlock(void)
 {
-	syncObject->unlock();
+	//syncObject->unlock();
+	syncIndexes->unlock();
+}
+
+void StorageTableShare::lockIndexes(bool exclusiveLock)
+{
+	syncIndexes->lock(NULL, (exclusiveLock) ? Exclusive : Shared);
+}
+
+void StorageTableShare::unlockIndexes(void)
+{
+	syncIndexes->unlock();
 }
 
 int StorageTableShare::open(void)
@@ -189,7 +196,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 +218,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 +248,54 @@ 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, int indexCount, const char *sql)
 {
 	if (!table)
 		open();
 
-	return storageDatabase->createIndex(storageConnection, table, name, sql);
+	// Always get syncIndexes before syncObject
+	
+	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(indexCount, indexDesc);
+		
+	return ret;
 }
 
-int StorageTableShare::dropIndex(StorageConnection *storageConnection, const char* name, const char* sql)
+int StorageTableShare::dropIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql)
 {
 	if (!table)
 		open();
 
-	return storageDatabase->dropIndex(storageConnection, table, name, sql);
+	// Always get syncIndexes before syncObject
+
+	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)
+		clearIndex(indexDesc);
+				
+	return ret;
 }
 
 int StorageTableShare::renameTable(StorageConnection *storageConnection, const char* newName)
@@ -274,72 +317,132 @@ int StorageTableShare::renameTable(Stora
 	return ret;
 }
 
-StorageIndexDesc* StorageTableShare::getIndex(int indexCount, int indexId, StorageIndexDesc* indexDesc)
+void StorageTableShare::resizeIndexes(int indexCount)
 {
-	// Rebuild array if indexes have been added or dropped
+	if (indexCount <= 0)
+		return;
 	
-#ifdef ONLINE_ALTER
+	if ((uint)indexCount > indexes.length)
+		indexes.extend(indexCount + 5);
 
-	// TODO: This does not work. It should be done at the time of index creation
+	numberIndexes = indexCount;
+}
 
-	if (indexes && (numberIndexes != indexCount))
+int StorageTableShare::setIndex(int indexCount, const StorageIndexDesc *indexInfo)
 		{
-		Sync sync(syncObject, "StorageTableShare::getIndex");
-		sync.lock(Exclusive);
-		StorageIndexDesc **oldIndexes = indexes;
-		StorageIndexDesc **newIndexes = new StorageIndexDesc*[indexCount];
-		memset(newIndexes, 0, indexCount * sizeof(StorageIndexDesc*));
+	int indexId = indexInfo->id;
 		
-		for (int n = 0; n < numberIndexes; ++n)
-			newIndexes[n] = indexes[n];
+	if ((uint)indexId >= indexes.length || numberIndexes < indexCount)
+		resizeIndexes(indexCount);
 		
-		indexes = newIndexes;
-		numberIndexes = indexCount;
-		delete [] oldIndexes;
-		}
-#endif
+	// Allocate a new index if necessary
 	
-	if (!indexes)
-		{
-		indexes = new StorageIndexDesc*[indexCount];
-		memset(indexes, 0, indexCount * sizeof(StorageIndexDesc*));
-		numberIndexes = indexCount;
-		}
+	StorageIndexDesc *indexDesc = indexes.get(indexId);
 	
-	if (indexId >= numberIndexes)
-		return NULL;
+	if (!indexDesc)
+		indexes.vector[indexId] = indexDesc = new StorageIndexDesc(indexId);
 	
-	StorageIndexDesc *index = indexes[indexId];
+	// Copy index description info
 	
-	if (index)
-		return index;
+	*indexDesc = *indexInfo;
 
-	indexes[indexId] = index = new StorageIndexDesc;
-	*index = *indexDesc;
+	// Find the corresponding Falcon index
 	
 	if (indexDesc->primaryKey)
-		index->index = table->primaryKey;
+		indexDesc->index = table->primaryKey;
 	else
 		{
-		char indexName[150];
-		sprintf(indexName, "%s$%d", (const char*) name, indexId);
-		index->index = storageDatabase->findIndex(table, indexName);
+		char indexName[indexNameSize];
+		sprintf(indexName, "%s$%s", name.getString(), indexDesc->name.getString());
+		indexDesc->index = table->findIndex(indexName);
 		}
 
-	if (index->index)
-		index->segmentRecordCounts = index->index->recordsPerSegment;
+	int ret = 0;
+	
+	if (indexDesc->index)
+		indexDesc->segmentRecordCounts = indexDesc->index->recordsPerSegment;
 	else
-		index = NULL;
+		ret = StorageErrorNoIndex;
 	
-	return index;
+	ASSERT((!ret ? validateIndexes() : true));
+		
+	return ret;
+}
+
+void StorageTableShare::clearIndex(StorageIndexDesc *indexDesc)
+{
+	if (numberIndexes > 0)
+		{
+		for (int n = indexDesc->id; n < numberIndexes-1; n++)
+			{
+			indexes.vector[n] = indexes.vector[n+1];
+			indexes.vector[n]->id = n; // assume that index id will match server
+			}
+			
+		indexes.zap(numberIndexes-1);
+		numberIndexes--;
+		}
+		
+	ASSERT(validateIndexes());
+}
+
+bool StorageTableShare::validateIndexes()
+{
+	for (int n = 0; n < numberIndexes; n++)
+		{
+		StorageIndexDesc *indexDesc = indexes.get(n);
+		if (indexDesc && indexDesc->id != n)
+			return false;
+		}
+			
+	return true;
 }
 
 StorageIndexDesc* StorageTableShare::getIndex(int indexId)
 {
-	if (!indexes || indexId >= numberIndexes)
+	if (!indexes.length || indexId >= numberIndexes)
 		return NULL;
 	
-	return indexes[indexId];
+	ASSERT(validateIndexes());
+	
+	return indexes.get(indexId);
+}
+
+StorageIndexDesc* StorageTableShare::getIndex(int indexId, StorageIndexDesc *indexDesc)
+{
+	StorageIndexDesc *index;
+	
+	if (!indexes.length || indexId >= numberIndexes)
+		index = NULL;
+	else
+		{
+		Sync sync(syncObject, "StorageTableShare::getIndex");
+		sync.lock(Shared);
+	
+		ASSERT(validateIndexes());
+
+		index = indexes.get(indexId);
+	
+		if (index)
+			*indexDesc = *index;
+		}
+		
+	return index;
+}
+
+StorageIndexDesc* StorageTableShare::getIndex(const char *name)
+{
+	Sync sync(syncObject, "StorageTableShare::getIndex(name)");
+	sync.lock(Shared);
+	
+	for (int i = 0; i < numberIndexes; i++)
+		{
+		StorageIndexDesc *indexDesc = indexes.get(i);
+		if (indexDesc && indexDesc->name == name)
+			return indexDesc;
+		}
+
+	return NULL;
 }
 
 INT64 StorageTableShare::getSequenceValue(int delta)
@@ -365,34 +468,44 @@ int StorageTableShare::setSequenceValue(
 	return 0;
 }
 
+// Get index id using the internal (Falcon) index name
+
 int StorageTableShare::getIndexId(const char* schemaName, const char* indexName)
 {
-	if (indexes)
+	if (indexes.length > 0)
 		for (int n = 0; n < numberIndexes; ++n)
 			{
-			Index *index = indexes[n]->index;
+			Index *index = indexes.get(n)->index;
 			
 			if (strcmp(index->getIndexName(), indexName) == 0 &&
 				strcmp(index->getSchemaName(), schemaName) == 0)
+				{
+//				if (n != indexes.get(n)->id) //debug
+//					return n;
 				return n;
 			}
+			}
 		
 	return -1;
 }
 
 int StorageTableShare::haveIndexes(int indexCount)
 {
-	if (indexes == NULL)
+	if (indexes.length == 0)
 		return false;
 		
-#ifdef ONLINE_ALTER
-	if (indexCount != numberIndexes)
+	if (indexCount > numberIndexes)
 		return false;
-#endif	
 	
 	for (int n = 0; n < numberIndexes; ++n)
-		if (indexes[n]== NULL)
+		{
+		StorageIndexDesc* index = indexes.get(n);
+		if (!index)
 			return false;
+			
+		if (index && !index->index)
+			return false;
+		}
 	
 	return true;
 }

=== 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-18 05:45:29 +0000
@@ -18,6 +18,7 @@
 
 #include "JString.h"
 #include "SyncObject.h"
+#include "DenseArray.h"
 
 #ifndef _WIN32
 #define __int64			long long
@@ -26,6 +27,7 @@
 typedef __int64			INT64;
 
 static const int MaxIndexSegments	= 16;
+static const int indexNameSize		= 257;
 
 class StorageDatabase;
 class StorageConnection;
@@ -47,11 +49,17 @@ struct StorageSegment {
 	void			*mysql_charset;
 	};
 
-struct StorageIndexDesc {
+class StorageIndexDesc
+{
+public:
+	StorageIndexDesc(int indexId=0) : id (indexId), unique(0), primaryKey(0), numberSegments(0), /*name(NULL),*/ index(NULL), segmentRecordCounts(NULL){};
+	
+	int			id;//cwp
 	int			unique;
 	int			primaryKey;
 	int			numberSegments;
-	const char	*name;
+	JString		name;			// clean name
+	JString		rawName;		// original name
 	Index		*index;
 	uint64		*segmentRecordCounts;
 	StorageSegment segments[MaxIndexSegments];
@@ -95,22 +103,28 @@ 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, int indexCount, const char *sql);
+	virtual int			dropIndex(StorageConnection *storageConnection, StorageIndexDesc *indexDesc, const char *sql);
 	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				resizeIndexes(int indexCount);
+	int					setIndex(int indexCount, const StorageIndexDesc* indexInfo);
+	void				clearIndex(StorageIndexDesc *indexDesc);
+	bool				validateIndexes();
 	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 +143,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,10 +155,11 @@ public:
 	unsigned char		*impure;
 	int					initialized;
 	SyncObject			*syncObject;
+	SyncObject			*syncIndexes;
 	StorageDatabase		*storageDatabase;
 	StorageHandler		*storageHandler;
 	Table				*table;
-	StorageIndexDesc	**indexes;
+	DenseArray<StorageIndexDesc *,10> indexes;
 	Sequence			*sequence;
 	Format				*format;						// format for insertion
 	int					numberIndexes;

=== 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/Transaction.cpp'
--- a/storage/falcon/Transaction.cpp	2008-08-14 11:18:42 +0000
+++ b/storage/falcon/Transaction.cpp	2008-08-18 05:45:29 +0000
@@ -300,17 +300,19 @@ void Transaction::commit()
 	database->flushInversion(this);
 
 	// Transfer transaction from active list to committed list, set committed state
+
 	Sync syncCommitted(&transactionManager->committedTransactions.syncObject, "Transaction::commit(2)");
 	Sync syncActiveTransactions(&transactionManager->activeTransactions.syncObject, "Transaction::commit(3)");
-	syncCommitted.lock(Exclusive);
+
 	syncActiveTransactions.lock(Exclusive);
+	syncCommitted.lock(Exclusive);
 
 	transactionManager->activeTransactions.remove(this);
 	transactionManager->committedTransactions.append(this);
 	state = Committed;
 
-	syncActiveTransactions.unlock();
 	syncCommitted.unlock();
+	syncActiveTransactions.unlock();
 
 	database->commit(this);
 

=== 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-18 05:45:29 +0000
@@ -54,7 +54,7 @@
 #endif
 
 #ifndef ONLINE_ALTER
-//#define ONLINE_ALTER
+#define ONLINE_ALTER
 #endif
 
 #ifdef DEBUG_BACKLOG
@@ -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(indexId);
+	getKeyDesc(table, indexId, &indexDesc);
+	
+	char indexName[indexNameSize];
+	storageShare->createIndexName(indexDesc.name.getString(), 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, table->s->keys, 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(indexId);
+	getKeyDesc(table, indexId, &indexDesc);
+	
+	char indexName[indexNameSize];
+	storageShare->createIndexName(indexDesc.name.getString(), 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
@@ -963,6 +987,7 @@ int StorageInterface::delete_table(const
 
 	if (storageShare)
 		{
+//		storageShare->lockIndexes(true);
 		storageShare->lock(true);
 
 		if (storageShare->initialized)
@@ -973,6 +998,7 @@ int StorageInterface::delete_table(const
 			}
 
 		storageShare->unlock();
+//		storageShare->unlockIndexes();
 		}
 
 	int res = storageTable->deleteTable();
@@ -1358,7 +1384,6 @@ int StorageInterface::index_read(uchar *
 		}
 }
 
-
 int StorageInterface::index_init(uint idx, bool sorted)
 {
 	DBUG_ENTER("StorageInterface::index_init");
@@ -1367,33 +1392,24 @@ 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)
 		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 +1422,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 +1432,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 +1452,27 @@ 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];
+	
+	indexDesc->rawName		  = keyInfo->name;
+	storageShare->cleanupFieldName(indexDesc->rawName, nameBuffer, sizeof(nameBuffer));
+	indexDesc->name			  = nameBuffer;
+	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 +1493,6 @@ void StorageInterface::getKeyDesc(KEY *k
 		}
 }
 
-
 int StorageInterface::rename_table(const char *from, const char *to)
 {
 	DBUG_ENTER("StorageInterface::rename_table");
@@ -1489,17 +1509,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 +1651,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 +1670,6 @@ int StorageInterface::index_next_same(uc
 		}
 }
 
-
 double StorageInterface::scan_time(void)
 {
 	DBUG_ENTER("StorageInterface::scan_time");
@@ -1691,13 +1706,11 @@ bool StorageInterface::threadSwitch(THD*
 	return true;
 }
 
-
 int StorageInterface::threadSwitchError(void)
 {
 	return 1;
 }
 
-
 int StorageInterface::error(int storageError)
 {
 	DBUG_ENTER("StorageInterface::error");
@@ -1737,7 +1750,6 @@ int StorageInterface::error(int storageE
 	DBUG_RETURN(mySqlError);
 }
 
-
 int StorageInterface::getMySqlError(int storageError)
 {
 	switch (storageError)
@@ -1856,8 +1868,6 @@ int StorageInterface::reset()
 	DBUG_RETURN(0);
 }
 
- 
- 
 int StorageInterface::external_lock(THD *thd, int lock_type)
 {
 	DBUG_ENTER("StorageInterface::external_lock");
@@ -1873,7 +1883,10 @@ int StorageInterface::external_lock(THD 
 			storageConnection->releaseVerb();
 
 		if (storageTable)
+			{
 			storageTable->clearStatement();
+			storageTable->clearCurrentIndex();
+			}
 		}
 	else
 		{
@@ -1894,6 +1907,9 @@ int StorageInterface::external_lock(THD 
 
 				if (ret)
 					{
+					if (storageTable)
+						storageTable->clearCurrentIndex();
+						
 					DBUG_RETURN(error(ret));
 					}
 				}
@@ -1910,9 +1926,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 +1936,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 +1949,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 +1966,6 @@ void StorageInterface::get_auto_incremen
 	DBUG_VOID_RETURN;
 }
 
-
 const char *StorageInterface::index_type(uint key_number)
 {
   DBUG_ENTER("StorageInterface::index_type");
@@ -1971,7 +1980,6 @@ void StorageInterface::dropDatabase(hand
 	DBUG_VOID_RETURN;
 }
 
-
 void StorageInterface::freeActiveBlobs(void)
 {
 	for (StorageBlob *blob; (blob = activeBlobs); )
@@ -1983,14 +1991,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 +2005,6 @@ int StorageInterface::panic(handlerton* 
 	return 0;
 }
 
-
 int StorageInterface::closeConnection(handlerton *hton, THD *thd)
 {
 	DBUG_ENTER("NfsStorageEngine::closeConnection");
@@ -2009,7 +2014,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");
@@ -2243,10 +2247,11 @@ int StorageInterface::addIndex(THD* thd,
 					break;
 					
 			if (tableKey >= tableEnd)
-				if ((ret = createIndex(schemaName, tableName, key, n)))
+				if ((ret = createIndex(schemaName, tableName, alteredTable, n)))
 					return (error(ret));
 			}
 		}
+		
 	return 0;
 }
 
@@ -2271,7 +2276,7 @@ int StorageInterface::dropIndex(THD* thd
 					break;
 
 			if (alterKey >= alterEnd)
-				if ((ret = dropIndex(schemaName, tableName, key, n)))
+				if ((ret = dropIndex(schemaName, tableName, table, n)))
 				return (error(ret));
 				}
 		}
@@ -2288,7 +2293,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 +2302,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 +2317,31 @@ void StorageInterface::logger(int mask, 
 		}
 }
 
+int StorageInterface::setIndex(TABLE *table, int indexId)
+{
+	StorageIndexDesc indexDesc(indexId);
+	getKeyDesc(table, indexId, &indexDesc);
+
+	return storageTable->setIndex(table->s->keys, &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 (n == table->s->primary_key)
-				indexDesc.primaryKey = true;
+			if ((ret = setIndex(table, n)))
+				break;
 
-			int ret = storageTable->setIndex(table->s->keys, n, &indexDesc);
-			if (ret)
-				return ret;
-			}
-		}
+	storageShare->unlockIndexes();
 
-	storageShare->unlock();
-	return 0;
+	return ret;
 }
 
 int StorageInterface::genTable(TABLE* table, CmdGen* gen)
@@ -2348,7 +2350,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 +2497,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 +2519,6 @@ void StorageInterface::genKeyFields(KEY*
 	gen->gen(")");
 }
 
-
 void StorageInterface::encodeRecord(uchar *buf, bool updateFlag)
 {
 	storageTable->preInsert();
@@ -3504,7 +3503,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-18 05:45:29 +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,14 +113,16 @@ 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				genTable(TABLE* table, CmdGen* gen);
 	int				genType(Field *field, CmdGen *gen);

Thread
bzr push into mysql-6.0-falcon branch (cpowers:2786 to 2787) Bug#38039Bug#38041 Bug#38043 Bug#38044Christopher Powers18 Aug