mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-21 19:01:03 +00:00
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:
parent
dd264972c9
commit
c84e989ab2
3 changed files with 102 additions and 49 deletions
13
SQLClient.h
13
SQLClient.h
|
@ -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).
|
||||||
*/
|
*/
|
||||||
|
|
126
SQLClient.m
126
SQLClient.m
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue