diff --git a/ChangeLog b/ChangeLog index b0b7fb3..0c6d075 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-11-12 Richard Frith-Macdonald + + * SQLClient.h: + * SQLClient.m: + Add support for tracking the number of consecutive connection failures + and imposing a delay between connection attempts. + 2008-07-19 Nicola Pero * configure.ac: Documented the --with-additional-include=, diff --git a/SQLClient.h b/SQLClient.h index 5793a30..549c571 100644 --- a/SQLClient.h +++ b/SQLClient.h @@ -374,12 +374,15 @@ extern unsigned SQLClientTimeTick(); * Timestamp of last operation.
* Maintained by -simpleExecute: -simpleQuery:recordType:listType: * and -cache:simpleQuery:recordType:listType: + * Also set for a failed connection attempt, but not reported by the + * -lastOperation method in that case. */ NSTimeInterval _lastOperation; NSTimeInterval _duration; unsigned int _debugging; /** The current debugging level */ GSCache *_cache; /** The cache for query results */ NSThread *_cacheThread; /** Thread for cache queries */ + unsigned _connectFails; /** The count of connection failures */ } /** @@ -529,7 +532,14 @@ extern unsigned SQLClientTimeTick(); * If the connected instance variable is NO, this method * calls -backendConnect to ensure that there is a connection to the * database server established. Returns the result.
- * Performs any necessary locking for thread safety. + * Performs any necessary locking for thread safety.
+ * This method also counts the number of consecutive failed connection + * attempts. A delay is enforced between each connection attempt, with + * the length of the delay growing with each failure. This ensures + * that applications which fail to deal with connection failures, and + * just keep trying to reconnect, will not overload the system/server.
+ * The maximum delay is 30 seconds, so when the database server is restarted, + * the application can reconnect reasonably quickly. */ - (BOOL) connect; @@ -712,6 +722,11 @@ extern unsigned SQLClientTimeTick(); */ - (NSString*) quotef: (NSString*)fmt, ...; +/** + * Convert a big (64 bit) integer to a string suitable for use in an SQL query. + */ +- (NSString*) quoteBigInteger: (int64_t)i; + /** * Convert a 'C' string to a string suitable for use in an SQL query * by using -quoteString: to convert it to a literal string format.
diff --git a/SQLClient.m b/SQLClient.m index 4157fb3..f242362 100644 --- a/SQLClient.m +++ b/SQLClient.m @@ -1141,13 +1141,33 @@ static unsigned int maxConnections = 8; [lock lock]; if (connected == NO) { + if (_connectFails > 1) + { + NSTimeInterval delay; + NSTimeInterval elapsed; + + /* If we have repeated connection failures, we enforce a + * delay fo up to 30 seconds between connection attempts + * to avoid overloading the system with too frequent + * connection attempts. + */ + delay = (_connectFails < 30) ? _connectFails : 30; + elapsed = GSTickerTimeNow() - _lastOperation; + if (elapsed < delay) + { + [NSThread sleepForTimeInterval: delay - elapsed]; + } + } NS_DURING { [self backendConnect]; + _connectFails = 0; } NS_HANDLER { [lock unlock]; + _lastOperation = GSTickerTimeNow(); + _connectFails++; [localException raise]; } NS_ENDHANDLER @@ -1347,7 +1367,7 @@ static unsigned int maxConnections = 8; - (NSDate*) lastOperation { - if (_lastOperation > 0.0) + if (_lastOperation > 0.0 && _connectFails == 0) { return [NSDate dateWithTimeIntervalSinceReferenceDate: _lastOperation]; } @@ -1494,6 +1514,11 @@ static unsigned int maxConnections = 8; return quoted; } +- (NSString*) quoteBigInteger: (int64_t)i +{ + return [NSString stringWithFormat: @"%lld", i]; +} + - (NSString*) quoteCString: (const char *)s { NSString *str;