Authored by Thomas Rasch

o Moved RMTileCacheDAO into RMDatabaseCache

... ... @@ -98,11 +98,14 @@
@interface RMDBMapSource(PrivateMethods)
- (NSString *)getPreferenceAsString:(NSString *)name;
- (float)getPreferenceAsFloat:(NSString *)name;
- (int)getPreferenceAsInt:(NSString *)name;
@end
#pragma mark -
@implementation RMDBMapSource
... ... @@ -197,7 +200,7 @@
UIImage *image = nil;
if ([result next]) {
image = [[[UIImage alloc] initWithData:[result dataNoCopyForColumn:@"image"]] autorelease];
image = [[[UIImage alloc] initWithData:[result dataForColumn:@"image"]] autorelease];
} else {
image = [RMTileImage missingTile];
}
... ...
... ... @@ -29,10 +29,18 @@
#import "RMTileCache.h"
@class RMTileCacheDAO;
@class FMDatabase;
@interface RMDatabaseCache : NSObject <RMTileCache> {
// Database
FMDatabase* db;
NSString *databasePath;
RMTileCacheDAO *dao;
NSUInteger tileCount;
NSOperationQueue *writeQueue;
NSRecursiveLock *writeQueueLock;
// Cache
RMCachePurgeStrategy purgeStrategy;
NSUInteger capacity;
NSUInteger minimalPurge;
... ...
... ... @@ -26,10 +26,23 @@
// POSSIBILITY OF SUCH DAMAGE.
#import "RMDatabaseCache.h"
#import "RMTileCacheDAO.h"
#import "FMDatabase.h"
#import "RMTileImage.h"
#import "RMTile.h"
#define kWriteQueueLimit 25
@interface RMDatabaseCache ()
- (NSUInteger)count;
- (NSUInteger)countTiles;
- (void)touchTile:(RMTile)tile withKey:(NSString *)cacheKey;
- (void)purgeTiles:(NSUInteger)count;
@end
#pragma mark -
@implementation RMDatabaseCache
@synthesize databasePath;
... ... @@ -62,20 +75,45 @@
return nil;
}
- (void)configureDBForFirstUse
{
[db executeQuery:@"PRAGMA synchronous=OFF"];
[db executeQuery:@"PRAGMA journal_mode=OFF"];
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS ZCACHE (tile_hash INTEGER NOT NULL, cache_key VARCHAR(25) NOT NULL, last_used DOUBLE NOT NULL, data BLOB NOT NULL)"];
[db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS main_index ON ZCACHE(tile_hash, cache_key)"];
[db executeUpdate:@"CREATE INDEX IF NOT EXISTS last_used_index ON ZCACHE(last_used)"];
}
- (id)initWithDatabase:(NSString *)path
{
if (!(self = [super init]))
return nil;
self.databasePath = path;
dao = [[RMTileCacheDAO alloc] initWithDatabase:path];
if (!dao) {
writeQueue = [NSOperationQueue new];
[writeQueue setMaxConcurrentOperationCount:1];
writeQueueLock = [NSRecursiveLock new];
RMLog(@"Opening database at %@", path);
db = [[FMDatabase alloc] initWithPath:path];
if (![db open])
{
RMLog(@"Could not connect to database - %@", [db lastErrorMessage]);
[[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
dao = [[RMTileCacheDAO alloc] initWithDatabase:path];
}
if (![db open]) {
[self release];
return nil;
}
}
if (dao == nil)
return nil;
[db setCrashOnErrors:TRUE];
[db setShouldCacheStatements:TRUE];
[self configureDBForFirstUse];
tileCount = [self countTiles];
return self;
}
... ... @@ -88,7 +126,11 @@
- (void)dealloc
{
self.databasePath = nil;
[dao release]; dao = nil;
[writeQueueLock lock];
[writeQueue release]; writeQueue = nil;
[writeQueueLock unlock];
[writeQueueLock release]; writeQueueLock = nil;
[db close]; [db release]; db = nil;
[super dealloc];
}
... ... @@ -111,44 +153,142 @@
{
// RMLog(@"DB cache check for tile %d %d %d", tile.x, tile.y, tile.zoom);
NSData *data = [dao dataForTile:RMTileKey(tile) withKey:aCacheKey];
if (data == nil)
return nil;
[writeQueueLock lock];
FMResultSet *results = [db executeQuery:@"SELECT data FROM ZCACHE WHERE tile_hash = ? AND cache_key = ?", [RMTileCache tileHash:tile], aCacheKey];
if ([db hadError]) {
RMLog(@"DB error while fetching tile data: %@", [db lastErrorMessage]);
return nil;
}
NSData *data = nil;
UIImage *cachedImage = nil;
if ([results next]) {
data = [results dataForColumnIndex:0];
if (data) cachedImage = [UIImage imageWithData:data];
}
[results close];
[writeQueueLock unlock];
if (capacity != 0 && purgeStrategy == RMCachePurgeStrategyLRU) {
[dao touchTile:RMTileKey(tile) withKey:aCacheKey];
[self touchTile:tile withKey:aCacheKey];
}
// RMLog(@"DB cache hit tile %d %d %d (%@)", tile.x, tile.y, tile.zoom, [RMTileCache tileHash:tile]);
return [UIImage imageWithData:data];
return cachedImage;
}
- (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey
{
// TODO: Converting the image here (again) is not so good...
NSData *data = UIImagePNGRepresentation(image);
if (capacity != 0) {
NSUInteger tilesInDb = [dao count];
if (capacity != 0)
{
NSUInteger tilesInDb = [self count];
if (capacity <= tilesInDb) {
[dao purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
[self purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
}
// RMLog(@"DB cache insert tile %d %d %d (%@)", tile.x, tile.y, tile.zoom, [RMTileCache tileHash:tile]);
[dao addData:data forTile:RMTileKey(tile) withKey:aCacheKey];
// Don't add new images to the database while there are still more than kWriteQueueLimit
// insert operations pending. This prevents some memory issues.
if ([writeQueue operationCount] > kWriteQueueLimit) return;
[writeQueue addOperationWithBlock:^{
// RMLog(@"addData\t%d", tileHash);
[writeQueueLock lock];
BOOL result = [db executeUpdate:@"INSERT OR IGNORE INTO ZCACHE (tile_hash, cache_key, last_used, data) VALUES (?, ?, ?, ?)", [RMTileCache tileHash:tile], aCacheKey, [NSDate date], data];
[writeQueueLock unlock];
if (result == NO)
{
RMLog(@"Error occured adding data");
} else
tileCount++;
}];
}
}
- (void)didReceiveMemoryWarning
#pragma mark -
- (NSUInteger)count
{
return tileCount;
}
- (NSUInteger)countTiles
{
[writeQueueLock lock];
NSUInteger count = 0;
FMResultSet *results = [db executeQuery:@"SELECT COUNT(tile_hash) FROM ZCACHE"];
if ([results next])
count = [results intForColumnIndex:0];
else
RMLog(@"Unable to count columns");
[results close];
[writeQueueLock unlock];
return count;
}
- (void)purgeTiles:(NSUInteger)count
{
[dao didReceiveMemoryWarning];
RMLog(@"purging %u old tiles from db cache", count);
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedInt:count]];
[db executeQuery:@"VACUUM"];
tileCount = [self countTiles];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
}
- (void)removeAllCachedImages
{
[dao removeAllCachedImages];
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE"];
[db executeQuery:@"VACUUM"];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
tileCount = [self countTiles];
}];
}
- (void)touchTile:(RMTile)tile withKey:(NSString *)cacheKey
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"UPDATE ZCACHE SET last_used = ? WHERE tile_hash = ? AND cache_key = ?", [NSDate date], [RMTileCache tileHash:tile], cacheKey];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error touching tile");
}
}];
}
- (void)didReceiveMemoryWarning
{
RMLog(@"Low memory in the tilecache");
[writeQueue cancelAllOperations];
}
@end
... ...
... ... @@ -60,11 +60,11 @@
for (id cfg in cacheCfg)
{
id <RMTileCache> newCache = nil;
@try {
NSString *type = [cfg valueForKey:@"type"];
if ([@"memory-cache" isEqualToString:type]) {
memoryCache = [[self memoryCacheWithConfig:cfg] retain];
continue;
... ... @@ -188,7 +188,7 @@
NSUInteger capacity = 1000;
NSUInteger minimalPurge = capacity / 10;
NSNumber *capacityNumber = [cfg objectForKey:@"capacity"];
if (capacityNumber != nil) {
NSInteger value = [capacityNumber intValue];
... ... @@ -200,13 +200,13 @@
} else
RMLog(@"illegal value for capacity: %d", value);
}
NSString *strategyStr = [cfg objectForKey:@"strategy"];
if (strategyStr != nil) {
if ([strategyStr caseInsensitiveCompare:@"FIFO"] == NSOrderedSame) strategy = RMCachePurgeStrategyFIFO;
if ([strategyStr caseInsensitiveCompare:@"LRU"] == NSOrderedSame) strategy = RMCachePurgeStrategyLRU;
}
NSNumber *useCacheDirNumber = [cfg objectForKey:@"useCachesDirectory"];
if (useCacheDirNumber != nil)
useCacheDir = [useCacheDirNumber boolValue];
... ...
//
// DAO.h
//
// Copyright (c) 2008-2009, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import <UIKit/UIKit.h>
@class FMDatabase;
/// the interface between RMDatabaseCache and FMDB
@interface RMTileCacheDAO : NSObject {
FMDatabase* db;
NSUInteger tileCount;
NSOperationQueue *writeQueue;
NSRecursiveLock *writeQueueLock;
}
- (id)initWithDatabase:(NSString *)path;
- (NSUInteger)count;
- (NSData *)dataForTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)touchTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)addData:(NSData *)data forTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)purgeTiles:(NSUInteger)count;
- (void)removeAllCachedImages;
- (void)didReceiveMemoryWarning;
@end
//
// DAO.m
//
// Copyright (c) 2008-2009, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import "RMTileCacheDAO.h"
#import "FMDatabase.h"
#import "RMTileCache.h"
#import "RMTileImage.h"
#define kWriteQueueLimit 25
@interface RMTileCacheDAO ()
- (NSUInteger)countTiles;
@end
@implementation RMTileCacheDAO
- (void)configureDBForFirstUse
{
[db executeQuery:@"PRAGMA synchronous=OFF"];
[db executeQuery:@"PRAGMA journal_mode=OFF"];
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS ZCACHE (tile_hash INTEGER NOT NULL, cache_key VARCHAR(25) NOT NULL, last_used DOUBLE NOT NULL, data BLOB NOT NULL)"];
[db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS main_index ON ZCACHE(tile_hash, cache_key)"];
[db executeUpdate:@"CREATE INDEX IF NOT EXISTS last_used_index ON ZCACHE(last_used)"];
}
- (id)initWithDatabase:(NSString *)path
{
if (!(self = [super init]))
return nil;
writeQueue = [NSOperationQueue new];
[writeQueue setMaxConcurrentOperationCount:1];
writeQueueLock = [NSRecursiveLock new];
RMLog(@"Opening database at %@", path);
db = [[FMDatabase alloc] initWithPath:path];
if (![db open])
{
RMLog(@"Could not connect to database - %@", [db lastErrorMessage]);
return nil;
}
[db setCrashOnErrors:TRUE];
[db setShouldCacheStatements:TRUE];
[self configureDBForFirstUse];
tileCount = [self countTiles];
return self;
}
- (void)dealloc
{
LogMethod();
[writeQueueLock lock];
[writeQueue release]; writeQueue = nil;
[writeQueueLock unlock];
[writeQueueLock release]; writeQueueLock = nil;
[db close]; [db release]; db = nil;
[super dealloc];
}
- (NSUInteger)count
{
return tileCount;
}
- (NSUInteger)countTiles
{
[writeQueueLock lock];
NSUInteger count = 0;
FMResultSet *results = [db executeQuery:@"SELECT COUNT(tile_hash) FROM ZCACHE"];
if ([results next])
count = [results intForColumnIndex:0];
else
RMLog(@"Unable to count columns");
[results close];
[writeQueueLock unlock];
return count;
}
- (NSData *)dataForTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
[writeQueueLock lock];
FMResultSet *results = [db executeQuery:@"SELECT data FROM ZCACHE WHERE tile_hash = ? AND cache_key = ?", [NSNumber numberWithUnsignedLongLong:tileHash], cacheKey];
if ([db hadError]) {
RMLog(@"DB error while fetching tile data: %@", [db lastErrorMessage]);
return nil;
}
NSData *data = nil;
if ([results next])
// TODO: Would dataNoCopy work? What would we have to do?
data = [results dataForColumnIndex:0];
[results close];
[writeQueueLock unlock];
return data;
}
- (void)purgeTiles:(NSUInteger)count
{
RMLog(@"purging %u old tiles from db cache", count);
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedInt:count]];
[db executeQuery:@"VACUUM"];
tileCount = [self countTiles];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
}
- (void)removeAllCachedImages
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE"];
[db executeQuery:@"VACUUM"];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
tileCount = [self countTiles];
}];
}
- (void)touchTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"UPDATE ZCACHE SET last_used = ? WHERE tile_hash = ? AND cache_key = ?", [NSDate date], [NSNumber numberWithUnsignedInt:tileHash], cacheKey];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error touching tile");
}
}];
}
- (void)addData:(NSData *)data forTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
// Don't add new images to the database while there are still more than kWriteQueueLimit
// insert operations pending. This prevents some memory issues.
if ([writeQueue operationCount] > kWriteQueueLimit) return;
[writeQueue addOperationWithBlock:^{
// RMLog(@"addData\t%d", tileHash);
[writeQueueLock lock];
BOOL result = [db executeUpdate:@"INSERT OR IGNORE INTO ZCACHE (tile_hash, cache_key, last_used, data) VALUES (?, ?, ?, ?)", [NSNumber numberWithUnsignedLongLong:tileHash], cacheKey, [NSDate date], data];
[writeQueueLock unlock];
if (result == NO)
{
RMLog(@"Error occured adding data");
} else
tileCount++;
}];
}
- (void)didReceiveMemoryWarning
{
RMLog(@"Low memory in the tilecache");
[writeQueue cancelAllOperations];
}
@end
... ... @@ -130,7 +130,7 @@ static UIImage *_missingTile = nil;
- (void)updateWithImage:(UIImage *)image andNotify:(BOOL)notifyListeners
{
dispatch_async(dispatch_get_main_queue(),^ {
dispatch_async(dispatch_get_main_queue(), ^{
layer.contents = (id)[image CGImage];
});
... ...
... ... @@ -82,7 +82,6 @@
2BEC60490F8AC738008FB858 /* RMProjection.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64E40E80E73F001663B6 /* RMProjection.m */; };
2BEC604A0F8AC739008FB858 /* RMTile.c in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D70E80E73F001663B6 /* RMTile.c */; };
2BEC604B0F8AC73A008FB858 /* RMTileCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D10E80E73F001663B6 /* RMTileCache.m */; };
2BEC604C0F8AC73C008FB858 /* RMTileCacheDAO.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */; };
2BEC604E0F8AC73D008FB858 /* RMTileImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D90E80E73F001663B6 /* RMTileImage.m */; };
2BEC604F0F8AC73E008FB858 /* RMTileImageSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64E10E80E73F001663B6 /* RMTileImageSet.m */; };
2BEC60500F8AC73F008FB858 /* RMTileLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64C70E80E73F001663B6 /* RMTileLoader.m */; };
... ... @@ -105,8 +104,6 @@
B8474B9D0EB40094006A0BC1 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B900EB40094006A0BC1 /* FMDatabaseAdditions.m */; };
B8474B9F0EB40094006A0BC1 /* FMResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B920EB40094006A0BC1 /* FMResultSet.h */; };
B8474BA00EB40094006A0BC1 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B930EB40094006A0BC1 /* FMResultSet.m */; };
B8474BA20EB40094006A0BC1 /* RMTileCacheDAO.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */; };
B8474BA30EB40094006A0BC1 /* RMTileCacheDAO.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */; };
B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */; };
B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */; };
B8474BC10EB4019A006A0BC1 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */; };
... ... @@ -281,8 +278,6 @@
B8474B910EB40094006A0BC1 /* fmdb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fmdb.m; sourceTree = "<group>"; };
B8474B920EB40094006A0BC1 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = "<group>"; };
B8474B930EB40094006A0BC1 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = "<group>"; };
B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMTileCacheDAO.h; sourceTree = "<group>"; };
B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMTileCacheDAO.m; sourceTree = "<group>"; };
B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMDatabaseCache.h; sourceTree = "<group>"; };
B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMDatabaseCache.m; sourceTree = "<group>"; };
B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
... ... @@ -531,7 +526,6 @@
B83E64D30E80E73F001663B6 /* RMMemoryCache.m */,
B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */,
B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */,
B8474B940EB40094006A0BC1 /* Database */,
);
name = "Tile Cache";
sourceTree = "<group>";
... ... @@ -587,16 +581,6 @@
path = FMDB;
sourceTree = "<group>";
};
B8474B940EB40094006A0BC1 /* Database */ = {
isa = PBXGroup;
children = (
B8474B8C0EB40094006A0BC1 /* FMDB */,
B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */,
B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */,
);
name = Database;
sourceTree = "<group>";
};
B8474C610EB53A01006A0BC1 /* Resources */ = {
isa = PBXGroup;
children = (
... ... @@ -633,6 +617,7 @@
isa = PBXGroup;
children = (
175701DB1323C2CF00A5D314 /* iOS Additions */,
B8474B8C0EB40094006A0BC1 /* FMDB */,
17F02BB01319BA4B00260C6B /* RouteMe.h */,
B1EB26C510B5D8E6009F8658 /* RMNotifications.h */,
96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */,
... ... @@ -706,7 +691,6 @@
B8474B9A0EB40094006A0BC1 /* FMDatabase.h in Headers */,
B8474B9C0EB40094006A0BC1 /* FMDatabaseAdditions.h in Headers */,
B8474B9F0EB40094006A0BC1 /* FMResultSet.h in Headers */,
B8474BA20EB40094006A0BC1 /* RMTileCacheDAO.h in Headers */,
B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */,
23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */,
B8800FF10EC3A237003E9CDD /* RMMarkerManager.h in Headers */,
... ... @@ -892,7 +876,6 @@
2BEC60490F8AC738008FB858 /* RMProjection.m in Sources */,
2BEC604A0F8AC739008FB858 /* RMTile.c in Sources */,
2BEC604B0F8AC73A008FB858 /* RMTileCache.m in Sources */,
2BEC604C0F8AC73C008FB858 /* RMTileCacheDAO.m in Sources */,
2BEC604E0F8AC73D008FB858 /* RMTileImage.m in Sources */,
2BEC604F0F8AC73E008FB858 /* RMTileImageSet.m in Sources */,
2BEC60500F8AC73F008FB858 /* RMTileLoader.m in Sources */,
... ... @@ -935,7 +918,6 @@
B8474B9B0EB40094006A0BC1 /* FMDatabase.m in Sources */,
B8474B9D0EB40094006A0BC1 /* FMDatabaseAdditions.m in Sources */,
B8474BA00EB40094006A0BC1 /* FMResultSet.m in Sources */,
B8474BA30EB40094006A0BC1 /* RMTileCacheDAO.m in Sources */,
B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */,
126693040EB76C0B00E002D5 /* RMConfiguration.m in Sources */,
23A0AAE90EB90A99003A4521 /* RMFoundation.c in Sources */,
... ...