Add code to limit idle connections in pool to the poll 'min' size.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@37951 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2014-06-20 05:15:24 +00:00
parent dd264972c9
commit c84e989ab2
3 changed files with 102 additions and 49 deletions

View file

@ -383,14 +383,15 @@ SQLCLIENT_PRIVATE
NSString *_user; /** The configured user */ NSString *_user; /** The configured user */
NSMutableArray *_statements; /** Uncommitted statements */ NSMutableArray *_statements; /** Uncommitted statements */
/** /**
* Timestamp of last operation.<br /> * Timestamp of completion of last operation.<br />
* Maintained by -simpleExecute: -simpleQuery:recordType:listType: * Maintained by -simpleExecute: -simpleQuery:recordType:listType:
* and -cache:simpleQuery:recordType:listType: * and -cache:simpleQuery:recordType:listType:
* Also set for a failed connection attempt, but not reported by the * Also set for a failed connection attempt, but not reported by the
* -lastOperation method in that case. * -lastOperation method in that case.
*/ */
NSTimeInterval _lastOperation; NSTimeInterval _lastOperation;
NSTimeInterval _duration; NSTimeInterval _lastStart; /** Last op start or connect */
NSTimeInterval _duration; /** Duration logging threshold */
unsigned int _debugging; /** The current debugging level */ unsigned int _debugging; /** The current debugging level */
GSCache *_cache; /** The cache for query results */ GSCache *_cache; /** The cache for query results */
NSThread *_cacheThread; /** Thread for cache queries */ NSThread *_cacheThread; /** Thread for cache queries */
@ -687,6 +688,14 @@ SQLCLIENT_PRIVATE
*/ */
- (NSDate*) lastOperation; - (NSDate*) lastOperation;
/** Compares the receiver with the other client to see which one has been
* inactive but connected for longest (if they are connected) and returns
* that instance.<br />
* If neither is idle but connected, the method returns nil.<br />
* In a tie, the method returns the other instance.
*/
- (SQLClient*) longestIdle: (SQLClient*)other;
/** /**
* Return the database reference name for this instance (or nil). * Return the database reference name for this instance (or nil).
*/ */

View file

@ -76,10 +76,11 @@ NSString * const SQLClientDidDisconnectNotification
static NSNull *null = nil; static NSNull *null = nil;
static NSArray *queryModes = nil; static NSArray *queryModes = nil;
static NSThread *mainThread = nil; static NSThread *mainThread = nil;
static Class NSStringClass = 0; static Class NSStringClass = Nil;
static Class NSArrayClass = 0; static Class NSArrayClass = Nil;
static Class NSDateClass = 0; static Class NSDateClass = Nil;
static Class NSSetClass = 0; static Class NSSetClass = Nil;
static Class SQLClientClass = Nil;
@interface _ConcreteSQLRecord : SQLRecord @interface _ConcreteSQLRecord : SQLRecord
{ {
@ -738,29 +739,34 @@ static unsigned int maxConnections = 8;
+ (void) initialize + (void) initialize
{ {
static id modes[1]; if (Nil == SQLClientClass && [SQLClient class] == self)
modes[0] = NSDefaultRunLoopMode;
queryModes = [[NSArray alloc] initWithObjects: modes count: 1];
GSTickerTimeNow();
[SQLRecord class]; // Force initialisation
if (0 == clientsHash)
{ {
clientsHash = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0); static id modes[1];
clientsMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSNonRetainedObjectMapValueCallBacks, 0); SQLClientClass = self;
clientsLock = [NSRecursiveLock new]; modes[0] = NSDefaultRunLoopMode;
beginStatement = [[NSArray arrayWithObject: beginString] retain]; queryModes = [[NSArray alloc] initWithObjects: modes count: 1];
commitStatement = [[NSArray arrayWithObject: commitString] retain]; GSTickerTimeNow();
rollbackStatement = [[NSArray arrayWithObject: rollbackString] retain]; [SQLRecord class]; // Force initialisation
NSStringClass = [NSString class]; if (0 == clientsHash)
NSArrayClass = [NSArray class]; {
NSSetClass = [NSSet class]; clientsHash = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
[NSTimer scheduledTimerWithTimeInterval: 1.0 clientsMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
target: self NSNonRetainedObjectMapValueCallBacks, 0);
selector: @selector(_tick:) clientsLock = [NSRecursiveLock new];
userInfo: 0 beginStatement = [[NSArray arrayWithObject: beginString] retain];
repeats: YES]; commitStatement = [[NSArray arrayWithObject: commitString] retain];
rollbackStatement
= [[NSArray arrayWithObject: rollbackString] retain];
NSStringClass = [NSString class];
NSArrayClass = [NSArray class];
NSSetClass = [NSSet class];
[NSTimer scheduledTimerWithTimeInterval: 1.0
target: self
selector: @selector(_tick:)
userInfo: 0
repeats: YES];
}
} }
} }
@ -958,6 +964,7 @@ static unsigned int maxConnections = 8;
} }
} }
_lastStart = GSTickerTimeNow();
[self backendConnect]; [self backendConnect];
/* On establishng a new connection, we must restore any /* On establishng a new connection, we must restore any
* listen instructions in the backend. * listen instructions in the backend.
@ -1274,6 +1281,51 @@ static unsigned int maxConnections = 8;
return nil; return nil;
} }
- (SQLClient*) longestIdle: (SQLClient*)other
{
NSTimeInterval t0;
NSTimeInterval t1;
NSAssert([other isKindOfClass: SQLClientClass], NSInvalidArgumentException);
t0 = _lastOperation;
if (t0 < _lastStart)
{
t0 = _lastStart;
}
if (NO == connected || 0 != _connectFails)
{
t0 = 0.0;
}
if (YES == [other isProxy])
{
t1 = 0.0;
}
else
{
t1 = other->_lastOperation;
if (t1 < other->_lastStart)
{
t1 = other->_lastStart;
}
if (NO == connected || 0 != other->_connectFails)
{
t1 = 0.0;
}
}
if (t0 <= 0.0 && t1 <= 0.0)
{
return nil;
}
if (t1 <= t0)
{
return other;
}
return self;
}
- (NSString*) name - (NSString*) name
{ {
return _name; return _name;
@ -1706,7 +1758,6 @@ static unsigned int maxConnections = 8;
[lock lock]; [lock lock];
NS_DURING NS_DURING
{ {
NSTimeInterval start = 0.0;
NSString *statement; NSString *statement;
BOOL isCommit = NO; BOOL isCommit = NO;
BOOL isRollback = NO; BOOL isRollback = NO;
@ -1722,10 +1773,7 @@ static unsigned int maxConnections = 8;
isRollback = YES; isRollback = YES;
} }
if (_duration >= 0) _lastStart = GSTickerTimeNow();
{
start = GSTickerTimeNow();
}
result = [self backendExecute: info]; result = [self backendExecute: info];
_lastOperation = GSTickerTimeNow(); _lastOperation = GSTickerTimeNow();
[_statements addObject: statement]; [_statements addObject: statement];
@ -1733,7 +1781,7 @@ static unsigned int maxConnections = 8;
{ {
NSTimeInterval d; NSTimeInterval d;
d = _lastOperation - start; d = _lastOperation - _lastStart;
if (d >= _duration) if (d >= _duration)
{ {
if (isCommit || isRollback) if (isCommit || isRollback)
@ -1814,19 +1862,14 @@ static unsigned int maxConnections = 8;
[lock lock]; [lock lock];
NS_DURING NS_DURING
{ {
NSTimeInterval start = 0.0; _lastStart = GSTickerTimeNow();
if (_duration >= 0)
{
start = GSTickerTimeNow();
}
result = [self backendQuery: stmt recordType: rtype listType: ltype]; result = [self backendQuery: stmt recordType: rtype listType: ltype];
_lastOperation = GSTickerTimeNow(); _lastOperation = GSTickerTimeNow();
if (_duration >= 0) if (_duration >= 0)
{ {
NSTimeInterval d; NSTimeInterval d;
d = _lastOperation - start; d = _lastOperation - _lastStart;
if (d >= _duration) if (d >= _duration)
{ {
debug = [NSString stringWithFormat: debug = [NSString stringWithFormat:
@ -2678,7 +2721,6 @@ static unsigned int maxConnections = 8;
{ {
NSMutableArray *result; NSMutableArray *result;
NSMutableDictionary *md; NSMutableDictionary *md;
NSTimeInterval start;
GSCache *c; GSCache *c;
id toCache; id toCache;
@ -2688,7 +2730,7 @@ static unsigned int maxConnections = 8;
md = [[NSThread currentThread] threadDictionary]; md = [[NSThread currentThread] threadDictionary];
[md setObject: rtype forKey: @"SQLClientRecordType"]; [md setObject: rtype forKey: @"SQLClientRecordType"];
[md setObject: ltype forKey: @"SQLClientListType"]; [md setObject: ltype forKey: @"SQLClientListType"];
start = GSTickerTimeNow(); _lastStart = GSTickerTimeNow();
c = [self cache]; c = [self cache];
toCache = nil; toCache = nil;
@ -2733,7 +2775,7 @@ static unsigned int maxConnections = 8;
{ {
NSTimeInterval d; NSTimeInterval d;
d = _lastOperation - start; d = _lastOperation - _lastStart;
if (d >= _duration) if (d >= _duration)
{ {
[self debug: @"Duration %g for query %@", d, stmt]; [self debug: @"Duration %g for query %@", d, stmt];

View file

@ -69,11 +69,13 @@ main()
nil] nil]
]; ];
sp = [[SQLClientPool alloc] initWithConfiguration: nil sp = [[[SQLClientPool alloc] initWithConfiguration: nil
name: @"test" name: @"test"
max: 2 max: 2
min: 1]; min: 1] autorelease];
db = [[sp autorelease] provideClient]; db = [sp provideClient];
[sp swallowClient: db];
db = [sp provideClient];
l = [Logger new]; l = [Logger new];
[[NSNotificationCenter defaultCenter] addObserver: l [[NSNotificationCenter defaultCenter] addObserver: l