mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-20 18:32:06 +00:00
thread-safety fixup
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38110 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
1ebf4e67b8
commit
94f90586bb
2 changed files with 63 additions and 27 deletions
|
@ -1,3 +1,10 @@
|
|||
2014-10-07 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* SQLClient.m: Add locking of the database client by SQLTransaction
|
||||
in case another thread tries to use the client whjile the transaction
|
||||
is using it (ie between an attempted transaction and a rollback if
|
||||
it fails).
|
||||
|
||||
2014-10-02 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* SQLClient.m: On exception during SQLTransaction -execute, roll back.
|
||||
|
|
83
SQLClient.m
83
SQLClient.m
|
@ -648,12 +648,53 @@ static NSArray *rollbackStatement = nil;
|
|||
|
||||
|
||||
@interface SQLClient (Private)
|
||||
|
||||
/**
|
||||
* Internal method to handle configuration using the notification object.
|
||||
* This object may be either a configuration front end or a user defaults
|
||||
* object ... so we have to be careful that we work with both.
|
||||
*/
|
||||
- (void) _configure: (NSNotification*)n;
|
||||
|
||||
/** Internal method to make the client instance lock available to
|
||||
* an associated SQLTransaction
|
||||
*/
|
||||
- (NSRecursiveLock*) _lock;
|
||||
|
||||
/** Internal method to populate the cache with the result of a query.
|
||||
*/
|
||||
- (void) _populateCache: (CacheQuery*)a;
|
||||
|
||||
/**
|
||||
* Internal method to build an sql string by quoting any non-string objects
|
||||
* and concatenating the resulting strings in a nil terminated list.<br />
|
||||
* Returns an array containing the statement as the first object and
|
||||
* any NSData objects following. The NSData objects appear in the
|
||||
* statement strings as the marker sequence - <code>'?'''?'</code>
|
||||
*/
|
||||
- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args;
|
||||
|
||||
/** Internal method called to record the 'main' thread in which automated
|
||||
* cache updates are to be performed.
|
||||
*/
|
||||
- (void) _recordMainThread;
|
||||
|
||||
/**
|
||||
* Internal method to substitute values from the dictionary into
|
||||
* a string containing markup identifying where the values should
|
||||
* appear by name. Non-string objects in the dictionary are quoted.<br />
|
||||
* Returns an array containing the statement as the first object and
|
||||
* any NSData objects following. The NSData objects appear in the
|
||||
* statement strings as the marker sequence - <code>'?'''?'</code>
|
||||
*/
|
||||
- (NSMutableArray*) _substitute: (NSString*)str with: (NSDictionary*)vals;
|
||||
|
||||
/*
|
||||
* Called at one second intervals to ensure that our current timestamp
|
||||
* is reasonably accurate.
|
||||
*/
|
||||
+ (void) _tick: (NSTimer*)t;
|
||||
|
||||
@end
|
||||
|
||||
@interface SQLClient (GSCacheDelegate)
|
||||
|
@ -2041,11 +2082,6 @@ static unsigned int maxConnections = 8;
|
|||
|
||||
@implementation SQLClient (Private)
|
||||
|
||||
/**
|
||||
* Internal method to handle configuration using the notification object.
|
||||
* This object may be either a configuration front end or a user defaults
|
||||
* object ... so we have to be careful that we work with both.
|
||||
*/
|
||||
- (void) _configure: (NSNotification*)n
|
||||
{
|
||||
NSDictionary *o;
|
||||
|
@ -2203,8 +2239,11 @@ static unsigned int maxConnections = 8;
|
|||
[lock unlock];
|
||||
}
|
||||
|
||||
/** Internal method to populate the cache with the result of a query.
|
||||
*/
|
||||
- (NSRecursiveLock*) _lock
|
||||
{
|
||||
return lock;
|
||||
}
|
||||
|
||||
- (void) _populateCache: (CacheQuery*)a
|
||||
{
|
||||
GSCache *cache;
|
||||
|
@ -2232,13 +2271,6 @@ static unsigned int maxConnections = 8;
|
|||
lifetime: a->lifetime];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to build an sql string by quoting any non-string objects
|
||||
* and concatenating the resulting strings in a nil terminated list.<br />
|
||||
* Returns an array containing the statement as the first object and
|
||||
* any NSData objects following. The NSData objects appear in the
|
||||
* statement strings as the marker sequence - <code>'?'''?'</code>
|
||||
*/
|
||||
- (NSMutableArray*) _prepare: (NSString*)stmt args: (va_list)args
|
||||
{
|
||||
NSMutableArray *ma = [NSMutableArray arrayWithCapacity: 2];
|
||||
|
@ -2285,14 +2317,6 @@ static unsigned int maxConnections = 8;
|
|||
mainThread = [NSThread currentThread];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to substitute values from the dictionary into
|
||||
* a string containing markup identifying where the values should
|
||||
* appear by name. Non-string objects in the dictionary are quoted.<br />
|
||||
* Returns an array containing the statement as the first object and
|
||||
* any NSData objects following. The NSData objects appear in the
|
||||
* statement strings as the marker sequence - <code>'?'''?'</code>
|
||||
*/
|
||||
- (NSMutableArray*) _substitute: (NSString*)str with: (NSDictionary*)vals
|
||||
{
|
||||
unsigned int l = [str length];
|
||||
|
@ -2467,10 +2491,6 @@ static unsigned int maxConnections = 8;
|
|||
return ma;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called at one second intervals to ensure that our current timestamp
|
||||
* is reasonably accurate.
|
||||
*/
|
||||
+ (void) _tick: (NSTimer*)t
|
||||
{
|
||||
(void) GSTickerTimeNow();
|
||||
|
@ -3201,8 +3221,11 @@ static unsigned int maxConnections = 8;
|
|||
if (_count > 0)
|
||||
{
|
||||
NSMutableArray *info = nil;
|
||||
BOOL wrap = [_db isInTransaction] ? NO : YES;
|
||||
NSRecursiveLock *dbLock = [_db _lock];
|
||||
BOOL wrap;
|
||||
|
||||
[dbLock lock];
|
||||
wrap = [_db isInTransaction] ? NO : YES;
|
||||
NS_DURING
|
||||
{
|
||||
NSMutableString *sql;
|
||||
|
@ -3231,6 +3254,7 @@ static unsigned int maxConnections = 8;
|
|||
|
||||
[_db simpleExecute: info];
|
||||
[info release]; info = nil;
|
||||
[dbLock unlock];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
|
@ -3250,6 +3274,7 @@ static unsigned int maxConnections = 8;
|
|||
}
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
[dbLock unlock];
|
||||
[e raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
@ -3268,6 +3293,9 @@ static unsigned int maxConnections = 8;
|
|||
|
||||
if (_count > 0)
|
||||
{
|
||||
NSRecursiveLock *dbLock = [_db _lock];
|
||||
|
||||
[dbLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
[self execute];
|
||||
|
@ -3370,6 +3398,7 @@ static unsigned int maxConnections = 8;
|
|||
}
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[dbLock unlock];
|
||||
}
|
||||
return executed;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue