List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:October 30 2008 2:51pm
Subject:bzr commit into mysql-6.0-falcon-team branch (vvaintroub:2889) Bug#38186
View as plain text  
#At file:///G:/bzr/mysql-6.0-falcon-team/

 2889 Vladislav Vaintroub	2008-10-30
       Fixed a long-standing problem that tablespace file was present even after "drop
tablespace" successfully completed. This problem was  previously worked around in
Bug#38186.
modified:
  storage/falcon/IO.cpp
  storage/falcon/StorageHandler.cpp
  storage/falcon/TableSpaceManager.cpp
  storage/falcon/TableSpaceManager.h

=== modified file 'storage/falcon/IO.cpp'
--- a/storage/falcon/IO.cpp	2008-09-11 10:56:00 +0000
+++ b/storage/falcon/IO.cpp	2008-10-30 13:51:27 +0000
@@ -117,6 +117,19 @@ static char baseDir[PATH_MAX+1]={0};
 bool deleteFilesOnExit = false;
 bool inCreateDatabase = false;
 
+#ifdef _WIN32
+static int winUnlink(const char *file);
+static int winOpen(const char *filename, int flags,...);
+#endif
+
+#ifdef _WIN32
+#define POSIX_OPEN_FILE winOpen
+#define POSIX_UNLINK_FILE winUnlink
+#else
+#define POSIX_OPEN_FILE   ::open
+#define POSIX_UNLINK_FILE ::unlink
+#endif
+
 #ifdef _DEBUG
 #undef THIS_FILE
 static const char THIS_FILE[]=__FILE__;
@@ -186,7 +199,7 @@ bool IO::openFile(const char * name, boo
 	ASSERT(!inCreateDatabase);
 
 	fileName = getPath(name);
-	fileId = ::open (fileName, (readOnly) ? (O_RDONLY | O_BINARY) : (O_RDWR | O_BINARY));
+	fileId = POSIX_OPEN_FILE(fileName, (readOnly) ? (O_RDONLY | O_BINARY) : (O_RDWR |
O_BINARY));
 
 	if (fileId < 0)
 		{
@@ -241,7 +254,7 @@ bool IO::createFile(const char *name)
 	Log::debug("IO::createFile: creating file \"%s\"\n", name);
 
 	fileName = getPath(name);
-	fileId = ::open (fileName.getString(),O_CREAT | O_RDWR | O_RANDOM | O_EXCL | O_BINARY,
+	fileId = POSIX_OPEN_FILE (fileName.getString(),O_CREAT | O_RDWR | O_RANDOM | O_EXCL |
O_BINARY,
 						S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP);
 
 
@@ -557,6 +570,7 @@ void IO::writeHeader(Hdr *header)
 void IO::deleteFile()
 {
 	deleteFile(fileName);
+	fileName="";
 }
 
 int IO::pread(int64 offset, int length, UCHAR* buffer)
@@ -675,10 +689,132 @@ void IO::sync(void)
 		traceOperation(TRACE_SYNC_END);
 }
 
+#ifdef _WIN32
+#define FALCON_DELETED_FILE "fdf"
+
+/*
+	The only safe way to delete file on Windows without invalidating open file 
+	handles is that:
+	- rename file to be deleted to a unique temporary name.
+	- open file it with FILE_FLAG_DELETE_ON_CLOSE
+	- close the file handle
+	Temp file will disappear as soon as last handle on it is closed.
+	This works only if files are opened with FILE_SHARE_DELETE flag.
+*/
+
+static int winUnlink(const char *file)
+{
+	DWORD attributes = GetFileAttributes(file);
+
+	// Bail out, if file does not exist.
+	if (attributes == INVALID_FILE_ATTRIBUTES)
+		return -1;
+
+	// If file is a symbolic link, just delete the link, but not the link target
+	if (attributes & FILE_ATTRIBUTE_REPARSE_POINT)
+		{
+		if(DeleteFile(file))
+			return 0;
+		return -1;
+		}
+
+	// Rename the file to unique name, then open with FILE_FLAG_DELETE_ON_CLOSE
+	// and close.
+	char  tmpDir[MAX_PATH];
+	strncpy(tmpDir, file, sizeof(tmpDir)-1);
+	char *p = strrchr(tmpDir ,SEPARATOR);
+	if (p)
+		*p = 0;
+	else
+		strcpy(tmpDir,".");
+
+	char  tmpFile[MAX_PATH];
+	if (GetTempFileName(tmpDir, FALCON_DELETED_FILE, 0, tmpFile))
+		{
+		if (MoveFileEx(file, tmpFile, MOVEFILE_REPLACE_EXISTING))
+			{
+			HANDLE hFile = CreateFile(tmpFile, 0,
+				FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+				NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+
+			if (hFile != INVALID_HANDLE_VALUE)
+				{
+				CloseHandle(hFile);
+				return 0;
+				}
+			}
+		else
+			DeleteFile(tmpFile);
+		}
+	
+	// Something went wrong. Try DeleteFile(), even if it can invalidate
+	// open file handles.
+	if(DeleteFile(file))
+		return 0;
+
+	return -1;
+}
+
+/* 
+	A wrapper for Posix open(). The reason it is there is the FILE_SHARE_DELETE 
+	flag used in CreateFile, which allows for  posixly-correct unlink
+	(that works with open files)
+*/
+static int winOpen(const char *filename, int flags,...)
+{
+	DWORD access;
+	if (flags & O_WRONLY)
+		access = GENERIC_WRITE;
+	else if (flags & O_RDWR)
+		access = GENERIC_READ|GENERIC_WRITE;
+	else
+		access = GENERIC_READ;
+
+	DWORD disposition;
+	if (flags & O_CREAT)
+		disposition = CREATE_NEW;
+	else
+		disposition = OPEN_EXISTING;
+
+	DWORD attributes;
+	if (flags & O_RANDOM)
+		attributes = FILE_FLAG_RANDOM_ACCESS;
+	else
+		attributes = FILE_ATTRIBUTE_NORMAL;
+
+	HANDLE hFile = CreateFile(filename, access, 
+		FILE_SHARE_DELETE, NULL, disposition, attributes, NULL);
+	
+	if (hFile == INVALID_HANDLE_VALUE)
+		{
+		switch(GetLastError())
+			{
+			case ERROR_ACCESS_DENIED:
+				errno = EACCES;
+				break;
+			case ERROR_FILE_NOT_FOUND:
+			case ERROR_PATH_NOT_FOUND:
+				errno = ENOENT;
+				break;
+			default:
+				errno = EINVAL;
+				break;
+			}
+		return -1;
+		}
+	return _open_osfhandle((intptr_t)hFile, 
+		flags & (_O_APPEND|_O_RDONLY|_O_TEXT));
+}
+
+#endif
+
 void IO::deleteFile(const char* fileName)
 {
-	JString path = getPath(fileName);
-	unlink(path.getString());
+	if(fileName && *fileName)
+		{
+		JString path = getPath(fileName);
+		POSIX_UNLINK_FILE(path.getString());
+		}
 }
 
 void IO::tracePage(Bdb* bdb)
@@ -810,3 +946,4 @@ uint16 IO::computeChecksum(Page *page, s
 	return (uint16) sum;
 
 }
+

=== modified file 'storage/falcon/StorageHandler.cpp'
--- a/storage/falcon/StorageHandler.cpp	2008-10-01 03:13:44 +0000
+++ b/storage/falcon/StorageHandler.cpp	2008-10-30 13:51:27 +0000
@@ -508,10 +508,6 @@ int StorageHandler::createTablespace(con
 	TableSpaceManager *tableSpaceManager =
 		dictionaryConnection->database->tableSpaceManager;
 
-	if (!tableSpaceManager->waitForPendingDrop(filename, 10))
-		// file still exists after waiting for 10 seconds
-		return  StorageErrorTableSpaceDataFileExist;
-
 	try
 		{
 		JString cmd = genCreateTableSpace(tableSpaceName, filename, comment);

=== modified file 'storage/falcon/TableSpaceManager.cpp'
--- a/storage/falcon/TableSpaceManager.cpp	2008-09-22 09:24:39 +0000
+++ b/storage/falcon/TableSpaceManager.cpp	2008-10-30 13:51:27 +0000
@@ -58,7 +58,6 @@ TableSpaceManager::TableSpaceManager(Dat
 	memset(nameHash, 0, sizeof(nameHash));
 	memset(idHash, 0, sizeof(nameHash));
 	tableSpaces = NULL;
-	pendingDrops = 0;
 	syncObject.setName("TableSpaceManager::syncObject");
 }
 
@@ -209,12 +208,7 @@ void TableSpaceManager::bootstrap(int se
 		p = EncodedDataStream::decode(p, &id, true);
 		p = EncodedDataStream::decode(p, &fileName, true);
 		p = EncodedDataStream::decode(p, &type, true);
-		/***
-		p = EncodedDataStream::decode(p, &comment, true);
 
-		TableSpaceInit tsInit;
-		tsInit.comment		= comment.getString();
-		***/
 		
 		TableSpace *tableSpace = new TableSpace(database, name.getString(), id.getInt(),
fileName.getString(), type.getInt(), NULL);
 		Log::debug("New table space %s, id %d, type %d, filename %s\n", (const char*)
tableSpace->name, tableSpace->tableSpaceId, tableSpace->type, (const char*)
tableSpace->filename);
@@ -252,7 +246,6 @@ TableSpace* TableSpaceManager::getTableS
 		throw SQLError(COMPILE_ERROR, "can't find table space %d", id);
 
 	if (!tableSpace->active)
-		//throw SQLError(RUNTIME_ERROR, "table space \"%s\" is not active", (const char*)
tableSpace->name);
 		tableSpace->open();
 
 	return tableSpace;
@@ -298,13 +291,14 @@ void TableSpaceManager::dropTableSpace(T
 			break;
 			}
 			
-	pendingDrops++;
 	syncObj.unlock();
+	tableSpace->active = false;
+	JString filename = tableSpace->dbb->fileName;
 
 	database->serialLog->logControl->dropTableSpace.append(tableSpace,
transaction);
 	database->commitSystemTransaction();
+	IO::deleteFile(filename);
 
-	tableSpace->active = false;
 }
 
 void TableSpaceManager::reportStatistics(void)
@@ -370,12 +364,10 @@ void TableSpaceManager::expungeTableSpac
 			}
 
 	sync.unlock();
-	tableSpace->dropTableSpace();
+	//File already deleted, just close the file descriptor
+	tableSpace->close();
 	delete tableSpace;
 
-	sync.lock(Exclusive);
-	if(pendingDrops >0)
-		pendingDrops--;
 }
 
 void TableSpaceManager::reportWrites(void)
@@ -563,28 +555,5 @@ void TableSpaceManager::getTableSpaceFil
 		infoTable->setNull(37);			// EXTRA
 		infoTable->putRecord();
 		}
-}
-
-
-// Wait for specified amount of time for a  file to be deleted.
-// Don't wait if pendingDrops count is 0.
-//
-// The function returns true, if wait was successfull, i.e file does not exist
-//(anymore)
-bool TableSpaceManager::waitForPendingDrop(const char  *filename, int seconds)
-{
-	bool fileExists;
-
-	do
-		{
-		fileExists = IO::doesFileExist(filename);
-		if (fileExists && pendingDrops > 0 && seconds-- > 0)
-			Thread::getThread("TransactionManager::waitForPendingDrop")->sleep(1000);
-		else
-			break;
-		}
-	while(true);
-
-	return !fileExists;
 }
 

=== modified file 'storage/falcon/TableSpaceManager.h'
--- a/storage/falcon/TableSpaceManager.h	2008-09-22 09:24:39 +0000
+++ b/storage/falcon/TableSpaceManager.h	2008-10-30 13:51:27 +0000
@@ -63,7 +63,7 @@ public:
 	void			reportWrites(void);
 	void			redoCreateTableSpace(int id, int nameLength, const char* name, int
fileNameLength, const char* fileName, int type, TableSpaceInit* tsInit);
 	void			initialize(void);
-	bool			waitForPendingDrop(const char *filename, int seconds);
+
 
 	Database	*database;
 	TableSpace	*tableSpaces;

Thread
bzr commit into mysql-6.0-falcon-team branch (vvaintroub:2889) Bug#38186Vladislav Vaintroub30 Oct