Monotone-Parent: 90a9a165bd97c227034ffe99dc1bcd6de1cd3e2b

Monotone-Revision: 4198e2465d45fe776a415bd2dea2e4f56eed4826

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2009-11-30T16:31:19
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2009-11-30 16:31:19 +00:00
parent 76c81ab71a
commit 62856908bb
4 changed files with 78 additions and 65 deletions

View File

@ -1,5 +1,10 @@
2009-11-30 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* GCSChannelManager.m (-databaseKeyForURL): removed obsolete
method, replaced with the new one below.
(-acquireOpenChannelForURL:): we keep the last failure timestamp
into account and prevent further attempts before 5 seconds.
* NSURL+GCS.m (-gcsURLId): new method that returns a unique
identifier for database connections.

View File

@ -37,6 +37,8 @@
{
NSMutableDictionary *urlToAdaptor;
NSMutableDictionary *lastFailures;
NSMutableArray *availableChannels;
NSMutableArray *busyChannels;
NSTimer *gcTimer;

View File

@ -107,6 +107,7 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
if ((self = [super init]))
{
urlToAdaptor = [[NSMutableDictionary alloc] initWithCapacity: 4];
lastFailures = [[NSMutableDictionary alloc] initWithCapacity: 4];
availableChannels = [[NSMutableArray alloc] initWithCapacity: 16];
busyChannels = [[NSMutableArray alloc] initWithCapacity: 16];
@ -126,26 +127,11 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
[busyChannels release];
[availableChannels release];
[lastFailures release];
[urlToAdaptor release];
[super dealloc];
}
/* DB key */
- (NSString *) databaseKeyForURL: (NSURL *) _url
{
/*
We need to build a proper key that omits passwords and URL path components
which are not required.
*/
NSString *key;
key = [NSString stringWithFormat: @"%@\n%@\n%@\n%@",
[_url host], [_url port],
[_url user], [_url gcsDatabaseName]];
return key;
}
/* adaptors */
- (NSDictionary *) connectionDictionaryForURL: (NSURL *) _url
@ -184,7 +170,7 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
if (_url)
{
if ((key = [self databaseKeyForURL: _url]))
if ((key = [_url gcsURLId]))
{
adaptor = [urlToAdaptor objectForKey: key];
if (adaptor)
@ -289,60 +275,77 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
// TODO: naive implementation, add pooling!
EOAdaptorChannel *channel;
GCSChannelHandle *handle;
NSCalendarDate *now;
NSCalendarDate *now, *lastFailure;
NSString *urlId;
channel = nil;
urlId = [_url gcsURLId];
now = [NSCalendarDate date];
/* look for cached handles */
handle = [self findAvailChannelHandleForURL: _url];
if (handle)
lastFailure = [lastFailures objectForKey: urlId];
if ([[lastFailure dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0 seconds: 5]
earlierDate: now] != now)
{
// TODO: check age?
[busyChannels addObject: handle];
[availableChannels removeObject: handle];
ASSIGN (handle->lastAcquireTime, now);
/* look for cached handles */
channel = [handle channel];
if (debugPools)
[self logWithFormat: @"DBPOOL: reused cached DB channel! (%p)",
channel];
}
else
{
if (debugPools)
{
[self logWithFormat: @"DBPOOL: create new DB channel for URL: %@",
[_url absoluteString]];
}
handle = [self findAvailChannelHandleForURL: _url];
if (handle)
{
// TODO: check age?
[busyChannels addObject: handle];
[availableChannels removeObject: handle];
ASSIGN (handle->lastAcquireTime, now);
/* create channel */
channel = [self _createChannelForURL: _url];
if (channel)
{
if ([channel isOpen]
|| [channel openChannel])
{
/* create handle for channel */
channel = [handle channel];
if (debugPools)
[self logWithFormat: @"DBPOOL: reused cached DB channel! (%p)",
channel];
}
else
{
if (debugPools)
{
[self logWithFormat: @"DBPOOL: create new DB channel for URL: %@",
[_url absoluteString]];
}
handle = [[GCSChannelHandle alloc] init];
handle->url = [_url retain];
handle->channel = [channel retain];
handle->creationTime = [now retain];
handle->lastAcquireTime = [now retain];
/* create channel */
channel = [self _createChannelForURL: _url];
if (channel)
{
if ([channel isOpen]
|| [channel openChannel])
{
/* create handle for channel */
[busyChannels addObject: handle];
[handle release];
}
else
{
[self errorWithFormat: @"could not open channel %@ for URL: %@",
channel, [_url absoluteString]];
channel = nil;
}
}
handle = [[GCSChannelHandle alloc] init];
handle->url = [_url retain];
handle->channel = [channel retain];
handle->creationTime = [now retain];
handle->lastAcquireTime = [now retain];
[busyChannels addObject: handle];
[handle release];
if (lastFailure)
{
[self logWithFormat: @"db for %@ is now back up",
[_url absoluteString]];
[lastFailures removeObjectForKey: urlId];
}
}
else
{
[self errorWithFormat: @"could not open channel %@ for URL: %@",
channel, [_url absoluteString]];
channel = nil;
[lastFailures setObject: now forKey: urlId];
[self warnWithFormat: @" will prevent opening of this"
@" channel 5 seconds after %@", now];
}
}
}
}
return channel;

View File

@ -56,10 +56,13 @@
- (NSString *) gcsURLId
{
return [NSString stringWithFormat: @"%@:%@:%@:%@:%@",
/*
We need to build a proper key that omits passwords and URL path components
which are not required.
*/
return [NSString stringWithFormat: @"%@:%@:%@:%@",
[self host], [self port],
[self user], [self password],
[self gcsDatabaseName]];
[self user], [self gcsDatabaseName]];
}
@end /* NSURL(GCS) */