From 808a76c28f2346befc38a7b6e744987b2bedace1 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sat, 28 Mar 2009 01:48:37 +0000 Subject: - Add a preference (currently with no UI) for connection timeout - Improve connection error messages slightly. - Avoid reading prefs for every keepalive check - now sets connection timeout and keepalive interval on connection setup - Fix and extend connection checks to avoid showing extra errors when the connection has been closed --- Source/CMMCPConnection.h | 8 ++----- Source/CMMCPConnection.m | 32 +++++++--------------------- Source/MainController.m | 1 + Source/SPTableData.m | 10 +++++---- Source/TableDocument.m | 55 ++++++++++++++++++++++++++++++++---------------- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/Source/CMMCPConnection.h b/Source/CMMCPConnection.h index b26319ee..70b460f1 100644 --- a/Source/CMMCPConnection.h +++ b/Source/CMMCPConnection.h @@ -26,11 +26,6 @@ #import #import "CMMCPResult.h" -// Set the connection timeout to enforce for all connections - used for the initial connection -// timeout and ping timeouts, but not for long queries/reads/writes. -// Probably worth moving this to a preference at some point. -#define SP_CONNECTION_TIMEOUT 10 - @interface NSObject (CMMCPConnectionDelegate) - (void)willQueryString:(NSString *)query; @@ -50,6 +45,8 @@ int connectionPort; NSString *connectionSocket; float lastQueryExecutionTime; + int connectionTimeout; + float keepAliveInterval; NSTimer *keepAliveTimer; NSDate *lastKeepAliveSuccess; @@ -73,7 +70,6 @@ - (void) setDelegate:(id)object; - (NSTimeZone *) timeZone; - (BOOL) pingConnection; -- (double) keepAliveInterval; - (void) startKeepAliveTimerResettingState:(BOOL)resetState; - (void) stopKeepAliveTimer; - (void) keepAlive:(NSTimer *)theTimer; diff --git a/Source/CMMCPConnection.m b/Source/CMMCPConnection.m index 64315ff6..abb61d82 100644 --- a/Source/CMMCPConnection.m +++ b/Source/CMMCPConnection.m @@ -67,6 +67,10 @@ static void forcePingTimeout(int signalNumber); connectionPort = 0; connectionSocket = nil; keepAliveTimer = nil; + connectionTimeout = [[[NSUserDefaults standardUserDefaults] objectForKey:@"connectionTimeout"] intValue]; + if (!connectionTimeout) connectionTimeout = 10; + keepAliveInterval = [[[NSUserDefaults standardUserDefaults] objectForKey:@"keepAliveInterval"] doubleValue]; + if (!keepAliveInterval) keepAliveInterval = 0; lastKeepAliveSuccess = nil; lastQueryExecutionTime = 0; if (![NSBundle loadNibNamed:@"ConnectionErrorDialog" owner:self]) { @@ -93,7 +97,6 @@ static void forcePingTimeout(int signalNumber); if (socket) connectionSocket = [[NSString alloc] initWithString:socket]; if (mConnection != NULL) { - unsigned int connectionTimeout = SP_CONNECTION_TIMEOUT; mysql_options(mConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout); } @@ -158,7 +161,6 @@ static void forcePingTimeout(int signalNumber); if (mConnection != NULL) { // Set a connection timeout for the new connection - unsigned int connectionTimeout = SP_CONNECTION_TIMEOUT; mysql_options(mConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout); // Attempt to reestablish the connection - using own method so everything gets set up as standard. @@ -542,7 +544,7 @@ static void forcePingTimeout(int signalNumber); sigemptyset(&timeoutAction.sa_mask); timeoutAction.sa_flags = 0; sigaction(SIGALRM, &timeoutAction, NULL); - alarm(SP_CONNECTION_TIMEOUT+1); + alarm(connectionTimeout+1); // Set up a "restore point", returning 0; if longjmp is used later with this reference, execution // jumps back to this point and returns a nonzero value, so this function evaluates to false when initially @@ -587,28 +589,11 @@ static void forcePingTimeout(int signalNumber) longjmp(pingTimeoutJumpLocation, 1); } - -/* - * Returns the keepalive interval, or 0 if keepalive should be disabled. - * Sequel Pro draws this from the preferences with a default of 60 secs. - */ -- (double) keepAliveInterval -{ - double interval; - - interval = [[[NSUserDefaults standardUserDefaults] objectForKey:@"keepAliveInterval"] doubleValue]; - if (!interval) interval = 0; - - return interval; -} - /* * Restarts a keepalive to fire in the future. */ - (void) startKeepAliveTimerResettingState:(BOOL)resetState { - double interval; - if (keepAliveTimer) [self stopKeepAliveTimer]; if (!mConnected) return; @@ -617,10 +602,9 @@ static void forcePingTimeout(int signalNumber) lastKeepAliveSuccess = nil; } - interval = [self keepAliveInterval]; - if (interval) { + if (keepAliveInterval) { keepAliveTimer = [NSTimer - scheduledTimerWithTimeInterval:interval + scheduledTimerWithTimeInterval:keepAliveInterval target:self selector:@selector(keepAlive:) userInfo:nil @@ -652,7 +636,7 @@ static void forcePingTimeout(int signalNumber) // cut but mysql doesn't pick up on the fact - see comment for pingConnection above. The same // forced-timeout approach cannot be used here on a background thread. // When the connection is disconnected in code, these 5 "hanging" threads are automatically cleaned. - if (lastKeepAliveSuccess && [lastKeepAliveSuccess timeIntervalSinceNow] < -5 * [self keepAliveInterval]) return; + if (lastKeepAliveSuccess && [lastKeepAliveSuccess timeIntervalSinceNow] < -5 * keepAliveInterval) return; [NSThread detachNewThreadSelector:@selector(threadedKeepAlive) toTarget:self withObject:nil]; [self startKeepAliveTimerResettingState:NO]; diff --git a/Source/MainController.m b/Source/MainController.m index 8c76014a..257d43c3 100644 --- a/Source/MainController.m +++ b/Source/MainController.m @@ -668,6 +668,7 @@ checks for updates and opens download page in default browser [NSNumber numberWithBool:YES], @"fetchRowCount", [NSNumber numberWithBool:YES], @"limitRows", [NSNumber numberWithInt:1000], @"limitRowsValue", + [NSNumber numberWithInt:10], @"connectionTimeout", [NSNumber numberWithInt:60], @"keepAliveInterval", [NSNumber numberWithInt:0], @"lastUsedVersion", nil]]; diff --git a/Source/SPTableData.m b/Source/SPTableData.m index 1b4893ae..bc4820eb 100644 --- a/Source/SPTableData.m +++ b/Source/SPTableData.m @@ -266,7 +266,7 @@ // Check for any errors, but only display them if a connection still exists if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - if (![mySQLConnection isConnected]) { + if ([mySQLConnection isConnected]) { NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving table information:\n\n%@", [mySQLConnection getLastErrorMessage]], @"OK", nil, nil); } return nil; @@ -439,7 +439,7 @@ // Check for any errors, but only display them if a connection still exists if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - if (![mySQLConnection isConnected]) { + if ([mySQLConnection isConnected]) { NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving view information:\n\n%@", [mySQLConnection getLastErrorMessage]], @"OK", nil, nil); } return nil; @@ -519,9 +519,11 @@ // Run the status query and retrieve as a dictionary. CMMCPResult *tableStatusResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW TABLE STATUS LIKE '%@'", [tableListInstance tableName]]]; - // Check for any errors + // Check for any errors, only displaying them if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving table status:\n\n%@", [mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving table status:\n\n%@", [mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return FALSE; } diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 012b30dc..142fa0c8 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -239,12 +239,12 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa //can't connect to host NSBeginAlertSheet(NSLocalizedString(@"Connection failed!", @"connection failed"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, @selector(sheetDidEnd:returnCode:contextInfo:), @"connect", - [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to host %@.\nBe sure that the address is correct and that you have the necessary privileges.\nMySQL said: %@", @"message of panel when connection to host failed"), [hostField stringValue], [mySQLConnection getLastErrorMessage]]); + [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to host %@, or the request timed out.\n\nBe sure that the address is correct and that you have the necessary privileges, or try increasing the connection timeout (currently %i seconds).\n\nMySQL said: %@", @"message of panel when connection to host failed"), [hostField stringValue], [[prefs objectForKey:@"connectionTimeout"] intValue], [mySQLConnection getLastErrorMessage]]); } else if (code == 3) { //can't connect to db NSBeginAlertSheet(NSLocalizedString(@"Connection failed!", @"connection failed"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, @selector(sheetDidEnd:returnCode:contextInfo:), @"connect", - [NSString stringWithFormat:NSLocalizedString(@"Unable to connect to database %@.\nBe sure that the database exists and that you have the necessary privileges.\nMySQL said: %@", @"message of panel when connection to db failed"), [databaseField stringValue], [mySQLConnection getLastErrorMessage]]); + [NSString stringWithFormat:NSLocalizedString(@"Connected to host, but unable to connect to database %@.\n\nBe sure that the database exists and that you have the necessary privileges.\n\nMySQL said: %@", @"message of panel when connection to db failed"), [databaseField stringValue], [mySQLConnection getLastErrorMessage]]); } else if (code == 4) { //no host is given NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, @@ -801,9 +801,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa NSString *query = [NSString stringWithFormat:@"SHOW CREATE TABLE %@", [[self table] backtickQuotedString]]; CMMCPResult *theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while creating table syntax.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while creating table syntax.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return; } @@ -822,9 +824,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa NSString *query = [NSString stringWithFormat:@"SHOW CREATE TABLE %@", [[self table] backtickQuotedString]]; CMMCPResult *theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while creating table syntax.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while creating table syntax.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return; } @@ -854,9 +858,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"CHECK TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while checking table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while checking table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return; } @@ -875,9 +881,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"ANALYZE TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while analyzing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while analyzing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return; } @@ -896,9 +904,12 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"OPTIMIZE TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while optimizing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while optimizing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } + return; } // Process result @@ -916,9 +927,12 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"REPAIR TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while repairing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while repairing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } + return; } // Process result @@ -935,9 +949,11 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"FLUSH TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while flushing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while flushing table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } return; } @@ -955,9 +971,12 @@ NSString *TableDocumentFavoritesControllerFavoritesDidChange = @"TableDocumentFa query = [NSString stringWithFormat:@"CHECKSUM TABLE %@", [[self table] backtickQuotedString]]; theResult = [mySQLConnection queryString:query]; - // Check for errors + // Check for errors, only displaying if the connection hasn't been terminated if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while performming checksum on table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if ([mySQLConnection isConnected]) { + NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while performming checksum on table.\n\n: %@",[mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + } + return; } // Process result -- cgit v1.2.3