Author: rfm
Date: Thu May 28 10:39:10 2015
New Revision: 38579
URL: http://svn.gna.org/viewcvs/gnustep?rev=38579&view=rev
Log:
Various pool management enhancements
Modified:
libs/sqlclient/trunk/ChangeLog
libs/sqlclient/trunk/SQLClient.h
libs/sqlclient/trunk/SQLClient.m
libs/sqlclient/trunk/SQLClientPool.m
libs/sqlclient/trunk/testPostgres.m
Modified: libs/sqlclient/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/ChangeLog?rev=38579&r1=38578&r2=38579&view=diff
==============================================================================
--- libs/sqlclient/trunk/ChangeLog (original)
+++ libs/sqlclient/trunk/ChangeLog Thu May 28 10:39:10 2015
@@ -1,3 +1,10 @@
+2015-05-28 Richard Frith-Macdonald <[email protected]>
+
+ * SQLClient.h: Add pool purge control method.
+ * SQLClient.m: Fix bug finding least recently used client.
+ * SQLClientPool.m: Refine purging of pool. Fix autorelease bug.
+ Improve diagnostics. Fix bug reporting time pool has blocked.
+
2015-05-27 Richard Frith-Macdonald <[email protected]>
* Postgres.m: bugfixes
Modified: libs/sqlclient/trunk/SQLClient.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.h?rev=38579&r1=38578&r2=38579&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.h (original)
+++ libs/sqlclient/trunk/SQLClient.h Thu May 28 10:39:10 2015
@@ -1548,6 +1548,8 @@
NSTimeInterval _longest; /** Count of longest delay */
NSTimeInterval _delayWaits; /** Time waiting for provisions */
NSTimeInterval _failWaits; /** Time waiting for timewouts */
+ NSTimeInterval _purgeAll; /** Age to purge all connections */
+ NSTimeInterval _purgeMin; /** Age to purge excess connections */
}
/** Returns the count of currently available connections in the pool.
@@ -1575,6 +1577,11 @@
name: (NSString*)reference
max: (int)maxConnections
min: (int)minConnections;
+
+/** Returns a long description of the pool including statistics and
+ * the description of a sample client.
+ */
+- (NSString*) longDescription;
/** Return the maximum number of database connections in the pool.
*/
@@ -1637,6 +1644,13 @@
* maxConnections and may not be less than 1.
*/
- (void) setMax: (int)maxConnections min: (int)minConnections;
+
+/** Sets the ages (in seconds) after which idle connections are closed in
+ * the -purge method. Where there are excess connections (more than the
+ * minimum configured connection count) in the pool, minSeconds is used,
+ * otherwise allSeconds is used.
+ */
+- (void) setPurgeAll: (int)allSeconds min: (int)minSeconds;
/** Returns a string describing the usage of the pool.
*/
Modified: libs/sqlclient/trunk/SQLClient.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.m?rev=38579&r1=38578&r2=38579&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.m (original)
+++ libs/sqlclient/trunk/SQLClient.m Thu May 28 10:39:10 2015
@@ -1444,11 +1444,11 @@
}
}
- if (t1 > 0.0 && t1 <= t0)
+ if (t1 > 0.0 && (t1 <= t0 || 0.0 == t0))
{
return other;
}
- if (t0 > 0.0 && t0 <= t1)
+ if (t0 > 0.0 && (t0 <= t1 || 0.0 == t1))
{
return self;
}
Modified: libs/sqlclient/trunk/SQLClientPool.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClientPool.m?rev=38579&r1=38578&r2=38579&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClientPool.m (original)
+++ libs/sqlclient/trunk/SQLClientPool.m Thu May 28 10:39:10 2015
@@ -37,16 +37,6 @@
#import <Performance/GSCache.h>
#import "SQLClient.h"
-/** Connections idle for more than this time are candidates for purging
- * as long as there are at leas min connections open.
- */
-static NSTimeInterval purgeMinTime = 10.0;
-
-/** Connections idle for more than this time are candidates for purging
- * even if the number of open connections is less than or equal to min.
- */
-static NSTimeInterval purgeAllTime = 300.0;
-
@interface SQLClient(Pool)
- (void) _clearPool: (SQLClientPool*)p;
@end
@@ -132,13 +122,7 @@
- (NSString*) description
{
- NSMutableString *s = [[NSMutableString new] autorelease];
-
- [s appendString: [super description]];
- [s appendFormat: @"name:'%@', max:%d, min:%d\n", _name, max, min];
- [s appendString: [self statistics]];
- [s appendString: [q description]];
- return s;
+ return [NSString stringWithFormat: @"%@ '%@'", [super description], _name];
}
- (id) initWithConfiguration: (NSDictionary*)config
@@ -148,6 +132,7 @@
{
if (nil != (self = [super init]))
{
+ CREATE_AUTORELEASE_POOL(arp);
ASSIGN(_config, config);
ASSIGNCOPY(_name, reference);
lock = [[NSConditionLock alloc] initWithCondition: 0];
@@ -156,10 +141,22 @@
* available for general use since quoting does not actually
* require any database operation.
*/
- q = [[self provideClient] retain];
+ q = RETAIN([self provideClient]);
[self swallowClient: q];
+ RELEASE(arp);
}
return self;
+}
+
+- (NSString*) longDescription
+{
+ NSMutableString *s = [[NSMutableString new] autorelease];
+
+ [s appendString: [self description]];
+ [s appendFormat: @", max:%d, min:%d\n", max, min];
+ [s appendString: [self statistics]];
+ [s appendString: [q description]];
+ return s;
}
- (int) maxConnections
@@ -193,7 +190,7 @@
if (nil == future)
{
- future = [[NSDate distantFuture] retain];
+ future = RETAIN([NSDate distantFuture]);
}
when = future;
}
@@ -218,13 +215,14 @@
if (_debugging > 1)
{
- NSLog(@"%@ has no clients available", self);
- }
- until = [[NSDate alloc] initWithTimeIntervalSinceNow: 10.0];
+ NSLog(@"%@ has no clients available", [self description]);
+ }
+ now = [NSDate timeIntervalSinceReferenceDate];
+ until = [[NSDate alloc]
+ initWithTimeIntervalSinceReferenceDate: now + 10.0];
locked = NO;
while (NO == locked && now < end)
{
- now = [NSDate timeIntervalSinceReferenceDate];
if (now >= end)
{
/* End date is passed ... try to get the lock immediately.
@@ -239,12 +237,14 @@
{
locked = [lock lockWhenCondition: 1 beforeDate: when];
}
+ now = [NSDate timeIntervalSinceReferenceDate];
dif = now - start;
if (NO == locked && now < end)
{
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
- NSLog(@"%@ still waiting after %g seconds", self, dif);
+ NSLog(@"%@ still waiting after %g seconds",
+ [self description], dif);
}
[until release];
until = [[NSDate alloc] initWithTimeIntervalSinceNow: 10.0];
@@ -259,7 +259,8 @@
{
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
- NSLog(@"%@ abandoned wait after %g seconds", self, dif);
+ NSLog(@"%@ abandoned wait after %g seconds",
+ [self description], dif);
}
_failed++;
_failWaits += dif;
@@ -267,7 +268,8 @@
}
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
- NSLog(@"%@ provided client after %g seconds", self, dif);
+ NSLog(@"%@ provided client after %g seconds",
+ [self description], dif);
}
_delayed++;
_delayWaits += dif;
@@ -306,7 +308,7 @@
[lock unlockWithCondition: cond];
if (_debugging > 2)
{
- NSLog(@"%@ provides %p", self, c[found]);
+ NSLog(@"%@ provides %p", [self description], c[found]);
}
return [c[found] autorelease];
}
@@ -344,8 +346,13 @@
NSTimeInterval age;
age = -[[found lastOperation] timeIntervalSinceNow];
- if (age > purgeAllTime
- || (connected > min && age > purgeMinTime))
+ if (_debugging > 2)
+ {
+ NSLog(@"%@ purge found %p age %g",
+ [self description], found, age);
+ }
+ if (age > _purgeAll
+ || (connected > min && age > _purgeMin))
{
NS_DURING
{
@@ -480,6 +487,24 @@
}
min = minConnections;
[self _unlock];
+}
+
+- (void) setPurgeAll: (int)allSeconds min: (int)minSeconds
+{
+ if (allSeconds < 1)
+ {
+ allSeconds = 300;
+ }
+ if (minSeconds < 1)
+ {
+ minSeconds = 10;
+ }
+ if (allSeconds < minSeconds)
+ {
+ allSeconds = minSeconds;
+ }
+ _purgeMin = minSeconds;
+ _purgeAll = allSeconds;
}
- (NSString*) statistics
@@ -508,11 +533,30 @@
- (BOOL) swallowClient: (SQLClient*)client
{
- BOOL disconnected = NO;
- BOOL replaced = NO;
BOOL found = NO;
int index;
+ if (YES == [client isInTransaction])
+ {
+ /* The client has a transaction in progress ... if it's in the
+ * current thread we should be able to disconnect (implicit rollback)
+ * and return the client to the pool, otherwise we raise an exception.
+ */
+ if (YES == [client lockBeforeDate: nil])
+ {
+ [client disconnect];
+ [client unlock];
+ NSLog(@"ERROR: Disconnected client which was returned to pool"
+ @" while a transaction was in progress: %@", client);
+ }
+ else
+ {
+ [NSException raise: SQLConnectionException
+ format: @"failed to return to pool because a transaction"
+ @" was in progress: %@", client];
+ }
+ }
+
[self _lock];
for (index = 0; index < max && NO == found; index++)
{
@@ -522,46 +566,18 @@
found = YES;
}
}
- if (YES == found && YES == [client isInTransaction])
- {
- if (YES == [client lockBeforeDate: nil])
- {
- disconnected = YES;
- [client disconnect];
- [client unlock];
+ [self _unlock];
+
+ if (_debugging > 2)
+ {
+ if (YES == found)
+ {
+ NSLog(@"%@ swallows %p", [self description], client);
}
else
{
- replaced = YES;
- c[index] = [[SQLClient alloc] initWithConfiguration: _config
- name: _name
- pool: self];
- }
- }
- [self _unlock];
-
- if (_debugging > 2)
- {
- if (YES == found)
- {
- NSLog(@"%@ swallows %p", self, client);
- }
- else
- {
- NSLog(@"%@ rejects %p", self, client);
- }
- }
-
- if (YES == disconnected)
- {
- NSLog(@"ERROR: Disconnected client which was returned to pool"
- @" while a transaction was in progress: %@", client);
- }
- else if (YES == replaced)
- {
- NSLog(@"ERROR: Replaced client which was returned to pool"
- @" while a transaction was in progress: %@", client);
- [client release];
+ NSLog(@"%@ rejects %p", [self description], client);
+ }
}
return found;
Modified: libs/sqlclient/trunk/testPostgres.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/testPostgres.m?rev=38579&r1=38578&r2=38579&view=diff
==============================================================================
--- libs/sqlclient/trunk/testPostgres.m (original)
+++ libs/sqlclient/trunk/testPostgres.m Thu May 28 10:39:10 2015
@@ -73,7 +73,7 @@
name: @"test"
max: 2
min: 1] autorelease];
-#if 0
+#if 1
{
NSAutoreleasePool *p;
SQLClient *c0;
@@ -83,18 +83,39 @@
p = [NSAutoreleasePool new];
c0 = [sp provideClient];
c1 = [sp provideClient];
+ NSLog(@"Got two clients from pool");
+ [c0 connect];
+ [c1 connect];
+ NSLog(@"Now putting clients back in pool again");
+ [sp swallowClient: c0];
+ [sp swallowClient: c1];
+ [sp setPurgeAll: 60 min: 1];
+ [NSThread sleepForTimeInterval: 1.0];
+ NSLog(@"Expecting purge to disconnect one client");
+ [sp purge];
+ c0 = [sp provideClient];
+ c1 = [sp provideClient];
+ NSLog(@"Expecting connected: %@", [c0 connected] ? @"YES" : @"NO");
+ NSLog(@"Expecting not connected: %@", [c1 connected] ? @"NO" : @"YES");
+
+ NSLog(@"Pool has provided both it's clients ... now try for another with a
15 second timeout");
[sp provideClientBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 15.0]];
+ NSLog(@"Emptying autorelease pool ... clients should be put back in pool");
[p release];
p = [NSAutoreleasePool new];
+ NSLog(@"Getting two clients again");
c0 = [sp provideClient];
c1 = [sp provideClient];
+ NSLog(@"Pool has provided both it's clients ... now try for another with a
15 second timeout");
[sp provideClientBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 15.0]];
+ NSLog(@"Emptying autorelease pool again");
[p release];
- [sp provideClientBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 25.0]];
+ NSLog(@"Expect to get client immediately");
}
#endif
db = [sp provideClient];
[sp swallowClient: db];
+
[sp queryString: @"SELECT CURRENT_TIMESTAMP", nil];
db = [sp provideClient];
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs