List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:June 8 2008 10:13pm
Subject:bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685)
Bug#36396
View as plain text  
#At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-falcon/

 2685 Vladislav Vaintroub	2008-06-09
      Bug#36396 - Assertion in IO::pread (on closed tablespace file)
      The problem was that gopher  processing "drop tablespace"
      was faster then the gopher procesing preceeding "drop table".
      As a result, tablespace file was closed and removed, while
      "DROP TABLE" still tried to access it.
      
      Solution is to synchronize gopher threads in this case, i.e
      all while transaction containing DROP TABLESPACE is  being
      processed, all other gophers wait until it completes.
      Additionally, a race condition during  CREATE TABLESPACE has
      been observed and fixed in this patch. It can happen that
      DROP TABLESPACE was completed, but the file is still there
      because commit record was not yet processed by a gopher thread.
      This resulted into infrequent errors on CREATE with "file already
      exists" message.
      
      The solution to this problem is to track number of pending
      DROP TABLESPACE commands.During CREATE TABLESPACE, if the file
      exists and there are pending DROPs, wait for a short time (10 sec)
      in a loop  for file to be deleted.
      
      No testcase is provided with this patch. Had no luck writing
      mysql-test-run script reproducing these race conditions.
modified:
  storage/falcon/Gopher.cpp
  storage/falcon/SRLDropTableSpace.cpp
  storage/falcon/SerialLog.h
  storage/falcon/SerialLogTransaction.cpp
  storage/falcon/SerialLogTransaction.h
  storage/falcon/TableSpaceManager.cpp
  storage/falcon/TableSpaceManager.h

=== modified file 'storage/falcon/Gopher.cpp'
--- a/storage/falcon/Gopher.cpp	2008-03-25 03:55:03 +0000
+++ b/storage/falcon/Gopher.cpp	2008-06-08 22:12:35 +0000
@@ -64,11 +64,22 @@ void Gopher::gopherThread(void)
 		
 		SerialLogTransaction *transaction = log->pending.first;
 		log->pending.remove(transaction);
+
+		
+		Sync serializeGophers(&log->syncSerializeGophers, "Gopher::gopherThread(4)");
+
+		if (transaction->allowConcurrentGophers)
+			serializeGophers.lock(Shared);
+		else
+			serializeGophers.lock(Exclusive);
+
 		sync.unlock();
 
 		transaction->doAction();
 
 		sync.lock(Exclusive);
+		serializeGophers.unlock();
+
 		log->inactions.append(transaction);
 		
 		if (log->pending.count > log->maxTransactions && !log->blocking)

=== modified file 'storage/falcon/SRLDropTableSpace.cpp'
--- a/storage/falcon/SRLDropTableSpace.cpp	2007-11-14 23:24:47 +0000
+++ b/storage/falcon/SRLDropTableSpace.cpp	2008-06-08 22:12:35 +0000
@@ -24,6 +24,7 @@
 #include "SRLVersion.h"
 #include "SerialLogControl.h"
 #include "Transaction.h"
+#include "SerialLogTransaction.h"
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
@@ -42,7 +43,12 @@ SRLDropTableSpace::~SRLDropTableSpace()
 void SRLDropTableSpace::append(TableSpace *tableSpace, Transaction *transaction)
 {
 	START_RECORD(srlDropTableSpace, "SRLDropTableSpace::append");
-	log->getTransaction(transaction->transactionId);
+
+	SerialLogTransaction* serialLogTransaction 
+		= log->getTransaction(transaction->transactionId);
+
+	serialLogTransaction->allowConcurrentGophers = false;
+
 	putInt(tableSpace->tableSpaceId);
 	putInt(transaction->transactionId);
 }

=== modified file 'storage/falcon/SerialLog.h'
--- a/storage/falcon/SerialLog.h	2008-03-11 16:15:47 +0000
+++ b/storage/falcon/SerialLog.h	2008-06-08 22:12:35 +0000
@@ -188,6 +188,7 @@ public:
 	SyncObject			syncSections;
 	SyncObject			syncIndexes;
 	SyncObject			syncGopher;
+	SyncObject			syncSerializeGophers;
 	SyncObject			syncUpdateStall;
 	Stack				buffers;
 	UCHAR				*bufferSpace;

=== modified file 'storage/falcon/SerialLogTransaction.cpp'
--- a/storage/falcon/SerialLogTransaction.cpp	2008-02-14 21:45:27 +0000
+++ b/storage/falcon/SerialLogTransaction.cpp	2008-06-08 22:12:35 +0000
@@ -46,6 +46,7 @@ SerialLogTransaction::SerialLogTransacti
 	window = NULL;
 	finished = false;
 	ordered = false;
+	allowConcurrentGophers = true;
 	transaction = NULL;
 	rolledBackSavepoints = NULL;
 	blockNumber = maxBlockNumber = minBlockNumber = physicalBlockNumber = 0;

=== modified file 'storage/falcon/SerialLogTransaction.h'
--- a/storage/falcon/SerialLogTransaction.h	2008-03-11 16:15:47 +0000
+++ b/storage/falcon/SerialLogTransaction.h	2008-06-08 22:12:35 +0000
@@ -71,6 +71,7 @@ public:
 	int						xidLength;
 	UCHAR					*xid;
 	bool					finished;
+	bool					allowConcurrentGophers;
 
 	SerialLog				*log;
 	SerialLogTransaction	*next;

=== modified file 'storage/falcon/TableSpaceManager.cpp'
--- a/storage/falcon/TableSpaceManager.cpp	2008-05-06 23:37:54 +0000
+++ b/storage/falcon/TableSpaceManager.cpp	2008-06-08 22:12:35 +0000
@@ -41,6 +41,7 @@
 #include "SRLDropTableSpace.h"
 #include "Log.h"
 #include "InfoTable.h"
+#include "Thread.h"
 
 #ifdef _DEBUG
 #undef THIS_FILE
@@ -57,6 +58,7 @@ TableSpaceManager::TableSpaceManager(Dat
 	memset(nameHash, 0, sizeof(nameHash));
 	memset(idHash, 0, sizeof(nameHash));
 	tableSpaces = NULL;
+	pendingDrops = 0;
 }
 
 TableSpaceManager::~TableSpaceManager()
@@ -168,10 +170,32 @@ TableSpace* TableSpaceManager::createTab
 	
 	TableSpace *tableSpace = new TableSpace(database, name, id, fileName, type, tsInit);
 	
-	if (!repository && tableSpace->dbb->doesFileExist(fileName))
+	if (!repository)
 		{
-		delete tableSpace;
-		throw SQLError(TABLESPACE_DATAFILE_EXIST_ERROR, "table space file name \"%s\" already exists\n", fileName);
+		bool fileExists;
+
+		// Check if table space file already exists.
+		// Take into account, that tablespace might have been already  dropped
+		// by another transaction, yet file can still be present on the disk,
+		// if log record is not yet fully committed by the gopher thread).
+		// So we'll wait for a few seconds if there are pending drops and 
+		// tablespace file exists.
+
+		for (int i=0; i < 10; i++)
+			{
+			fileExists = tableSpace->dbb->doesFileExist(fileName);
+
+			if (fileExists && pendingDrops > 0)
+				Thread::getThread("TableSpaceManager::createTableSpace")->sleep(1000);
+			else
+				break;
+			}
+
+		if (fileExists)
+			{
+			delete tableSpace;
+			throw SQLError(TABLESPACE_DATAFILE_EXIST_ERROR, "table space file name \"%s\" already exists\n", fileName);
+			}
 		}
 		
 	try
@@ -302,6 +326,7 @@ void TableSpaceManager::dropTableSpace(T
 	statement->executeUpdate();
 	Transaction *transaction = database->getSystemTransaction();
 	transaction->hasUpdates = true;
+	pendingDrops++;
 	database->serialLog->logControl->dropTableSpace.append(tableSpace, transaction);
 
 	syncDDL.unlock();
@@ -386,6 +411,9 @@ void TableSpaceManager::expungeTableSpac
 	sync.unlock();
 	tableSpace->dropTableSpace();
 	delete tableSpace;
+
+	sync.lock(Exclusive);
+	if(pendingDrops >0) pendingDrops--;
 }
 
 void TableSpaceManager::reportWrites(void)

=== modified file 'storage/falcon/TableSpaceManager.h'
--- a/storage/falcon/TableSpaceManager.h	2008-04-05 22:09:17 +0000
+++ b/storage/falcon/TableSpaceManager.h	2008-06-08 22:12:35 +0000
@@ -69,6 +69,7 @@ public:
 	TableSpace	*idHash[TS_HASH_SIZE];
 	SyncObject	syncObject;
 	void postRecovery(void);
+	int pendingDrops;
 };
 
 #endif // !defined(AFX_TABLESPACEMANAGER_H__BD1D39F6_2201_4136_899C_7CB106E99B8C__INCLUDED_)

Thread
bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685)Bug#36396Vladislav Vaintroub9 Jun
  • RE: bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685) Bug#36396Kevin Lewis9 Jun
    • RE: bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685) Bug#36396Vladislav Vaintroub9 Jun
      • RE: bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685) Bug#36396Kevin Lewis10 Jun
        • RE: bzr commit into mysql-6.0-falcon:mysql-6.0-falcon branch (vvaintroub:2685) Bug#36396Vladislav Vaintroub10 Jun