List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:April 2 2009 6:26am
Subject:bzr commit into mysql-6.0-falcon-team branch (vvaintroub:3093)
Bug#43562
View as plain text  
#At file:///G:/bzr/mysql-6.0-falcon-team/ based on revid:kevin.lewis@stripped

 3093 Vladislav Vaintroub	2009-04-02
      Bug#43562 Crash when creating a Falcon table after upgrade from 6.0.9 to 6.0.10
      
      The reason for the crash is that generation of multisegment key format was changed 
      slightly as side-effect of fix for 42136. The new format worked ok with new databases
      but not with the old ones. 
      
      In this particular case, the error comes from Falcon's internal security mechanism. 
      Due to changed index format, a query in Falcon's data dictionary unexpectedly returned 
      an empty result set. This was interpreted was missing privilege to create tables.
      Exception (security error) was thrown and not caught.
      
      Fix:
      
      - Define new minor ODS version 2.4 for databases with changed multisegment index.
      - During the start, perform a check for 2.4 format(MySQL 6.10 would correspond to 
      2.4 Falcon)
      
      When building multisegment indexes, regard the ODS version and create different 
      indexes in 2.3  and 2.4.
     @ storage/falcon/Database.cpp
        Special check for ODS version 2.3 (it  can be in fact 2.4)
     @ storage/falcon/Database.h
        Increase ODS_MINOR_VERSION
     @ storage/falcon/Dbb.cpp
        New function to upgrade minor ODS version the fly
     @ storage/falcon/Dbb.h
        New function to upgrade minor ODS version the fly
     @ storage/falcon/Index.cpp
        Depending on ODS version, build multisegment key in either 2.3 or 2.4 format.

    modified:
      storage/falcon/Database.cpp
      storage/falcon/Database.h
      storage/falcon/Dbb.cpp
      storage/falcon/Dbb.h
      storage/falcon/Index.cpp
=== modified file 'storage/falcon/Database.cpp'
--- a/storage/falcon/Database.cpp	2009-04-01 18:51:04 +0000
+++ b/storage/falcon/Database.cpp	2009-04-02 06:26:04 +0000
@@ -795,7 +795,8 @@ void Database::openDatabase(const char *
 
 	Sync syncDDL(&syncSysDDL, "Database::openDatabase");
 	syncDDL.lock(Shared);
-	
+	checkODSVersion23();
+
 	PreparedStatement *statement = prepareStatement ("select tableid from tables");
 	ResultSet *resultSet = statement->executeQuery();
 
@@ -847,6 +848,43 @@ void Database::openDatabase(const char *
 		scheduler->start();
 }
 
+
+// Check if ODS version 2.3 is really 2.3 and not 2.4
+//
+// Background:
+// There was a subtle change from 2.3 to 2.4 in the way multisegment indexes are built.
+// And there are databases that 2.3 in header page, but with 2.4 indexes.
+// This function will fix minor version the header page and Dbb in such case
+//
+// For the check, we use a query that is known to return empty  resultSet if 
+// and only if ODS is <= 2.3 and engine > 2.3.
+void Database::checkODSVersion23()
+{
+	if (dbb->odsVersion == ODS_VERSION2 && dbb->odsMinorVersion == ODS_MINOR_VERSION3)
+		{
+
+		// For the next query, force index code to use 2.4 algorithm for multisegments
+		dbb->odsMinorVersion = ODS_MINOR_VERSION4;
+
+		const char checkVersion24Query[] = 
+			"select privilegeMask from system.privileges where holderType=3 and "
+			"holderSchema='' and holderName='MYSQL' and  objectType=0 and "
+			"objectSchema='FALCON' and objectName='TABLES'";
+		PreparedStatement *statement = prepareStatement(checkVersion24Query);
+		ResultSet *resultSet = statement->executeQuery();
+
+		if (resultSet->next())
+			// Got non-empty result -> have ODS 2.4
+			dbb->setODSMinorVersion(ODS_MINOR_VERSION4);
+		else
+			// Got empty result -> have ODS 2.3
+			dbb->odsMinorVersion = ODS_MINOR_VERSION3;
+
+		resultSet->close();
+		statement->close();
+		}
+}
+
 #ifndef STORAGE_ENGINE
 void Database::startSessionManager()
 {

=== modified file 'storage/falcon/Database.h'
--- a/storage/falcon/Database.h	2009-03-20 19:28:10 +0000
+++ b/storage/falcon/Database.h	2009-04-02 06:26:04 +0000
@@ -34,7 +34,8 @@
 #define ODS_MINOR_VERSION1	1		// Has serial log
 #define ODS_MINOR_VERSION2	2		// Has SequencePages external to the section tree
 #define ODS_MINOR_VERSION3	3		// Switch to variable length record numbers in index
-#define ODS_MINOR_VERSION	ODS_MINOR_VERSION3
+#define ODS_MINOR_VERSION4	4		// Accidentially fixed multisegment keys wrt padding
+#define ODS_MINOR_VERSION	ODS_MINOR_VERSION4
 
 #define COMBINED_VERSION(major,minor)	(major * 100 + minor)
 #define VERSION_CURRENT					COMBINED_VERSION(ODS_VERSION, ODS_MINOR_VERSION)					
@@ -182,6 +183,7 @@ public:
 	User*			findUser (const char *account);
 	User*			createUser (const char *account, const char *password, bool encrypted, Coterie *coterie);
 	int				getMaxKeyLength(void);
+	void			checkODSVersion23();
 
 #ifndef STORAGE_ENGINE
 	void		startSessionManager();

=== modified file 'storage/falcon/Dbb.cpp'
--- a/storage/falcon/Dbb.cpp	2009-03-27 13:43:10 +0000
+++ b/storage/falcon/Dbb.cpp	2009-04-02 06:26:04 +0000
@@ -551,6 +551,19 @@ Cache* Dbb::open(const char * fileName, 
 	return cache;
 }
 
+
+void Dbb::setODSMinorVersion(int minor)
+{
+	odsMinorVersion = minor;
+	Bdb *bdb = fetchPage (HEADER_PAGE, PAGE_header, Exclusive);
+	BDB_HISTORY(bdb);
+	bdb->mark(NO_TRANSACTION);
+	Hdr *headerPage = (Hdr*) bdb->buffer;
+	headerPage->odsMinorVersion = minor;
+	bdb->release(REL_HISTORY);
+}
+
+
 void Dbb::deleteIndex(int32 indexId, int indexVersion, TransId transId)
 {
 	if (serialLog)

=== modified file 'storage/falcon/Dbb.h'
--- a/storage/falcon/Dbb.h	2009-03-25 22:11:35 +0000
+++ b/storage/falcon/Dbb.h	2009-04-02 06:26:04 +0000
@@ -144,6 +144,7 @@ public:
 	void	setDebug();
 	void	deleteIndex (int32 indexId, int indexVersion, TransId transId);
 	Cache*	open (const char *fileName, int64 cacheSize, TransId transId);
+	void	setODSMinorVersion(int minor);
 	void	flush();
 	bool	addIndexEntry (int32 indexId, int indexVersion, IndexKey *key, int32 recordNumber, TransId transId);
 	int32	createIndex(TransId transId, int indexVersion);

=== modified file 'storage/falcon/Index.cpp'
--- a/storage/falcon/Index.cpp	2009-03-24 15:01:11 +0000
+++ b/storage/falcon/Index.cpp	2009-04-02 06:26:04 +0000
@@ -384,6 +384,10 @@ void Index::makeKey(int count, Value **v
 	int n;
 	UCHAR *key = indexKey->key;
 
+	bool ODSVersion23OrOlder = 
+		(COMBINED_VERSION(database->dbb->odsVersion, database->dbb->odsMinorVersion) <=
+		COMBINED_VERSION(2,3));
+
 	for (n = 0; (n < count) && values[n]; ++n)
 		{
 		Field *field = fields[n];
@@ -415,7 +419,14 @@ void Index::makeKey(int count, Value **v
 
 		if (n < numberFields - 1)
 			{
-			char padByte = PAD_BYTE(field);
+			char padByte;
+
+			if (ODSVersion23OrOlder)
+				//PAD_BYTE is incorrect in these versions
+				//(has type of the next field)
+				padByte = PAD_BYTE(fields[n+1]);
+			else
+				padByte = PAD_BYTE(field);
 
 			while (p % RUN != 0)
 				key[p++] = padByte;


Attachment: [text/bzr-bundle] bzr/vvaintroub@mysql.com-20090402062604-3bsaafyvvvbtw4uj.bundle
Thread
bzr commit into mysql-6.0-falcon-team branch (vvaintroub:3093)Bug#43562Vladislav Vaintroub2 Apr