Skip to content

Commit

Permalink
Bug fixes, doc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ccgus committed Jun 24, 2011
1 parent 358f9c2 commit dfd8fb9
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 63 deletions.
8 changes: 4 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Internally, the `-execute*WithFormat:` methods are properly boxing things for yo

## Using FMDatabasePool and Thread Safety.

**Note:** This is preliminary and subject to change. Consider it experimental, but feel free to try it out and give me feedback. I'm also not a fan of the method names I've added (pullFromPool, pushTowardsPool, useDatabase:, useTransaction:) - if you've got better ideas of a name, let me know.
**Note:** This is preliminary and subject to change. Consider it experimental, but feel free to try it out and give me feedback. I'm also not a fan of the method names I've added (useDatabase:, useTransaction:) - if you've got better ideas of a name, let me know.

Using a single instance of FMDatabase from multiple threads at once is not supported. Bad things will eventually happen and you'll eventually get something to crash, or maybe get an exception, or maybe meteorites will fall out of the sky and hit your Mac Pro. *This would suck*.

Expand Down Expand Up @@ -143,14 +143,14 @@ When the result set is exhausted or [rs close] is called, the result set will te

If you'd rather use multiple queries without having to call [pool db] each time, you can grab a database instance, tell it to stay out of the pool, and then tell it to go back in the pool when you're done:

FMDatabase *db = [[pool db] pullFromPool];
FMDatabase *db = [[pool db] popFromPool];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
// put the database back in the pool.
[db pushTowardsPool];
[db pushToPool];

Alternatively, you can use this nifty block based approach:

Expand Down Expand Up @@ -189,7 +189,7 @@ If you check out a database, but never execute a statement or query, **you need
// lala, don't do anything with the database
// oh look, I BETTER PUT THE DB BACK IN THE POOL OR ELSE IT IS GOING TO LEAK:
[db pushTowardsPool];
[db pushToPool];



Expand Down
8 changes: 5 additions & 3 deletions src/FMDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
BOOL _shouldCacheStatements;
BOOL _inUse;
int _busyRetryTimeout;
NSInteger _keepOutOfPoolCount;



NSMutableDictionary *_cachedStatements;
NSMutableSet *_openResultSets;

FMDatabasePool *_pool;
NSInteger _poolPopCount;
}


Expand Down Expand Up @@ -84,8 +86,8 @@

- (int)changes;

- (FMDatabase*)pullFromPool;
- (void)pushTowardsPool;
- (FMDatabase*)popFromPool;
- (void)pushToPool;


@end
Expand Down
69 changes: 34 additions & 35 deletions src/FMDatabase.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

@interface FMDatabase ()

- (void)pushInPoolIfClose;
- (void)checkPoolPushBack;
- (BOOL)inUse;
- (void)setInUse:(BOOL)b;

Expand Down Expand Up @@ -176,8 +176,7 @@ - (void)resultSetDidClose:(FMResultSet *)resultSet {

[_openResultSets removeObject:setValue];

[self pushInPoolIfClose];

[self checkPoolPushBack];
}

- (FMStatement*)cachedStatementForQuery:(NSString*)query {
Expand Down Expand Up @@ -295,11 +294,11 @@ - (sqlite_int64)lastInsertRowId {
return NO;
}

[self setInUse:YES];
_inUse = YES;

sqlite_int64 ret = sqlite3_last_insert_rowid(_db);

[self setInUse:NO];
_inUse = NO;

return ret;
}
Expand All @@ -310,11 +309,11 @@ - (int)changes {
return 0;
}

[self setInUse:YES];
_inUse = YES;

int ret = sqlite3_changes(_db);

[self setInUse:NO];
_inUse = NO;

return ret;
}
Expand Down Expand Up @@ -361,7 +360,7 @@ - (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt {
}
}

- (void)_extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments {
- (void)extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments {

NSUInteger length = [sql length];
unichar last = '\0';
Expand Down Expand Up @@ -474,8 +473,8 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
}

if (_inUse) {
[self pushTowardsPool];
[self warnInUse];
[self checkPoolPushBack];
return 0x00;
}

Expand Down Expand Up @@ -512,7 +511,7 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return nil;
}
}
Expand All @@ -530,7 +529,7 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr

sqlite3_finalize(pStmt);
[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return nil;
}
}
Expand Down Expand Up @@ -563,7 +562,7 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
sqlite3_finalize(pStmt);
[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return nil;
}

Expand Down Expand Up @@ -610,7 +609,7 @@ - (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... {

NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]];
NSMutableArray *arguments = [NSMutableArray array];
[self _extractSQL:format argumentsList:args intoString:sql arguments:arguments];
[self extractSQL:format argumentsList:args intoString:sql arguments:arguments];

va_end(args);

Expand All @@ -624,12 +623,12 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)ar
- (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args {

if (![self databaseExists]) {
[self pushTowardsPool];
[self checkPoolPushBack];
return NO;
}

if (_inUse) {
[self pushTowardsPool];
[self checkPoolPushBack];
[self warnInUse];
return NO;
}
Expand Down Expand Up @@ -666,7 +665,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return NO;
}
}
Expand All @@ -689,7 +688,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}

[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return NO;
}
}
Expand Down Expand Up @@ -722,7 +721,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
NSLog(@"Error: the bind count is not correct for the # of variables (%@) (executeUpdate)", sql);
sqlite3_finalize(pStmt);
[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return NO;
}

Expand Down Expand Up @@ -798,7 +797,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}

[self setInUse:NO];
[self pushTowardsPool];
[self checkPoolPushBack];
return (rc == SQLITE_OK);
}

Expand All @@ -824,7 +823,7 @@ - (BOOL)executeUpdateWithFormat:(NSString*)format, ... {
NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]];
NSMutableArray *arguments = [NSMutableArray array];

[self _extractSQL:format argumentsList:args intoString:sql arguments:arguments];
[self extractSQL:format argumentsList:args intoString:sql arguments:arguments];

va_end(args);

Expand All @@ -847,7 +846,7 @@ - (BOOL)rollback {
_inTransaction = NO;
}

[self pushInPoolIfClose];
[self pushToPool];

return b;
}
Expand All @@ -858,15 +857,15 @@ - (BOOL)commit {
_inTransaction = NO;
}

[self pushInPoolIfClose];
[self pushToPool];

return b;
}

- (BOOL)beginDeferredTransaction {

if (_pool) {
[self pullFromPool];
[self popFromPool];
}

BOOL b = [self executeUpdate:@"BEGIN DEFERRED TRANSACTION;"];
Expand All @@ -880,15 +879,14 @@ - (BOOL)beginDeferredTransaction {
- (BOOL)beginTransaction {

if (_pool) {
[self pullFromPool];
[self popFromPool];
}

BOOL b = [self executeUpdate:@"BEGIN EXCLUSIVE TRANSACTION;"];
if (b) {
_inTransaction = YES;


}

return b;
}

Expand Down Expand Up @@ -917,35 +915,36 @@ - (void)setShouldCacheStatements:(BOOL)value {
}
}

- (FMDatabase*)pullFromPool {
- (FMDatabase*)popFromPool {

if (!_pool) {
NSLog(@"No FMDatabasePool in place for %@", self);
return 0x00;
}

_keepOutOfPoolCount++;
_poolPopCount++;

return self;
}

- (void)pushTowardsPool {
_keepOutOfPoolCount--;
- (void)pushToPool {
_poolPopCount--;

[self pushInPoolIfClose];
[self checkPoolPushBack];
}

- (void)pushInPoolIfClose {
- (void)checkPoolPushBack {

if (_keepOutOfPoolCount <= 0) {
if (_poolPopCount <= 0) {
[_pool pushDatabaseBackInPool:self];

if (_keepOutOfPoolCount < 0) {
_keepOutOfPoolCount = 0;
if (_poolPopCount < 0) {
_poolPopCount = 0;
}
}
}


@end


Expand Down
2 changes: 2 additions & 0 deletions src/FMDatabasePool.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
- (void)pushDatabaseBackInPool:(FMDatabase*)db;
- (FMDatabase*)db;

- (NSUInteger)countOfCheckedInDatabases;
- (NSUInteger)countOfCheckedOutDatabases;
- (NSUInteger)countOfOpenDatabases;
- (void)releaseAllDatabases;

Expand Down
28 changes: 25 additions & 3 deletions src/FMDatabasePool.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ - (FMDatabase*)db {
}

db = [FMDatabase databaseWithPath:_path];

if ([db open]) {

if ([_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![_delegate databasePool:self shouldAddDatabaseToPool:db]) {
[db close];
db = 0x00;
Expand All @@ -115,6 +115,28 @@ - (FMDatabase*)db {
return db;
}

- (NSUInteger)countOfCheckedInDatabases {

__block NSInteger count;

[self executeLocked:^() {
count = [_databaseInPool count];
}];

return count;
}

- (NSUInteger)countOfCheckedOutDatabases {

__block NSInteger count;

[self executeLocked:^() {
count = [_databaseOutPool count];
}];

return count;
}

- (NSUInteger)countOfOpenDatabases {
__block NSInteger count;

Expand All @@ -134,11 +156,11 @@ - (void)releaseAllDatabases {

- (void)useDatabase:(void (^)(FMDatabase *db))block {

FMDatabase *db = [[self db] pullFromPool];
FMDatabase *db = [[self db] popFromPool];

block(db);

[db pushTowardsPool];
[db pushToPool];
}

- (void)useTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
Expand Down
Loading

0 comments on commit dfd8fb9

Please sign in to comment.