/MapView/Map/RMTileCache.m
http://github.com/route-me/route-me · Objective C · 217 lines · 143 code · 40 blank · 34 comment · 33 complexity · 1a0ecc356806087fc1fd92fefc67cad7 MD5 · raw file
- //
- // RMTileCache.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 "RMTileCache.h"
- #import "RMMemoryCache.h"
- #import "RMDatabaseCache.h"
- #import "RMConfiguration.h"
- #import "RMTileSource.h"
- @interface RMTileCache ( Configuration )
- - (id<RMTileCache>) newMemoryCacheWithConfig: (NSDictionary*) cfg;
- - (id<RMTileCache>) newDatabaseCacheWithConfig: (NSDictionary*) cfg tileSource: (id<RMTileSource>) tileSource;
- @end
- @implementation RMTileCache
- -(id)initWithTileSource: (id<RMTileSource>) tileSource
- {
- if (![super init])
- return nil;
-
- caches = [[NSMutableArray alloc] init];
- id cacheCfg = [[RMConfiguration configuration] cacheConfiguration];
-
- if (cacheCfg==nil)
- {
- cacheCfg = [NSArray arrayWithObjects:
- /// \bug magic string literals
- [NSDictionary dictionaryWithObject: @"memory-cache" forKey: @"type"],
- [NSDictionary dictionaryWithObject: @"db-cache" forKey: @"type"],
- nil
- ];
- }
- for (id cfg in cacheCfg)
- {
- id<RMTileCache> newCache = nil;
-
- @try {
- NSString* type = [cfg valueForKey:@"type"];
-
- /// \bug magic string literals
- if ([@"memory-cache" isEqualToString: type])
- newCache = [self newMemoryCacheWithConfig: cfg];
- if ([@"db-cache" isEqualToString: type])
- newCache = [self newDatabaseCacheWithConfig: cfg tileSource: tileSource];
- if (newCache) {
- [caches addObject: newCache];
- [newCache release];
- } else {
- RMLog(@"failed to create cache of type %@", type);
- }
- }
- @catch (NSException * e) {
- RMLog(@"*** configuration error: %@", [e reason]);
- }
-
- }
- return self;
- }
- -(void) dealloc
- {
- [caches release];
- [super dealloc];
- }
- -(void)addCache: (id<RMTileCache>)cache
- {
- [caches addObject:cache];
- }
- +(NSNumber*) tileHash: (RMTile)tile
- {
- return [NSNumber numberWithUnsignedLongLong: RMTileKey(tile)];
- }
- // Returns the cached image if it exists. nil otherwise.
- -(RMTileImage*) cachedImage:(RMTile)tile
- {
- for (id<RMTileCache> cache in caches)
- {
- RMTileImage *image = [cache cachedImage:tile];
- if (image != nil)
- return image;
- }
-
- return nil;
- }
- -(void)addTile: (RMTile)tile WithImage: (RMTileImage*)image
- {
- for (id<RMTileCache> cache in caches)
- {
- if ([cache respondsToSelector:@selector(addTile:WithImage:)])
- {
- [cache addTile:tile WithImage:image];
- }
- }
- }
- -(void)didReceiveMemoryWarning
- {
- LogMethod();
- for (id<RMTileCache> cache in caches)
- {
- [cache didReceiveMemoryWarning];
- }
- }
- -(void) removeAllCachedImages
- {
- for (id<RMTileCache> cache in caches)
- {
- [cache removeAllCachedImages];
- }
- }
- @end
- @implementation RMTileCache ( Configuration )
- /// \bug magic numbers and strings
- - (id<RMTileCache>) newMemoryCacheWithConfig: (NSDictionary*) cfg
- {
- NSNumber* capacity = [cfg objectForKey:@"capacity"];
- if (capacity == nil) capacity = [NSNumber numberWithInt: 32];
- return [[RMMemoryCache alloc] initWithCapacity: [capacity intValue]];
- }
- /// \bug magic numbers and strings
- - (id<RMTileCache>) newDatabaseCacheWithConfig: (NSDictionary*) cfg tileSource: (id<RMTileSource>) theTileSource
- {
- BOOL useCacheDir = NO;
- RMCachePurgeStrategy strategy = RMCachePurgeStrategyFIFO;
- /// \bug magic numbers
- NSUInteger capacity = 1000;
- NSUInteger minimalPurge = capacity / 10;
-
- NSNumber* capacityNumber = [cfg objectForKey:@"capacity"];
- if (capacityNumber!=nil) {
- NSInteger value = [capacityNumber intValue];
-
- // 0 is valid: it means no capacity limit
- if (value >= 0) {
- capacity = value;
- minimalPurge = MAX(1,capacity / 10);
- } 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;
- }
-
- /// \bug magic string literals
- NSNumber* useCacheDirNumber = [cfg objectForKey:@"useCachesDirectory"];
- if (useCacheDirNumber!=nil) useCacheDir = [useCacheDirNumber boolValue];
-
- NSNumber* minimalPurgeNumber = [cfg objectForKey:@"minimalPurge"];
- if (minimalPurgeNumber != nil && capacity != 0) {
- NSUInteger value = [minimalPurgeNumber unsignedIntValue];
- if (value > 0 && value<=capacity)
- minimalPurge = value;
- else {
- RMLog(@"minimalPurge must be at least one and at most the cache capacity");
- }
- }
-
- RMDatabaseCache* dbCache = [[RMDatabaseCache alloc]
- initWithTileSource: theTileSource
- usingCacheDir: useCacheDir
- ];
-
- [dbCache setCapacity: capacity];
- [dbCache setPurgeStrategy: strategy];
- [dbCache setMinimalPurge: minimalPurge];
-
- return dbCache;
- }
- @end