Author: rfm
Date: Fri May 29 11:33:03 2015
New Revision: 38583
URL: http://svn.gna.org/viewcvs/gnustep?rev=38583&view=rev
Log:
Improve diagnostics
Modified:
libs/sqlclient/trunk/SQLClient.h
libs/sqlclient/trunk/SQLClient.m
libs/sqlclient/trunk/SQLClientPool.m
Modified: libs/sqlclient/trunk/SQLClient.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.h?rev=38583&r1=38582&r2=38583&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.h (original)
+++ libs/sqlclient/trunk/SQLClient.h Fri May 29 11:33:03 2015
@@ -439,6 +439,7 @@
* -lastOperation method in that case.
*/
NSTimeInterval _lastOperation;
+ NSTimeInterval _lastConnect; /** Last successful connect */
NSTimeInterval _lastStart; /** Last op start or connect */
NSTimeInterval _duration; /** Duration logging threshold */
unsigned int _debugging; /** The current debugging level */
@@ -743,6 +744,12 @@
* -begin, -commit, and -rollback.
*/
- (BOOL) isInTransaction;
+
+/**
+ * Returns the date/time stamp of the last database connection established
+ * by the receiver, or nil if no connection has ever been established.
+ */
+- (NSDate*) lastConnect;
/**
* Returns the date/time stamp of the last database operation performed
@@ -1535,6 +1542,7 @@
NSConditionLock *lock; /** Controls access to the pool contents */
SQLClient **c; /** The clients of the pool. */
BOOL *u; /** Whether the client is in use. */
+ NSTimeInterval *t; /** When client was removed from pool. */
int max; /** Maximum connection count */
int min; /** Minimum connection count */
NSDictionary *_config; /** The pool configuration object */
@@ -1577,8 +1585,8 @@
max: (int)maxConnections
min: (int)minConnections;
-/** Returns a long description of the pool including statistics and
- * the description of a sample client.
+/** Returns a long description of the pool including statistics, status,
+ * and the description of a sample client.
*/
- (NSString*) longDescription;
@@ -1654,6 +1662,10 @@
/** Returns a string describing the usage of the pool.
*/
- (NSString*) statistics;
+
+/** Returns a string describing the status of the pool.
+ */
+- (NSString*) status;
/** Puts the client back in the pool. This happens automatically
* when a client from a pool would normally be deallocated so you don't
Modified: libs/sqlclient/trunk/SQLClient.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClient.m?rev=38583&r1=38582&r2=38583&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClient.m (original)
+++ libs/sqlclient/trunk/SQLClient.m Fri May 29 11:33:03 2015
@@ -1105,6 +1105,7 @@
[self backendListen: n];
}
}
+ _lastConnect = GSTickerTimeNow();
_connectFails = 0;
}
NS_HANDLER
@@ -1396,6 +1397,15 @@
- (BOOL) isInTransaction
{
return _inTransaction;
+}
+
+- (NSDate*) lastConnect
+{
+ if (_lastConnect > 0.0)
+ {
+ return [NSDate dateWithTimeIntervalSinceReferenceDate: _lastConnect];
+ }
+ return nil;
}
- (NSDate*) lastOperation
@@ -2401,22 +2411,9 @@
GSCache *cache;
id result;
- [lock lock];
- NS_DURING
- {
- result = [self backendQuery: a->query
- recordType: a->recordType
- listType: a->listType];
- }
- NS_HANDLER
- {
- result = nil;
- [lock unlock];
- [localException raise];
- }
- NS_ENDHANDLER
- [lock unlock];
-
+ result = [self simpleQuery: a->query
+ recordType: a->recordType
+ listType: a->listType];
cache = [self cache];
[cache setObject: result
forKey: a->query
Modified: libs/sqlclient/trunk/SQLClientPool.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/sqlclient/trunk/SQLClientPool.m?rev=38583&r1=38582&r2=38583&view=diff
==============================================================================
--- libs/sqlclient/trunk/SQLClientPool.m (original)
+++ libs/sqlclient/trunk/SQLClientPool.m Fri May 29 11:33:03 2015
@@ -71,7 +71,7 @@
available = index = max;
while (index-- > 0)
{
- if (YES == u[index])
+ if (YES == u[index])
{
available--;
}
@@ -87,18 +87,21 @@
- (void) dealloc
{
- SQLClient **clients;
- BOOL *used;
- int count;
- int i;
+ SQLClient **clients;
+ NSTimeInterval *times;
+ BOOL *used;
+ int count;
+ int i;
[lock lock];
count = max;
max = 0;
min = 0;
clients = c;
+ times = t;
used = u;
c = 0;
+ t = 0;
u = 0;
[lock unlock];
DESTROY(lock);
@@ -115,6 +118,7 @@
}
}
free(clients);
+ free(times);
free(used);
}
[SQLClientPool _adjustPoolConnections: -count];
@@ -146,7 +150,8 @@
NSMutableString *s = [[NSMutableString new] autorelease];
[s appendString: [self description]];
- [s appendFormat: @", max:%d, min:%d\n", max, min];
+ [s appendString: @", "];
+ [s appendString: [self status]];
[s appendString: [self statistics]];
[s appendString: [c[0] description]];
return s;
@@ -169,11 +174,13 @@
- (SQLClient*) provideClientBeforeDate: (NSDate*)when
{
- SQLClient *client;
- int connected = -1;
- int found = -1;
- int index;
- int cond = 0;
+ NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
+ NSTimeInterval now = start;
+ SQLClient *client;
+ int connected = -1;
+ int found = -1;
+ int cond = 0;
+ int index;
/* 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.
@@ -200,9 +207,7 @@
}
else
{
- NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval end = [when timeIntervalSinceReferenceDate];
- NSTimeInterval now = 0.0;
NSTimeInterval dif = 0.0;
NSDate *until;
BOOL locked;
@@ -211,7 +216,6 @@
{
NSLog(@"%@ has no clients available", self);
}
- now = [NSDate timeIntervalSinceReferenceDate];
until = [[NSDate alloc]
initWithTimeIntervalSinceReferenceDate: now + 10.0];
locked = NO;
@@ -235,10 +239,11 @@
dif = now - start;
if (NO == locked && now < end)
{
- if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
+ if (_debugging > 0 || dif > 30.0
+ || (_duration >= 0.0 && dif > _duration))
{
- NSLog(@"%@ still waiting after %g seconds",
- self, dif);
+ NSLog(@"%@ still waiting after %g seconds:\n%@",
+ self, dif, [self status]);
}
[until release];
until = [[NSDate alloc] initWithTimeIntervalSinceNow: 10.0];
@@ -251,10 +256,11 @@
}
if (NO == locked)
{
- if (_debugging > 0 || (_duration >= 0.0 && dif > _duration))
- {
- NSLog(@"%@ abandoned wait after %g seconds",
- self, dif);
+ if (_debugging > 0 || dif > 30.0
+ || (_duration >= 0.0 && dif > _duration))
+ {
+ NSLog(@"%@ abandoned wait after %g seconds:\n%@",
+ self, dif, [self status]);
}
_failed++;
_failWaits += dif;
@@ -299,6 +305,7 @@
found = connected;
}
u[found] = YES;
+ t[found] = now;
[lock unlockWithCondition: cond];
client = [c[found] autorelease];
if (_debugging > 2)
@@ -380,7 +387,7 @@
[c[0] setCache: nil];
aCache = [c[0] cache];
}
- for (index = 0; index < max; index++)
+ for (index = 1; index < max; index++)
{
[c[index] setCache: aCache];
}
@@ -452,11 +459,13 @@
}
}
c = realloc(c, maxConnections * sizeof(SQLClient*));
+ t = realloc(t, maxConnections * sizeof(NSTimeInterval));
u = realloc(u, maxConnections * sizeof(BOOL));
}
else
{
c = calloc(maxConnections, sizeof(SQLClient*));
+ t = calloc(maxConnections, sizeof(NSTimeInterval));
u = calloc(maxConnections, sizeof(BOOL));
}
for (index = max; index < maxConnections; index++)
@@ -526,6 +535,117 @@
return s;
}
+- (NSString*) status
+{
+ NSMutableArray *idleInfo = nil;
+ NSMutableArray *liveInfo = nil;
+ unsigned int cond = 0;
+ unsigned int free = 0;
+ unsigned int dead = 0;
+ unsigned int idle = 0;
+ unsigned int live = 0;
+ unsigned int used = 0;
+ int index;
+ NSMutableString *s;
+
+ [lock lock];
+ for (index = 0; index < max; index++)
+ {
+ SQLClient *client = c[index];
+
+ /* Check to see if this client is free to be taken from the pool.
+ * Also, if a client is connected but not in use, we call it idle.
+ */
+ if (YES == u[index])
+ {
+ /* This is a client which has been provided by the pool,
+ * so it is in use by some code.
+ */
+ if (YES == [client isInTransaction])
+ {
+ NSDate *d = [client lastOperation];
+
+ live++;
+ if (nil == liveInfo)
+ {
+ liveInfo = [NSMutableArray array];
+ }
+ [liveInfo addObject: [NSString stringWithFormat:
+ @" Client '%@' active in transaction since %@\n",
+ [client name], d]];
+ }
+ else
+ {
+ if (YES == [client connected])
+ {
+ NSDate *d = [client lastOperation];
+
+ used++;
+ if (nil == d)
+ {
+ d = [client lastConnect];
+ }
+ if ([d timeIntervalSinceReferenceDate] < t[index])
+ {
+ d = [NSDate dateWithTimeIntervalSinceReferenceDate:
+ t[index]];
+ }
+ if (nil == idleInfo)
+ {
+ idleInfo = [NSMutableArray array];
+ }
+ [idleInfo addObject: [NSString stringWithFormat:
+ @" Client '%@' taken from pool but idle since %@\n",
+ [client name], d]];
+ }
+ else
+ {
+ idle++;
+ }
+ }
+ }
+ else
+ {
+ /* The client is not in use and can be provided by the pool,
+ * so we must therefore re-lock with condition 1.
+ */
+ cond = 1;
+ if (YES == [c[index] connected])
+ {
+ /* Still connected, so we count it as a free connection.
+ */
+ free++;
+ }
+ else
+ {
+ /* Not connected, so we count it as a dead connection.
+ */
+ dead++;
+ }
+ }
+ }
+
+ s = [NSMutableString stringWithFormat: @" size min: %u, max: %u\n"
+ @"live:%u, used:%u, idle:%u, free:%u, dead:%u\n",
+ min, max, live, used, idle, free, dead];
+ if (liveInfo)
+ {
+ for (index = 0; index < [liveInfo count]; index++)
+ {
+ [s appendString: [liveInfo objectAtIndex: index]];
+ }
+ }
+ if (idleInfo)
+ {
+ for (index = 0; index < [idleInfo count]; index++)
+ {
+ [s appendString: [idleInfo objectAtIndex: index]];
+ }
+ }
+ [lock unlockWithCondition: cond];
+ return s;
+}
+
- (BOOL) _swallowClient: (SQLClient*)client withRetain: (BOOL)shouldRetain
{
BOOL found = NO;
@@ -619,57 +739,19 @@
- (void) _unlock
{
- int idle = 0;
- int used = 0;
- int cond = 0;
int index;
for (index = 0; index < max; index++)
{
/* Check to see if this client is free to be taken from the pool.
- * Also, if a client is connected but not in use, we call it idle.
*/
- if (YES == u[index])
- {
- /* This is a client which has been provided by the pool,
- * so it is in use by some code.
- */
- used++;
- }
- else
- {
- /* The client is not in use and can be provided by the pool,
- * so we must therefore re-lock with condition 1.
- */
- cond = 1;
-
- if (YES == [c[index] connected])
- {
- /* This unused client is still connected, so we count
- * it as an idle connection.
- */
- idle++;
- }
- }
- }
-
- /* If we have fewer connections than we want, connect clients until we
- * are back up to the minimum.
- */
- for (index = 0; index < max && (used + idle) < min; index++)
- {
- if (NO == u[index] && NO == [c[index] connected])
- {
- NS_DURING
- [c[index] connect];
- NS_HANDLER
- NSLog(@"Failed to connect %@ ... %@", c[index], localException);
- NS_ENDHANDLER
- idle++;
- }
- }
-
- [lock unlockWithCondition: cond];
+ if (NO == u[index])
+ {
+ [lock unlockWithCondition: 1];
+ return;
+ }
+ }
+ [lock unlockWithCondition: 0];
}
@end
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs