Fix retain/release issue and add more diagnostics

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38580 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2015-05-28 12:57:08 +00:00
parent 35ee61bad9
commit 6eee4f014a
4 changed files with 74 additions and 43 deletions

View file

@ -1534,7 +1534,6 @@ SQLCLIENT_PRIVATE
{
NSConditionLock *lock; /** Controls access to the pool contents */
SQLClient **c; /** The clients of the pool. */
SQLClient *q; /** The clients used for quoting. */
BOOL *u; /** Whether the client is in use. */
int max; /** Maximum connection count */
int min; /** Minimum connection count */

View file

@ -85,6 +85,10 @@ static Class NSDateClass = Nil;
static Class NSSetClass = Nil;
static Class SQLClientClass = Nil;
@interface SQLClientPool (Swallow)
- (BOOL) _swallowClient: (SQLClient*)client withRetain: (BOOL)shouldRetain;
@end
@implementation SQLRecordKeys
- (NSUInteger) count
@ -1765,7 +1769,7 @@ static int poolConnections = 0;
{
if (nil != _pool)
{
[_pool swallowClient: self];
[_pool _swallowClient: self withRetain: NO];
}
else
{

View file

@ -56,6 +56,7 @@
@interface SQLClientPool (Private)
- (void) _lock;
- (NSString*) _rc: (SQLClient*)o;
- (void) _unlock;
@end
@ -81,7 +82,7 @@
- (GSCache*) cache
{
return [q cache];
return [c[0] cache];
}
- (void) dealloc
@ -132,18 +133,10 @@
{
if (nil != (self = [super init]))
{
CREATE_AUTORELEASE_POOL(arp);
ASSIGN(_config, config);
ASSIGNCOPY(_name, reference);
lock = [[NSConditionLock alloc] initWithCondition: 0];
[self setMax: maxConnections min: minConnections];
/* Get a client to be used for quoting ... we can then make it
* available for general use since quoting does not actually
* require any database operation.
*/
q = RETAIN([self provideClient]);
[self swallowClient: q];
RELEASE(arp);
}
return self;
}
@ -155,7 +148,7 @@
[s appendString: [self description]];
[s appendFormat: @", max:%d, min:%d\n", max, min];
[s appendString: [self statistics]];
[s appendString: [q description]];
[s appendString: [c[0] description]];
return s;
}
@ -176,10 +169,11 @@
- (SQLClient*) provideClientBeforeDate: (NSDate*)when
{
int connected = -1;
int found = -1;
int index;
int cond = 0;
SQLClient *client;
int connected = -1;
int found = -1;
int index;
int cond = 0;
/* If we haven't been given a timeout, we should wait for a client
* indefinitely ... so we set the timeout to be in the distant future.
@ -215,7 +209,7 @@
if (_debugging > 1)
{
NSLog(@"%@ has no clients available", [self description]);
NSLog(@"%@ has no clients available", self);
}
now = [NSDate timeIntervalSinceReferenceDate];
until = [[NSDate alloc]
@ -244,7 +238,7 @@
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
NSLog(@"%@ still waiting after %g seconds",
[self description], dif);
self, dif);
}
[until release];
until = [[NSDate alloc] initWithTimeIntervalSinceNow: 10.0];
@ -260,7 +254,7 @@
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
NSLog(@"%@ abandoned wait after %g seconds",
[self description], dif);
self, dif);
}
_failed++;
_failWaits += dif;
@ -269,7 +263,7 @@
if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
{
NSLog(@"%@ provided client after %g seconds",
[self description], dif);
self, dif);
}
_delayed++;
_delayWaits += dif;
@ -306,11 +300,12 @@
}
u[found] = YES;
[lock unlockWithCondition: cond];
client = [c[found] autorelease];
if (_debugging > 2)
{
NSLog(@"%@ provides %p", [self description], c[found]);
NSLog(@"%@ provides %p%@", self, c[found], [self _rc: client]);
}
return [c[found] autorelease];
return client;
}
- (void) purge
@ -349,7 +344,7 @@
if (_debugging > 2)
{
NSLog(@"%@ purge found %p age %g",
[self description], found, age);
self, found, age);
}
if (age > _purgeAll
|| (connected > min && age > _purgeMin))
@ -531,7 +526,7 @@
return s;
}
- (BOOL) swallowClient: (SQLClient*)client
- (BOOL) _swallowClient: (SQLClient*)client withRetain: (BOOL)shouldRetain
{
BOOL found = NO;
int index;
@ -564,6 +559,10 @@
{
u[index] = NO;
found = YES;
if (YES == shouldRetain)
{
NSIncrementExtraRefCount(client);
}
}
}
[self _unlock];
@ -572,17 +571,21 @@
{
if (YES == found)
{
NSLog(@"%@ swallows %p", [self description], client);
NSLog(@"%@ swallows %p%@", self, client, [self _rc: client]);
}
else
{
NSLog(@"%@ rejects %p", [self description], client);
NSLog(@"%@ rejects %p%@", self, client, [self _rc: client]);
}
}
return found;
}
- (BOOL) swallowClient: (SQLClient*)client
{
return [self _swallowClient: client withRetain: YES];
}
@end
@implementation SQLClientPool (Private)
@ -592,6 +595,28 @@
[lock lock];
}
- (NSString*) _rc: (SQLClient*)o
{
#if defined(GNUSTEP)
if (_debugging > 3)
{
static Class cls = Nil;
unsigned long rc;
unsigned long ac;
if (Nil == cls)
{
cls = [NSAutoreleasePool class];
}
rc = (unsigned long)[o retainCount];
ac = (unsigned long)[cls autoreleaseCountForObject: o];
return [NSString stringWithFormat: @" refs %ld (%lu-%lu)",
rc - ac, rc, ac];
}
#endif
return @"";
}
- (void) _unlock
{
int idle = 0;
@ -660,7 +685,7 @@
* First check validity and concatenate parts of the query.
*/
va_start (ap, stmt);
sql = [[q prepare: stmt args: ap] objectAtIndex: 0];
sql = [[c[0] prepare: stmt args: ap] objectAtIndex: 0];
va_end (ap);
return sql;
@ -668,7 +693,7 @@
- (NSString*) buildQuery: (NSString*)stmt with: (NSDictionary*)values
{
NSString *result = [q buildQuery: stmt with: values];
NSString *result = [c[0] buildQuery: stmt with: values];
return result;
}
@ -681,7 +706,7 @@
va_list ap;
va_start (ap, stmt);
stmt = [[q prepare: stmt args: ap] objectAtIndex: 0];
stmt = [[c[0] prepare: stmt args: ap] objectAtIndex: 0];
va_end (ap);
db = [self provideClient];
@ -764,7 +789,7 @@
va_list ap;
va_start (ap, stmt);
info = [q prepare: stmt args: ap];
info = [c[0] prepare: stmt args: ap];
va_end (ap);
db = [self provideClient];
NS_DURING
@ -803,7 +828,7 @@
* First check validity and concatenate parts of the query.
*/
va_start (ap, stmt);
stmt = [[q prepare: stmt args: ap] objectAtIndex: 0];
stmt = [[c[0] prepare: stmt args: ap] objectAtIndex: 0];
va_end (ap);
db = [self provideClient];
@ -842,7 +867,7 @@
va_list ap;
va_start (ap, stmt);
stmt = [[q prepare: stmt args: ap] objectAtIndex: 0];
stmt = [[c[0] prepare: stmt args: ap] objectAtIndex: 0];
va_end (ap);
db = [self provideClient];
@ -876,7 +901,7 @@
va_list ap;
va_start (ap, stmt);
stmt = [[q prepare: stmt args: ap] objectAtIndex: 0];
stmt = [[c[0] prepare: stmt args: ap] objectAtIndex: 0];
va_end (ap);
db = [self provideClient];
@ -909,7 +934,7 @@
- (NSString*) quote: (id)obj
{
NSString *result = [q quote: obj];
NSString *result = [c[0] quote: obj];
return result;
}
@ -920,7 +945,7 @@
{
NSMutableString *result;
result = [q quoteArray: a toString:s quotingStrings: _q];
result = [c[0] quoteArray: a toString:s quotingStrings: _q];
return result;
}
@ -935,49 +960,49 @@
str = [[NSString allocWithZone: NSDefaultMallocZone()]
initWithFormat: fmt arguments: ap];
va_end(ap);
quoted = [q quoteString: str];
quoted = [c[0] quoteString: str];
[str release];
return quoted;
}
- (NSString*) quoteBigInteger: (int64_t)i
{
NSString *result = [q quoteBigInteger: i];
NSString *result = [c[0] quoteBigInteger: i];
return result;
}
- (NSString*) quoteCString: (const char *)s
{
NSString *result = [q quoteCString: s];
NSString *result = [c[0] quoteCString: s];
return result;
}
- (NSString*) quoteChar: (char)chr
{
NSString *result = [q quoteChar: chr];
NSString *result = [c[0] quoteChar: chr];
return result;
}
- (NSString*) quoteFloat: (float)f
{
NSString *result = [q quoteFloat: f];
NSString *result = [c[0] quoteFloat: f];
return result;
}
- (NSString*) quoteInteger: (int)i
{
NSString *result = [q quoteInteger: i];
NSString *result = [c[0] quoteInteger: i];
return result;
}
- (NSString*) quoteString: (NSString *)s
{
NSString *result = [q quoteString: s];
NSString *result = [c[0] quoteString: s];
return result;
}

View file

@ -79,7 +79,7 @@ main()
SQLClient *c0;
SQLClient *c1;
[sp setDebugging: 2];
[sp setDebugging: 4];
p = [NSAutoreleasePool new];
c0 = [sp provideClient];
c1 = [sp provideClient];
@ -89,6 +89,9 @@ main()
NSLog(@"Now putting clients back in pool again");
[sp swallowClient: c0];
[sp swallowClient: c1];
NSLog(@"And emptying autorelease pool");
[p release];
p = [NSAutoreleasePool new];
[sp setPurgeAll: 60 min: 1];
[NSThread sleepForTimeInterval: 1.0];
NSLog(@"Expecting purge to disconnect one client");