mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-21 19:01:03 +00:00
initial thread pool implementation
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@37950 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c738aae5bc
commit
dd264972c9
4 changed files with 143 additions and 280 deletions
|
@ -36,7 +36,7 @@ DOCUMENT_NAME=SQLClient
|
||||||
|
|
||||||
SQLClient_INTERFACE_VERSION=1.7
|
SQLClient_INTERFACE_VERSION=1.7
|
||||||
|
|
||||||
SQLClient_OBJC_FILES = SQLClient.m
|
SQLClient_OBJC_FILES = SQLClient.m SQLClientPool.m
|
||||||
SQLClient_LIBRARIES_DEPEND_UPON = -lPerformance
|
SQLClient_LIBRARIES_DEPEND_UPON = -lPerformance
|
||||||
SQLClient_HEADER_FILES = SQLClient.h
|
SQLClient_HEADER_FILES = SQLClient.h
|
||||||
SQLClient_AGSDOC_FILES = SQLClient.h
|
SQLClient_AGSDOC_FILES = SQLClient.h
|
||||||
|
|
68
SQLClient.h
68
SQLClient.h
|
@ -375,6 +375,7 @@ SQLCLIENT_PRIVATE
|
||||||
* This should only be modified by the -setShouldTrim: method.
|
* This should only be modified by the -setShouldTrim: method.
|
||||||
*/
|
*/
|
||||||
BOOL _shouldTrim; /** Should whitespace be trimmed? */
|
BOOL _shouldTrim; /** Should whitespace be trimmed? */
|
||||||
|
BOOL _forUseInPool; /** Should be used in a pool only */
|
||||||
NSString *_name; /** Unique identifier for instance */
|
NSString *_name; /** Unique identifier for instance */
|
||||||
NSString *_client; /** Identifier within backend */
|
NSString *_client; /** Identifier within backend */
|
||||||
NSString *_database; /** The configured database name/host */
|
NSString *_database; /** The configured database name/host */
|
||||||
|
@ -622,6 +623,13 @@ SQLCLIENT_PRIVATE
|
||||||
*/
|
*/
|
||||||
- (id) initWithConfiguration: (NSDictionary*)config;
|
- (id) initWithConfiguration: (NSDictionary*)config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls -initWithConfiguration:name:pool: passing NO to say the client is
|
||||||
|
* not in a pool.
|
||||||
|
*/
|
||||||
|
- (id) initWithConfiguration: (NSDictionary*)config
|
||||||
|
name: (NSString*)reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise using the supplied configuration, or if that is nil, try to
|
* Initialise using the supplied configuration, or if that is nil, try to
|
||||||
* use values from NSUserDefaults (and automatically update when the
|
* use values from NSUserDefaults (and automatically update when the
|
||||||
|
@ -630,10 +638,10 @@ SQLCLIENT_PRIVATE
|
||||||
* a nil name is supplied, defaults to the value of SQLClientName in the
|
* a nil name is supplied, defaults to the value of SQLClientName in the
|
||||||
* configuration dictionary (or in the standard user defaults). If there is
|
* configuration dictionary (or in the standard user defaults). If there is
|
||||||
* no value for SQLClientName, uses the string 'Database'.<br />
|
* no value for SQLClientName, uses the string 'Database'.<br />
|
||||||
* If a SQLClient instance already exists with the name used for this
|
* If forUseInPool is NO and a SQLClient instance already exists with the
|
||||||
* instance, the receiver is deallocated and the existing instance is
|
* name used for this instance, the receiver is deallocated and the existing
|
||||||
* retained and returned ... there may only ever be one instance for a
|
* instance is retained and returned ... there may only ever be one instance
|
||||||
* particular reference name.<br />
|
* for a particular reference name which is not in a pool.<br />
|
||||||
* <br />
|
* <br />
|
||||||
* The config argument (or the SQLClientReferences user default)
|
* The config argument (or the SQLClientReferences user default)
|
||||||
* is a dictionary with names as keys and dictionaries
|
* is a dictionary with names as keys and dictionaries
|
||||||
|
@ -653,7 +661,8 @@ SQLCLIENT_PRIVATE
|
||||||
* connect to a database on a different host over the network.
|
* connect to a database on a different host over the network.
|
||||||
*/
|
*/
|
||||||
- (id) initWithConfiguration: (NSDictionary*)config
|
- (id) initWithConfiguration: (NSDictionary*)config
|
||||||
name: (NSString*)reference;
|
name: (NSString*)reference
|
||||||
|
pool: (BOOL)forUseInPool;
|
||||||
|
|
||||||
/** Two clients are considered equal if they refer to the same database
|
/** Two clients are considered equal if they refer to the same database
|
||||||
* and are logged in as the same database user using the same protocol.
|
* and are logged in as the same database user using the same protocol.
|
||||||
|
@ -1367,13 +1376,60 @@ SQLCLIENT_PRIVATE
|
||||||
* asynchronous query to update them will be run on the cache thread.<br />
|
* asynchronous query to update them will be run on the cache thread.<br />
|
||||||
* The rule is that, if the item's age is more than twice its nominal
|
* The rule is that, if the item's age is more than twice its nominal
|
||||||
* lifetime, it will be retrieved immediately, otherwise it will be
|
* lifetime, it will be retrieved immediately, otherwise it will be
|
||||||
* retrieved asynchrnonously.<br />
|
* retrieved asynchronously.<br />
|
||||||
* Currently this may only be the main thread or nil. Any attempt to set
|
* Currently this may only be the main thread or nil. Any attempt to set
|
||||||
* another thread will use the main thread instead.
|
* another thread will use the main thread instead.
|
||||||
*/
|
*/
|
||||||
- (void) setCacheThread: (NSThread*)aThread;
|
- (void) setCacheThread: (NSThread*)aThread;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/** <p>An SQLClientPool instance may be used to create/control a pool of
|
||||||
|
* client objects. Code may obtain autoreleased proxies to the clients
|
||||||
|
* from the pool and use them safe in the knowledge that they won't be
|
||||||
|
* used anywhere else ... as soon as the proxy is deallocated the client
|
||||||
|
* is returned to the pool.
|
||||||
|
* </p>
|
||||||
|
* <p>All clients in the pool share the same cache object, so query results
|
||||||
|
* cached by one client will be available to other clients in the pool.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@interface SQLClientPool : NSObject
|
||||||
|
{
|
||||||
|
NSConditionLock *lock; /** Controls access to the pool contents */
|
||||||
|
SQLClient **c; /** The clients of the pool. */
|
||||||
|
SQLClient **p; /** The proxies of the pool. */
|
||||||
|
int max; /** Maximum connection count */
|
||||||
|
int min; /** Minimum connection count */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls -initWithConfiguration:name:pool: passing NO to say the client is
|
||||||
|
* not in a pool.
|
||||||
|
*/
|
||||||
|
- (id) initWithConfiguration: (NSDictionary*)config
|
||||||
|
name: (NSString*)reference
|
||||||
|
max: (int)maxConnections
|
||||||
|
min: (int)minConnections;
|
||||||
|
|
||||||
|
/** Fetches an (autoreleased) proxy to a client from the pool.
|
||||||
|
*/
|
||||||
|
- (SQLClient*) provideClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache for all the clients in the pool.
|
||||||
|
*/
|
||||||
|
- (void) setCache: (GSCache*)aCache;
|
||||||
|
|
||||||
|
/** Takes the client form the provided proxy and places it back
|
||||||
|
* in the queue (so the proxy stops using it). This happens automatically
|
||||||
|
* when the proxy is deallocated so you don't generally needs to do it.
|
||||||
|
* Returns YES if the supplied proxy referred to a client in the pool,
|
||||||
|
* NO otherwise.
|
||||||
|
*/
|
||||||
|
- (BOOL) swallowClient: (SQLClient*)proxy;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLTransaction transaction class provides a convenient mechanism
|
* The SQLTransaction transaction class provides a convenient mechanism
|
||||||
* for grouping together a series of SQL statements to be executed as a
|
* for grouping together a series of SQL statements to be executed as a
|
||||||
|
|
346
SQLClient.m
346
SQLClient.m
|
@ -36,9 +36,9 @@
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
#import <Foundation/NSException.h>
|
#import <Foundation/NSException.h>
|
||||||
#import <Foundation/NSHashTable.h>
|
|
||||||
#import <Foundation/NSKeyValueCoding.h>
|
#import <Foundation/NSKeyValueCoding.h>
|
||||||
#import <Foundation/NSLock.h>
|
#import <Foundation/NSLock.h>
|
||||||
|
#import <Foundation/NSHashTable.h>
|
||||||
#import <Foundation/NSMapTable.h>
|
#import <Foundation/NSMapTable.h>
|
||||||
#import <Foundation/NSNotification.h>
|
#import <Foundation/NSNotification.h>
|
||||||
#import <Foundation/NSNull.h>
|
#import <Foundation/NSNull.h>
|
||||||
|
@ -105,237 +105,6 @@ static Class NSSetClass = 0;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface SQLClientPool : NSObject
|
|
||||||
{
|
|
||||||
unsigned pool;
|
|
||||||
NSString *name;
|
|
||||||
NSString *serv;
|
|
||||||
NSString *user;
|
|
||||||
NSString *pass;
|
|
||||||
NSString *path;
|
|
||||||
NSHashTable *idle;
|
|
||||||
NSHashTable *used;
|
|
||||||
}
|
|
||||||
- (BOOL) isSingle;
|
|
||||||
- (BOOL) makeIdle: (SQLClient*)c;
|
|
||||||
- (BOOL) makeUsed: (SQLClient*)c;
|
|
||||||
- (void) setConfiguration: (NSDictionary*)o;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation SQLClientPool
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
if (idle != 0)
|
|
||||||
{
|
|
||||||
NSFreeHashTable(idle);
|
|
||||||
idle = 0;
|
|
||||||
}
|
|
||||||
if (used != 0)
|
|
||||||
{
|
|
||||||
NSFreeHashTable(used);
|
|
||||||
used = 0;
|
|
||||||
}
|
|
||||||
[name release]; name = nil;
|
|
||||||
[serv release]; serv = nil;
|
|
||||||
[user release]; user = nil;
|
|
||||||
[pass release]; pass = nil;
|
|
||||||
[path release]; path = nil;
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithConfiguration: (NSDictionary*)config
|
|
||||||
name: (NSString*)reference
|
|
||||||
{
|
|
||||||
name = [reference copy];
|
|
||||||
idle = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 16);
|
|
||||||
used = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 16);
|
|
||||||
[self setConfiguration: config];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) isSingle
|
|
||||||
{
|
|
||||||
if (pool == 1)
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) makeIdle: (SQLClient*)c
|
|
||||||
{
|
|
||||||
if (NSHashGet(idle, (void*)c) == (void*)c)
|
|
||||||
{
|
|
||||||
return YES; // Already idle
|
|
||||||
}
|
|
||||||
if (NSHashGet(used, (void*)c) == (void*)c)
|
|
||||||
{
|
|
||||||
NSHashRemove(used, (void*)c);
|
|
||||||
}
|
|
||||||
if (NSCountHashTable(idle) + NSCountHashTable(used) < pool)
|
|
||||||
{
|
|
||||||
NSHashInsert(idle, (void*)c);
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) makeUsed: (SQLClient*)c
|
|
||||||
{
|
|
||||||
if (NSHashGet(used, (void*)c) == (void*)c)
|
|
||||||
{
|
|
||||||
return YES; // Already used
|
|
||||||
}
|
|
||||||
if (NSHashGet(idle, (void*)c) == (void*)c)
|
|
||||||
{
|
|
||||||
NSHashRemove(idle, (void*)c);
|
|
||||||
}
|
|
||||||
if (NSCountHashTable(idle) + NSCountHashTable(used) < pool)
|
|
||||||
{
|
|
||||||
NSHashInsert(used, (void*)c);
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setConfiguration: (NSDictionary*)o
|
|
||||||
{
|
|
||||||
NSDictionary *d;
|
|
||||||
NSString *s;
|
|
||||||
BOOL change = NO;
|
|
||||||
int capacity;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get dictionary containing config info for this client by name.
|
|
||||||
*/
|
|
||||||
d = [o objectForKey: @"SQLClientReferences"];
|
|
||||||
if ([d isKindOfClass: [NSDictionary class]] == NO)
|
|
||||||
{
|
|
||||||
d = nil;
|
|
||||||
}
|
|
||||||
d = [d objectForKey: name];
|
|
||||||
if ([d isKindOfClass: [NSDictionary class]] == NO)
|
|
||||||
{
|
|
||||||
d = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = [d objectForKey: @"ServerType"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = @"Postgres";
|
|
||||||
}
|
|
||||||
if (s != serv && [s isEqual: serv] == NO)
|
|
||||||
{
|
|
||||||
s = [s copy];
|
|
||||||
[serv release];
|
|
||||||
serv = s;
|
|
||||||
change = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = [d objectForKey: @"Database"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = [o objectForKey: @"Database"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = nil;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s != path && [s isEqual: path] == NO)
|
|
||||||
{
|
|
||||||
s = [s copy];
|
|
||||||
[path release];
|
|
||||||
path = s;
|
|
||||||
change = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = [d objectForKey: @"User"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = [o objectForKey: @"User"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s != user && [s isEqual: user] == NO)
|
|
||||||
{
|
|
||||||
s = [s copy];
|
|
||||||
[user release];
|
|
||||||
user = s;
|
|
||||||
change = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = [d objectForKey: @"Password"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = [o objectForKey: @"Password"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = @"";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s != pass && [s isEqual: pass] == NO)
|
|
||||||
{
|
|
||||||
s = [s copy];
|
|
||||||
[pass release];
|
|
||||||
pass = s;
|
|
||||||
change = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = [d objectForKey: @"Password"];
|
|
||||||
if ([s isKindOfClass: NSStringClass] == NO)
|
|
||||||
{
|
|
||||||
s = @"1";
|
|
||||||
}
|
|
||||||
capacity = [s intValue];
|
|
||||||
if (capacity < 1) capacity = 1;
|
|
||||||
if (capacity > 100) capacity = 100;
|
|
||||||
|
|
||||||
if (change == YES)
|
|
||||||
{
|
|
||||||
NSResetHashTable(idle);
|
|
||||||
NSResetHashTable(used);
|
|
||||||
}
|
|
||||||
if (pool > capacity)
|
|
||||||
{
|
|
||||||
unsigned ic = NSCountHashTable(idle);
|
|
||||||
unsigned uc = NSCountHashTable(used);
|
|
||||||
|
|
||||||
if (ic + uc > capacity)
|
|
||||||
{
|
|
||||||
NSHashEnumerator e = NSEnumerateHashTable(idle);
|
|
||||||
void *c;
|
|
||||||
|
|
||||||
while (ic + uc > capacity
|
|
||||||
&& (c = NSNextHashEnumeratorItem(&e)) != nil)
|
|
||||||
{
|
|
||||||
NSHashRemove(idle, c);
|
|
||||||
ic--;
|
|
||||||
}
|
|
||||||
NSEndHashTableEnumeration(&e);
|
|
||||||
if (uc > capacity)
|
|
||||||
{
|
|
||||||
NSHashEnumerator e = NSEnumerateHashTable(used);
|
|
||||||
void *c;
|
|
||||||
|
|
||||||
while (uc > capacity
|
|
||||||
&& (c = NSNextHashEnumeratorItem(&e)) != nil)
|
|
||||||
{
|
|
||||||
NSHashRemove(used, c);
|
|
||||||
uc--;
|
|
||||||
}
|
|
||||||
NSEndHashTableEnumeration(&e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pool = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Class aClass = 0;
|
static Class aClass = 0;
|
||||||
static Class rClass = 0;
|
static Class rClass = 0;
|
||||||
|
|
||||||
|
@ -866,8 +635,9 @@ static NSTimeInterval classDuration = -1;
|
||||||
/**
|
/**
|
||||||
* Container for all instances.
|
* Container for all instances.
|
||||||
*/
|
*/
|
||||||
|
static NSHashTable *clientsHash = 0;
|
||||||
static NSMapTable *clientsMap = 0;
|
static NSMapTable *clientsMap = 0;
|
||||||
static NSRecursiveLock *clientsMapLock = nil;
|
static NSRecursiveLock *clientsLock = nil;
|
||||||
static NSString *beginString = @"begin";
|
static NSString *beginString = @"begin";
|
||||||
static NSArray *beginStatement = nil;
|
static NSArray *beginStatement = nil;
|
||||||
static NSString *commitString = @"commit";
|
static NSString *commitString = @"commit";
|
||||||
|
@ -898,11 +668,19 @@ static unsigned int maxConnections = 8;
|
||||||
|
|
||||||
+ (NSArray*) allClients
|
+ (NSArray*) allClients
|
||||||
{
|
{
|
||||||
NSArray *a;
|
NSMutableArray *a;
|
||||||
|
NSHashEnumerator e;
|
||||||
|
id o;
|
||||||
|
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
a = NSAllMapTableValues(clientsMap);
|
a = [NSMutableArray arrayWithCapacity: NSCountHashTable(clientsHash)];
|
||||||
[clientsMapLock unlock];
|
e = NSEnumerateHashTable(clientsHash);
|
||||||
|
while (nil != (o = (id)NSNextHashEnumeratorItem(&e)))
|
||||||
|
{
|
||||||
|
[a addObject: o];
|
||||||
|
}
|
||||||
|
NSEndHashTableEnumeration(&e);
|
||||||
|
[clientsLock unlock];
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,10 +729,10 @@ static unsigned int maxConnections = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
existing = (SQLClient*)NSMapGet(clientsMap, reference);
|
existing = (SQLClient*)NSMapGet(clientsMap, reference);
|
||||||
[[existing retain] autorelease];
|
[[existing retain] autorelease];
|
||||||
[clientsMapLock unlock];
|
[clientsLock unlock];
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,11 +744,12 @@ static unsigned int maxConnections = 8;
|
||||||
queryModes = [[NSArray alloc] initWithObjects: modes count: 1];
|
queryModes = [[NSArray alloc] initWithObjects: modes count: 1];
|
||||||
GSTickerTimeNow();
|
GSTickerTimeNow();
|
||||||
[SQLRecord class]; // Force initialisation
|
[SQLRecord class]; // Force initialisation
|
||||||
if (clientsMap == 0)
|
if (0 == clientsHash)
|
||||||
{
|
{
|
||||||
|
clientsHash = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
|
||||||
clientsMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
clientsMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
||||||
NSNonRetainedObjectMapValueCallBacks, 0);
|
NSNonRetainedObjectMapValueCallBacks, 0);
|
||||||
clientsMapLock = [NSRecursiveLock new];
|
clientsLock = [NSRecursiveLock new];
|
||||||
beginStatement = [[NSArray arrayWithObject: beginString] retain];
|
beginStatement = [[NSArray arrayWithObject: beginString] retain];
|
||||||
commitStatement = [[NSArray arrayWithObject: commitString] retain];
|
commitStatement = [[NSArray arrayWithObject: commitString] retain];
|
||||||
rollbackStatement = [[NSArray arrayWithObject: rollbackString] retain];
|
rollbackStatement = [[NSArray arrayWithObject: rollbackString] retain];
|
||||||
|
@ -992,15 +771,14 @@ static unsigned int maxConnections = 8;
|
||||||
|
|
||||||
+ (void) purgeConnections: (NSDate*)since
|
+ (void) purgeConnections: (NSDate*)since
|
||||||
{
|
{
|
||||||
NSMapEnumerator e;
|
NSHashEnumerator e;
|
||||||
NSString *n;
|
|
||||||
SQLClient *o;
|
SQLClient *o;
|
||||||
unsigned int connectionCount = 0;
|
unsigned int connectionCount = 0;
|
||||||
NSTimeInterval t = [since timeIntervalSinceReferenceDate];
|
NSTimeInterval t = [since timeIntervalSinceReferenceDate];
|
||||||
|
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
e = NSEnumerateMapTable(clientsMap);
|
e = NSEnumerateHashTable(clientsHash);
|
||||||
while (NSNextMapEnumeratorPair(&e, (void**)&n, (void**)&o) != 0)
|
while (nil != (o = (SQLClient*)NSNextHashEnumeratorItem(&e)))
|
||||||
{
|
{
|
||||||
if (since != nil)
|
if (since != nil)
|
||||||
{
|
{
|
||||||
|
@ -1016,8 +794,8 @@ static unsigned int maxConnections = 8;
|
||||||
connectionCount++;
|
connectionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NSEndMapTableEnumeration(&e);
|
NSEndHashTableEnumeration(&e);
|
||||||
[clientsMapLock unlock];
|
[clientsLock unlock];
|
||||||
|
|
||||||
while (connectionCount >= maxConnections)
|
while (connectionCount >= maxConnections)
|
||||||
{
|
{
|
||||||
|
@ -1025,9 +803,9 @@ static unsigned int maxConnections = 8;
|
||||||
NSTimeInterval oldest = 0.0;
|
NSTimeInterval oldest = 0.0;
|
||||||
|
|
||||||
connectionCount = 0;
|
connectionCount = 0;
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
e = NSEnumerateMapTable(clientsMap);
|
e = NSEnumerateHashTable(clientsHash);
|
||||||
while (NSNextMapEnumeratorPair(&e, (void**)&n, (void**)&o))
|
while (nil != (o = (SQLClient*)NSNextHashEnumeratorItem(&e)))
|
||||||
{
|
{
|
||||||
if ([o connected] == YES)
|
if ([o connected] == YES)
|
||||||
{
|
{
|
||||||
|
@ -1041,8 +819,8 @@ static unsigned int maxConnections = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NSEndMapTableEnumeration(&e);
|
NSEndHashTableEnumeration(&e);
|
||||||
[clientsMapLock unlock];
|
[clientsLock unlock];
|
||||||
connectionCount--;
|
connectionCount--;
|
||||||
if ([other debugging] > 0)
|
if ([other debugging] > 0)
|
||||||
{
|
{
|
||||||
|
@ -1233,12 +1011,13 @@ static unsigned int maxConnections = 8;
|
||||||
{
|
{
|
||||||
NSNotificationCenter *nc;
|
NSNotificationCenter *nc;
|
||||||
|
|
||||||
if (_name != nil)
|
[clientsLock lock];
|
||||||
|
NSHashRemove(clientsHash, (void*)self);
|
||||||
|
if (_name != nil && NO == _forUseInPool)
|
||||||
{
|
{
|
||||||
[clientsMapLock lock];
|
|
||||||
NSMapRemove(clientsMap, (void*)_name);
|
NSMapRemove(clientsMap, (void*)_name);
|
||||||
[clientsMapLock unlock];
|
|
||||||
}
|
}
|
||||||
|
[clientsLock unlock];
|
||||||
nc = [NSNotificationCenter defaultCenter];
|
nc = [NSNotificationCenter defaultCenter];
|
||||||
[nc removeObserver: self];
|
[nc removeObserver: self];
|
||||||
[self disconnect];
|
[self disconnect];
|
||||||
|
@ -1381,6 +1160,14 @@ static unsigned int maxConnections = 8;
|
||||||
|
|
||||||
- (id) initWithConfiguration: (NSDictionary*)config
|
- (id) initWithConfiguration: (NSDictionary*)config
|
||||||
name: (NSString*)reference
|
name: (NSString*)reference
|
||||||
|
{
|
||||||
|
return [self initWithConfiguration: config name: reference pool: NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (id) initWithConfiguration: (NSDictionary*)config
|
||||||
|
name: (NSString*)reference
|
||||||
|
pool: (BOOL)forUseInPool
|
||||||
{
|
{
|
||||||
NSNotification *n;
|
NSNotification *n;
|
||||||
NSDictionary *conf = config;
|
NSDictionary *conf = config;
|
||||||
|
@ -1401,8 +1188,16 @@ static unsigned int maxConnections = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
existing = (SQLClient*)NSMapGet(clientsMap, reference);
|
_forUseInPool = (NO == forUseInPool) ? NO : YES;
|
||||||
|
if (YES == _forUseInPool)
|
||||||
|
{
|
||||||
|
existing = (SQLClient*)NSMapGet(clientsMap, reference);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existing = nil;
|
||||||
|
}
|
||||||
if (nil == existing)
|
if (nil == existing)
|
||||||
{
|
{
|
||||||
lock = [NSRecursiveLock new]; // Ensure thread-safety.
|
lock = [NSRecursiveLock new]; // Ensure thread-safety.
|
||||||
|
@ -1426,6 +1221,7 @@ static unsigned int maxConnections = 8;
|
||||||
object: conf
|
object: conf
|
||||||
userInfo: nil];
|
userInfo: nil];
|
||||||
|
|
||||||
|
NSHashInsert(clientsHash, (void*)self);
|
||||||
[self _configure: n]; // Actually set up the configuration.
|
[self _configure: n]; // Actually set up the configuration.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1433,7 +1229,7 @@ static unsigned int maxConnections = 8;
|
||||||
[self release];
|
[self release];
|
||||||
self = [existing retain];
|
self = [existing retain];
|
||||||
}
|
}
|
||||||
[clientsMapLock unlock];
|
[clientsLock unlock];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -1733,12 +1529,12 @@ static unsigned int maxConnections = 8;
|
||||||
* it from the table so that no other thread will find it
|
* it from the table so that no other thread will find it
|
||||||
* and try to use it while it is being deallocated.
|
* and try to use it while it is being deallocated.
|
||||||
*/
|
*/
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
if (NSDecrementExtraRefCountWasZero(self))
|
if (NSDecrementExtraRefCountWasZero(self))
|
||||||
{
|
{
|
||||||
[self dealloc];
|
[self dealloc];
|
||||||
}
|
}
|
||||||
[clientsMapLock unlock];
|
[clientsLock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) rollback
|
- (void) rollback
|
||||||
|
@ -1803,24 +1599,27 @@ static unsigned int maxConnections = 8;
|
||||||
{
|
{
|
||||||
if ([s isEqual: _name] == NO)
|
if ([s isEqual: _name] == NO)
|
||||||
{
|
{
|
||||||
[clientsMapLock lock];
|
[clientsLock lock];
|
||||||
if (NSMapGet(clientsMap, s) != 0)
|
if (NO == _forUseInPool)
|
||||||
{
|
{
|
||||||
[clientsMapLock unlock];
|
if (NSMapGet(clientsMap, s) != 0)
|
||||||
[lock unlock];
|
|
||||||
if ([self debugging] > 0)
|
|
||||||
{
|
{
|
||||||
[self debug: @"Error attempt to re-use client name %@", s];
|
[clientsLock unlock];
|
||||||
|
[lock unlock];
|
||||||
|
if ([self debugging] > 0)
|
||||||
|
{
|
||||||
|
[self
|
||||||
|
debug: @"Error attempt to re-use client name %@", s];
|
||||||
|
}
|
||||||
|
NS_VOIDRETURN;
|
||||||
}
|
}
|
||||||
NS_VOIDRETURN;
|
|
||||||
}
|
}
|
||||||
if (connected == YES)
|
if (connected == YES)
|
||||||
{
|
{
|
||||||
[self disconnect];
|
[self disconnect];
|
||||||
}
|
}
|
||||||
if (_name != nil)
|
if (NO == _forUseInPool && _name != nil)
|
||||||
{
|
{
|
||||||
[[self retain] autorelease];
|
|
||||||
NSMapRemove(clientsMap, (void*)_name);
|
NSMapRemove(clientsMap, (void*)_name);
|
||||||
}
|
}
|
||||||
s = [s copy];
|
s = [s copy];
|
||||||
|
@ -1828,8 +1627,11 @@ static unsigned int maxConnections = 8;
|
||||||
_name = s;
|
_name = s;
|
||||||
[_client release];
|
[_client release];
|
||||||
_client = [[[NSProcessInfo processInfo] globallyUniqueString] retain];
|
_client = [[[NSProcessInfo processInfo] globallyUniqueString] retain];
|
||||||
NSMapInsert(clientsMap, (void*)_name, (void*)self);
|
if (NO == _forUseInPool && _name != nil)
|
||||||
[clientsMapLock unlock];
|
{
|
||||||
|
NSMapInsert(clientsMap, (void*)_name, (void*)self);
|
||||||
|
}
|
||||||
|
[clientsLock unlock];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_HANDLER
|
NS_HANDLER
|
||||||
|
|
|
@ -42,6 +42,7 @@ int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||||
|
SQLClientPool *sp;
|
||||||
SQLClient *db;
|
SQLClient *db;
|
||||||
NSUserDefaults *defs;
|
NSUserDefaults *defs;
|
||||||
NSMutableArray *records;
|
NSMutableArray *records;
|
||||||
|
@ -68,7 +69,11 @@ main()
|
||||||
nil]
|
nil]
|
||||||
];
|
];
|
||||||
|
|
||||||
db = [SQLClient clientWithConfiguration: nil name: @"test"];
|
sp = [[SQLClientPool alloc] initWithConfiguration: nil
|
||||||
|
name: @"test"
|
||||||
|
max: 2
|
||||||
|
min: 1];
|
||||||
|
db = [[sp autorelease] provideClient];
|
||||||
|
|
||||||
l = [Logger new];
|
l = [Logger new];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver: l
|
[[NSNotificationCenter defaultCenter] addObserver: l
|
||||||
|
|
Loading…
Reference in a new issue