List:Commits« Previous MessageNext Message »
From:Christopher Powers Date:September 8 2008 7:48pm
Subject:bzr push into mysql-6.0-falcon branch (cpowers:2813 to 2814) Bug#38041
View as plain text  
 2814 Christopher Powers	2008-09-08
      Bug#38041 Bizarre errors when ALTER ADD/DROP KEY on Falcon tables
      
      - Added validation methods to detect out-of-sync condition between server and falcon indexes
      - Don't create StorageIndexDesc objects if internal falcon index does not exist
      - Enabled HA_ADD/DROP_UNIQUE_INDEX
      - Rebuild index mapping when table is renamed
modified:
  storage/falcon/Configuration.cpp
  storage/falcon/StorageTable.cpp
  storage/falcon/StorageTableShare.cpp
  storage/falcon/StorageTableShare.h
  storage/falcon/ha_falcon.cpp
  storage/falcon/ha_falcon.h

 2813 Vladislav Vaintroub	2008-09-08
      Add missing dependency to perror  to avoid  compile error in multiprocessor builds
modified:
  extra/CMakeLists.txt

=== modified file 'storage/falcon/Configuration.cpp'
--- a/storage/falcon/Configuration.cpp	2008-08-29 20:41:13 +0000
+++ b/storage/falcon/Configuration.cpp	2008-09-08 19:46:25 +0000
@@ -42,7 +42,6 @@
 #include "SQLError.h"
 #include "Log.h"
 #include "IOx.h"
-#include "ScanDir.h"
 
 #ifndef ULL
 #define ULL(a)		((uint64) a)

=== modified file 'storage/falcon/StorageTable.cpp'
--- a/storage/falcon/StorageTable.cpp	2008-08-22 06:47:40 +0000
+++ b/storage/falcon/StorageTable.cpp	2008-09-08 19:46:25 +0000
@@ -195,7 +195,7 @@ int StorageTable::setCurrentIndex(int in
 		}
 	
 	if (!(currentIndex = share->getIndex(indexId)))
-{
+		{
 		clearCurrentIndex();
 		return StorageErrorNoIndex;
 		}

=== modified file 'storage/falcon/StorageTableShare.cpp'
--- a/storage/falcon/StorageTableShare.cpp	2008-09-03 22:17:54 +0000
+++ b/storage/falcon/StorageTableShare.cpp	2008-09-08 19:46:25 +0000
@@ -62,10 +62,10 @@ StorageIndexDesc::StorageIndexDesc()
 	rawName[0] = '\0';
 };
 
-StorageIndexDesc::StorageIndexDesc(const StorageIndexDesc *indexInfo)
+StorageIndexDesc::StorageIndexDesc(const StorageIndexDesc *indexDesc)
 {
-	if (indexInfo)
-		*this = *indexInfo;
+	if (indexDesc)
+		*this = *indexDesc;
 	else
 		{
 		id = 0;
@@ -86,6 +86,35 @@ StorageIndexDesc::~StorageIndexDesc(void
 {
 }
 
+bool StorageIndexDesc::operator==(const StorageIndexDesc &indexDesc) const
+{
+	if ( !(id			  == indexDesc.id
+		&& unique		  == indexDesc.unique
+		&& primaryKey 	  == indexDesc.primaryKey
+		&& numberSegments == indexDesc.numberSegments))
+		return false;
+
+	if (strcmp(indexDesc.name, name) != 0)
+		return false;
+	
+	/***
+	const char *q = indexDesc.name;
+	const char *p = name;
+	
+	for (; (*p && *q); ++p, ++q)
+		if (*p != *q)
+			return false;
+	***/
+
+	return true;
+}
+
+bool StorageIndexDesc::operator!=(const StorageIndexDesc &indexDesc) const
+{
+	return !(*this == indexDesc);
+}
+
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -285,11 +314,17 @@ const char* StorageTableShare::cleanupTa
 	return buffer;
 }
 
-char* StorageTableShare::createIndexName(const char *rawName, char *indexName)
+char* StorageTableShare::createIndexName(const char *rawName, char *indexName, bool primary)
 {
-	char nameBuffer[indexNameSize];
-	cleanupFieldName(rawName, nameBuffer, sizeof(nameBuffer));
-	sprintf(indexName, "%s$%s", name.getString(), nameBuffer);
+	if (primary)
+		strcpy(indexName, table->getPrimaryKeyName().getString());
+	else
+		{
+		char nameBuffer[indexNameSize];
+		cleanupFieldName(rawName, nameBuffer, sizeof(nameBuffer));
+		sprintf(indexName, "%s$%s", name.getString(), nameBuffer);
+		}
+	
 	return indexName;
 }
 
@@ -362,12 +397,35 @@ int StorageTableShare::dropIndex(Storage
 	
 	int ret = storageDatabase->dropIndex(storageConnection, table, sql);
 	
-	if (!ret)
-		deleteIndex(indexDesc->id);
+	deleteIndex(indexDesc->id);
 				
 	return ret;
 }
 
+bool StorageTableShare::validateIndex(int indexId, StorageIndexDesc *indexTarget)
+{
+	StorageIndexDesc *indexDesc = getIndex(indexId);
+	
+	if (!indexDesc || *indexDesc != *indexTarget)
+		return false;
+	
+	Index *index = table->findIndex(indexDesc->name);
+	
+	if (!index)
+		return false;
+	
+	if (index != indexDesc->index)
+		return false;
+	
+	if (indexTarget->primaryKey && index->type != PrimaryKey)
+		return false;
+			
+	if (index->recordsPerSegment != indexDesc->segmentRecordCounts)
+		return false;
+	
+	return true;
+}
+
 void StorageTableShare::deleteIndexes()
 {
 	for (StorageIndexDesc *indexDesc; (indexDesc = indexes);)
@@ -377,6 +435,16 @@ void StorageTableShare::deleteIndexes()
 		}
 }
 
+int StorageTableShare::numberIndexes()
+{
+	int indexCount = 0;
+	
+	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next, indexCount++)
+		;
+	
+	return indexCount;
+}
+
 int StorageTableShare::renameTable(StorageConnection *storageConnection, const char* newName)
 {
 	char tableName[256];
@@ -402,24 +470,25 @@ int StorageTableShare::setIndex(const St
 
 	if (!getIndex(indexInfo->id))
 		{
-		StorageIndexDesc *indexDesc = new StorageIndexDesc(indexInfo);
-		addIndex(indexDesc);
 
-	// Find the corresponding Falcon index
-	
-	if (indexDesc->primaryKey)
-		indexDesc->index = table->primaryKey;
-	else
-		{
-		char indexName[indexNameSize];
-		sprintf(indexName, "%s$%s", name.getString(), indexDesc->name);
-		indexDesc->index = table->findIndex(indexName);
-		}
+		// Find the corresponding Falcon index else fail
 
-	if (indexDesc->index)
-		indexDesc->segmentRecordCounts = indexDesc->index->recordsPerSegment;
-	else
-		ret = StorageErrorNoIndex;
+		Index *index;
+		
+		if (indexInfo->primaryKey)
+			index = table->primaryKey;
+		else
+			index = table->findIndex(indexInfo->name);
+		
+		if (index)
+			{
+			StorageIndexDesc *indexDesc = new StorageIndexDesc(indexInfo);
+			indexDesc->index = index;
+			indexDesc->segmentRecordCounts = indexDesc->index->recordsPerSegment;
+			addIndex(indexDesc);
+			}
+		else
+			ret = StorageErrorNoIndex;
 		}
 		
 	return ret;
@@ -432,7 +501,10 @@ StorageIndexDesc* StorageTableShare::get
 			
 	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
 		if (indexDesc->id == indexId)
+			{
+			ASSERT(indexDesc->index != NULL);
 			return indexDesc;
+			}
 		
 	return NULL;
 }
@@ -462,8 +534,11 @@ StorageIndexDesc* StorageTableShare::get
 	sync.lock(Shared);
 	
 	for (StorageIndexDesc *indexDesc = indexes; indexDesc; indexDesc = indexDesc->next)
-		if (indexDesc->name == name)
+		if (!strcmp(indexDesc->name, name))
+			{
+			ASSERT(indexDesc->index != NULL);
 			return indexDesc;
+			}
 			
 	return NULL;
 }

=== modified file 'storage/falcon/StorageTableShare.h'
--- a/storage/falcon/StorageTableShare.h	2008-08-22 06:47:40 +0000
+++ b/storage/falcon/StorageTableShare.h	2008-09-08 19:46:25 +0000
@@ -53,8 +53,10 @@ class StorageIndexDesc
 {
 public:
 	StorageIndexDesc();
-	StorageIndexDesc(const StorageIndexDesc *indexInfo);
+	StorageIndexDesc(const StorageIndexDesc *indexDesc);
 	virtual ~StorageIndexDesc(void);
+	bool operator==(const StorageIndexDesc &indexDesc) const;
+	bool operator!=(const StorageIndexDesc &indexDesc) const;
 	
 	int			id;
 	int			unique;
@@ -113,7 +115,9 @@ public:
 	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 bool		validateIndex(int indexId, StorageIndexDesc *indexTarget);
 	virtual void		deleteIndexes();
+	virtual int			numberIndexes();
 	virtual int			renameTable(StorageConnection *storageConnection, const char* newName);
 	virtual INT64		getSequenceValue(int delta);
 	virtual int			setSequenceValue(INT64 value);
@@ -148,7 +152,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);
+	char*				createIndexName(const char *rawName, char *indexName, bool primary = false);
 	
 	JString				name;
 	JString				schemaName;

=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp	2008-09-05 16:26:12 +0000
+++ b/storage/falcon/ha_falcon.cpp	2008-09-08 19:46:25 +0000
@@ -518,11 +518,11 @@ int StorageInterface::open(const char *n
 
 	thr_lock_data_init((THR_LOCK *)storageShare->impure, &lockData, NULL);
 
-	ret = setIndexes();
-	
 	if (table)
 		mapFields(table);
 	
+	setIndexes(table);
+	
 	if (ret)
 		DBUG_RETURN(error(ret));
 
@@ -850,6 +850,8 @@ int StorageInterface::create(const char 
 				}
 
 	mapFields(form);
+	
+	setIndexes(table);
 
 	DBUG_RETURN(0);
 }
@@ -868,12 +870,9 @@ int StorageInterface::createIndex(const 
 	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\" on %s.\"%s\" ", unique, indexName, schemaName, tableName);
+	gen.gen("create %sindex \"%s\" on %s.\"%s\" ", unique, indexDesc.name, schemaName, tableName);
 	genKeyFields(key, &gen);
 	const char *sql = gen.getString();
 
@@ -885,11 +884,8 @@ int StorageInterface::dropIndex(const ch
 	StorageIndexDesc indexDesc;
 	getKeyDesc(table, indexId, &indexDesc);
 	
-	char indexName[indexNameSize];
-	storageShare->createIndexName(indexDesc.name, indexName);
-
 	CmdGen gen;
-	gen.gen("drop index %s.\"%s\"", schemaName, indexName);
+	gen.gen("drop index %s.\"%s\"", schemaName, indexDesc.name);
 	const char *sql = gen.getString();
 
 	return storageTable->dropIndex(&indexDesc, sql);
@@ -1394,8 +1390,9 @@ int StorageInterface::index_init(uint id
 	nextRecord = 0;
 	haveStartKey = false;
 	haveEndKey = false;
+	int ret = 0;
 
-	int ret = storageTable->setCurrentIndex(idx);
+	ret = storageTable->setCurrentIndex(idx);
 
 	if (ret)
 		{
@@ -1403,6 +1400,8 @@ int StorageInterface::index_init(uint id
 		ret = storageTable->setCurrentIndex(idx);
 		}
 		
+	// validateIndexes(table);
+		
 	if (ret)
 		DBUG_RETURN(error(ret));
 
@@ -1465,22 +1464,18 @@ void StorageInterface::getKeyDesc(TABLE 
 {
 	KEY *keyInfo = table->key_info + indexId;
 	int numberKeys = keyInfo->key_parts;
-	char nameBuffer[indexNameSize];
+	
+	indexDesc->id			  = indexId;
+	indexDesc->numberSegments = numberKeys;
+	indexDesc->unique		  = (keyInfo->flags & HA_NOSAME);
+	indexDesc->primaryKey	  = (table->s->primary_key == (uint)indexId);
 	
 	// 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';
+	storageShare->createIndexName(indexDesc->rawName, indexDesc->name, indexDesc->primaryKey);
 	
-	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 = indexDesc->segments + n;
@@ -1519,8 +1514,17 @@ int StorageInterface::rename_table(const
 	if (ret)
 		DBUG_RETURN(error(ret));
 
+	storageTable->clearCurrentIndex();
+	storageShare->lockIndexes(true);
+	storageShare->lock(true);
+
 	ret = storageShare->renameTable(storageConnection, to);
 	
+	remapIndexes(table);
+	
+	storageShare->unlock();
+	storageShare->unlockIndexes();
+
 	if (ret)
 		DBUG_RETURN(error(ret));
 
@@ -1541,6 +1545,7 @@ int StorageInterface::read_range_first(c
 	storageTable->clearIndexBounds();
 	haveStartKey = false;
 	haveEndKey = false;
+	int ret = 0;
 
 	if (start_key && !storageTable->isKeyNull((const unsigned char*) start_key->key, start_key->length))
 		{
@@ -1563,7 +1568,7 @@ int StorageInterface::read_range_first(c
 		if (end_key->flag == HA_READ_BEFORE_KEY)
 			storageTable->setReadBeforeKey();
 
-		int ret = storageTable->setIndexBound((const unsigned char*) end_key->key,
+		ret = storageTable->setIndexBound((const unsigned char*) end_key->key,
 												end_key->length, UpperBound);
 		if (ret)
 			DBUG_RETURN(error(ret));
@@ -2109,10 +2114,9 @@ int StorageInterface::check_if_supported
 	DBUG_ENTER("StorageInterface::check_if_supported_alter");
 	tempTable = (create_info->options & HA_LEX_CREATE_TMP_TABLE) ? true : false;
 	HA_ALTER_FLAGS supported;
-	supported = supported | HA_ADD_INDEX | HA_DROP_INDEX;
+	supported = supported | HA_ADD_INDEX | HA_DROP_INDEX | HA_ADD_UNIQUE_INDEX | HA_DROP_UNIQUE_INDEX;
 						/**
-						| HA_ADD_COLUMN | HA_ADD_UNIQUE_INDEX | HA_DROP_UNIQUE_INDEX
-						| HA_COLUMN_STORAGE | HA_COLUMN_FORMAT;
+						| HA_ADD_COLUMN | HA_COLUMN_STORAGE | HA_COLUMN_FORMAT;
 						**/
 	HA_ALTER_FLAGS notSupported = ~(supported);
 	
@@ -2153,7 +2157,7 @@ int StorageInterface::check_if_supported
 	// 1. Check for supported ALTER combinations
 	// 2. Can error message be improved for non-null columns?
 	
-	if (alter_flags->is_set(HA_ADD_INDEX))
+	if (alter_flags->is_set(HA_ADD_INDEX) || alter_flags->is_set(HA_ADD_UNIQUE_INDEX))
 		{
 		for (unsigned int n = 0; n < altered_table->s->keys; n++)
 			{
@@ -2185,7 +2189,7 @@ int StorageInterface::check_if_supported
 			}
 		}
 		
-	if (alter_flags->is_set(HA_DROP_INDEX))
+	if (alter_flags->is_set(HA_DROP_INDEX) || alter_flags->is_set(HA_DROP_UNIQUE_INDEX))
 		{
 		}
 		
@@ -2200,10 +2204,10 @@ int StorageInterface::alter_table_phase1
 	if (alter_flags->is_set(HA_ADD_COLUMN))
 		ret = addColumn(thd, altered_table, create_info, alter_info, alter_flags);
 		
-	if (alter_flags->is_set(HA_ADD_INDEX) && !ret)
+	if ((alter_flags->is_set(HA_ADD_INDEX) || alter_flags->is_set(HA_ADD_UNIQUE_INDEX)) && !ret)
 		ret = addIndex(thd, altered_table, create_info, alter_info, alter_flags);
 		
-	if (alter_flags->is_set(HA_DROP_INDEX) && !ret)
+	if ((alter_flags->is_set(HA_DROP_INDEX) || alter_flags->is_set(HA_DROP_UNIQUE_INDEX)) && !ret)
 		ret = dropIndex(thd, altered_table, create_info, alter_info, alter_flags);
 		
 	DBUG_RETURN(ret);
@@ -2386,7 +2390,7 @@ int StorageInterface::setIndex(TABLE *ta
 	return storageTable->setIndex(&indexDesc);
 }
 
-int StorageInterface::setIndexes(void)
+int StorageInterface::setIndexes(TABLE *table)
 {
 	int ret = 0;
 	
@@ -2394,14 +2398,14 @@ int StorageInterface::setIndexes(void)
 		return ret;
 
 	storageShare->lockIndexes(true);
+	storageShare->lock(true);
 
-	if (!storageShare->haveIndexes(table->s->keys))
-		for (uint n = 0; n < table->s->keys; ++n)
-			if ((ret = setIndex(table, n)))
-				break;
+	ret = remapIndexes(table);
+	// validateIndexes(table, true);
 
+	storageShare->unlock();
 	storageShare->unlockIndexes();
-
+	
 	return ret;
 }
 
@@ -2409,11 +2413,11 @@ int StorageInterface::remapIndexes(TABLE
 {
 	int ret = 0;
 	
+	storageShare->deleteIndexes();
+
 	if (!table)
 		return ret;
 		
-	storageShare->deleteIndexes();
-
 	for (uint n = 0; n < table->s->keys; ++n)
 		if ((ret = setIndex(table, n)))
 			break;
@@ -2421,6 +2425,32 @@ int StorageInterface::remapIndexes(TABLE
 	return ret;
 }
 
+bool StorageInterface::validateIndexes(TABLE *table, bool exclusiveLock)
+{
+	bool ret = true;
+	
+	if (!table)
+		return false;
+	
+	storageShare->lockIndexes(exclusiveLock);
+		
+	for (uint n = 0; (n < table->s->keys) && ret; ++n)
+		{
+		StorageIndexDesc indexDesc;
+		getKeyDesc(table, n, &indexDesc);
+		
+		if (!storageShare->validateIndex(n, &indexDesc))
+			ret = false;
+		}
+	
+	if (ret && (table->s->keys != (uint)storageShare->numberIndexes()))
+		ret = false;
+	
+	storageShare->unlockIndexes();
+
+	return ret;
+}
+
 int StorageInterface::genTable(TABLE* table, CmdGen* gen)
 {
 	const char *tableName = storageTable->getName();

=== modified file 'storage/falcon/ha_falcon.h'
--- a/storage/falcon/ha_falcon.h	2008-09-03 22:17:54 +0000
+++ b/storage/falcon/ha_falcon.h	2008-09-08 19:46:25 +0000
@@ -122,8 +122,9 @@ public:
 	int				error(int storageError);
 	void			freeActiveBlobs(void);
 	int				setIndex(TABLE *table, int indexId);
-	int				setIndexes(void);
+	int				setIndexes(TABLE *table);
 	int				remapIndexes(TABLE *table);
+	bool			validateIndexes(TABLE *table, bool exclusiveLock = false);
 	int				genTable(TABLE* table, CmdGen* gen);
 	int				genType(Field *field, CmdGen *gen);
 	void			genKeyFields(KEY *key, CmdGen *gen);

Thread
bzr push into mysql-6.0-falcon branch (cpowers:2813 to 2814) Bug#38041Christopher Powers8 Sep