Permalink
Browse files

Bug fixes, doc updates

  • Loading branch information...
1 parent 358f9c2 commit dfd8fb99ed3562f2b6542a3f9e6c5466bcf122cc @ccgus ccgus committed Jun 24, 2011
Showing with 132 additions and 63 deletions.
  1. +4 −4 README.markdown
  2. +5 −3 src/FMDatabase.h
  3. +34 −35 src/FMDatabase.m
  4. +2 −0 src/FMDatabasePool.h
  5. +25 −3 src/FMDatabasePool.m
  6. +62 −18 src/fmdb.m
View
@@ -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*.
@@ -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:
@@ -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];
View
@@ -15,12 +15,14 @@
BOOL _shouldCacheStatements;
BOOL _inUse;
int _busyRetryTimeout;
- NSInteger _keepOutOfPoolCount;
+
+
NSMutableDictionary *_cachedStatements;
NSMutableSet *_openResultSets;
FMDatabasePool *_pool;
+ NSInteger _poolPopCount;
}
@@ -84,8 +86,8 @@
- (int)changes;
-- (FMDatabase*)pullFromPool;
-- (void)pushTowardsPool;
+- (FMDatabase*)popFromPool;
+- (void)pushToPool;
@end
View
@@ -3,7 +3,7 @@
@interface FMDatabase ()
-- (void)pushInPoolIfClose;
+- (void)checkPoolPushBack;
- (BOOL)inUse;
- (void)setInUse:(BOOL)b;
@@ -176,8 +176,7 @@ - (void)resultSetDidClose:(FMResultSet *)resultSet {
[_openResultSets removeObject:setValue];
- [self pushInPoolIfClose];
-
+ [self checkPoolPushBack];
}
- (FMStatement*)cachedStatementForQuery:(NSString*)query {
@@ -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;
}
@@ -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;
}
@@ -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';
@@ -474,8 +473,8 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
}
if (_inUse) {
- [self pushTowardsPool];
[self warnInUse];
+ [self checkPoolPushBack];
return 0x00;
}
@@ -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;
}
}
@@ -530,7 +529,7 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr
sqlite3_finalize(pStmt);
[self setInUse:NO];
- [self pushTowardsPool];
+ [self checkPoolPushBack];
return nil;
}
}
@@ -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;
}
@@ -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);
@@ -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;
}
@@ -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;
}
}
@@ -689,7 +688,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}
[self setInUse:NO];
- [self pushTowardsPool];
+ [self checkPoolPushBack];
return NO;
}
}
@@ -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;
}
@@ -798,7 +797,7 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
}
[self setInUse:NO];
- [self pushTowardsPool];
+ [self checkPoolPushBack];
return (rc == SQLITE_OK);
}
@@ -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);
@@ -847,7 +846,7 @@ - (BOOL)rollback {
_inTransaction = NO;
}
- [self pushInPoolIfClose];
+ [self pushToPool];
return b;
}
@@ -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;"];
@@ -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;
}
@@ -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
@@ -33,6 +33,8 @@
- (void)pushDatabaseBackInPool:(FMDatabase*)db;
- (FMDatabase*)db;
+- (NSUInteger)countOfCheckedInDatabases;
+- (NSUInteger)countOfCheckedOutDatabases;
- (NSUInteger)countOfOpenDatabases;
- (void)releaseAllDatabases;
View
@@ -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;
@@ -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;
@@ -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 {
Oops, something went wrong.

0 comments on commit dfd8fb9

Please sign in to comment.