|
// |
|
// VSTagAuthoritySQL.m |
|
// Vesper |
|
// |
|
// Created by Brent Simmons on 2/28/14. |
|
// Copyright (c) 2014 Q Branch LLC. All rights reserved. |
|
// |
|
|
|
#import <libkern/OSAtomic.h> |
|
#import "VSTagAuthoritySQL.h" |
|
#import "QSDatabaseQueue.h" |
|
#import "FMDatabase.h" |
|
|
|
|
|
@interface VSTagAuthoritySQL () |
|
|
|
@property (nonatomic, readonly) QSDatabaseQueue *databaseQueue; |
|
@property (nonatomic, readonly) NSMutableDictionary *tags; |
|
|
|
@end |
|
|
|
|
|
static OSSpinLock tagsLock = OS_SPINLOCK_INIT; |
|
|
|
@implementation VSTagAuthoritySQL |
|
|
|
|
|
#pragma mark - Init |
|
|
|
- (instancetype)initWithDatabaseQueue:(QSDatabaseQueue *)databaseQueue { |
|
|
|
self = [super init]; |
|
if (self == nil) { |
|
return self; |
|
} |
|
|
|
_databaseQueue = databaseQueue; |
|
_tags = [NSMutableDictionary new]; |
|
[self fetchTags]; |
|
|
|
return self; |
|
} |
|
|
|
|
|
#pragma mark - Database |
|
|
|
static NSString *VSTagNameKey = @"name"; |
|
static NSString *VSTagClientIDKey = @"clientID"; |
|
|
|
- (void)fetchTags { |
|
|
|
OSSpinLockLock(&tagsLock); |
|
|
|
[self.databaseQueue fetch:^(FMDatabase *database) { |
|
|
|
FMResultSet *rs = [database executeQuery:@"select name, clientID from tags;"]; |
|
while ([rs next]) { |
|
|
|
/*In real life there would be a +VSTag tagWithResultSet: method. |
|
This is just to illustrate.*/ |
|
|
|
VSTag *oneTag = [VSTag new]; |
|
oneTag.name = [rs stringForColumn:VSTagNameKey]; |
|
oneTag.clientID = [rs stringForColumn:VSTagClientIDKey]; |
|
|
|
self.tags[oneTag.clientID] = oneTag; |
|
} |
|
|
|
OSSpinLockUnlock(&tagsLock); |
|
}]; |
|
} |
|
|
|
|
|
- (void)insertTagInDatabase:(VSTag *)tag { |
|
|
|
/*In real life there would be a |
|
-[VSTag insertInDatabase:(QSDatabaseQueue *)queue] method.*/ |
|
|
|
NSString *name = tag.name; |
|
NSString *clientID = tag.clientID; |
|
|
|
[self.databaseQueue update:^(FMDatabase *database) { |
|
|
|
[database executeUpdate:@"insert into tags (name, clientID) values (?, ?);", name, clientID]; |
|
}]; |
|
} |
|
|
|
|
|
#pragma mark - API |
|
|
|
- (VSTag *)existingTagWithName:(NSString *)name { |
|
|
|
NSParameterAssert(name != nil && [name length] > 0); |
|
|
|
NSString *clientID = [VSTag clientIDForTagName:name]; |
|
|
|
OSSpinLockLock(&tagsLock); |
|
VSTag *tag = self.tags[clientID]; |
|
OSSpinLockUnlock(&tagsLock); |
|
|
|
return tag; |
|
} |
|
|
|
|
|
- (VSTag *)tagWithName:(NSString *)name { |
|
|
|
NSParameterAssert(name != nil && [name length] > 0); |
|
|
|
NSString *clientID = [VSTag clientIDForTagName:name]; |
|
|
|
OSSpinLockLock(&tagsLock); |
|
VSTag *tag = self.tags[clientID]; |
|
|
|
if (!tag) { |
|
tag = [VSTag new]; |
|
tag.name = name; |
|
tag.clientID = clientID; |
|
|
|
self.tags[clientID] = tag; |
|
[self insertTagInDatabase:tag]; |
|
} |
|
|
|
OSSpinLockUnlock(&tagsLock); |
|
|
|
return tag; |
|
} |
|
|
|
@end |