mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
GSFileURLHandle: Use NSCache and limit cache size
This commit is contained in:
parent
21a48f6136
commit
e1fcc2db35
4 changed files with 81 additions and 54 deletions
|
@ -35,6 +35,7 @@
|
|||
#import "Foundation/NSURLHandle.h"
|
||||
#import "Foundation/NSRunLoop.h"
|
||||
#import "Foundation/NSFileManager.h"
|
||||
#import "Foundation/NSCache.h"
|
||||
|
||||
|
||||
@class GSFTPURLHandle;
|
||||
|
@ -48,7 +49,11 @@
|
|||
{
|
||||
NSString *_path;
|
||||
NSMutableDictionary *_attributes;
|
||||
BOOL _cached;
|
||||
BOOL _didLoad;
|
||||
}
|
||||
|
||||
- (void) _setFileCacheSize: (NSUInteger) size;
|
||||
@end
|
||||
|
||||
/**
|
||||
|
@ -604,8 +609,13 @@ static Class NSURLHandleClass = 0;
|
|||
*/
|
||||
@implementation GSFileURLHandle
|
||||
|
||||
static NSMutableDictionary *fileCache = nil;
|
||||
static NSLock *fileLock = nil;
|
||||
static NSCache *fileCache = nil;
|
||||
static NSUInteger defaultCacheSize = 4 * 1024 * 1024;
|
||||
|
||||
- (void) _setFileCacheSize: (NSUInteger) size
|
||||
{
|
||||
[fileCache setTotalCostLimit: size];
|
||||
}
|
||||
|
||||
+ (NSURLHandle*) cachedHandleForURL: (NSURL*)url
|
||||
{
|
||||
|
@ -616,19 +626,8 @@ static NSLock *fileLock = nil;
|
|||
NSString *path = [url path];
|
||||
|
||||
path = [path stringByStandardizingPath];
|
||||
[fileLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
obj = [fileCache objectForKey: path];
|
||||
IF_NO_ARC([[obj retain] autorelease];)
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[fileLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[fileLock unlock];
|
||||
obj = [fileCache objectForKey: path];
|
||||
IF_NO_ARC([[obj retain] autorelease];)
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
@ -644,10 +643,10 @@ static NSLock *fileLock = nil;
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
fileCache = [NSMutableDictionary new];
|
||||
fileCache = [NSCache new];
|
||||
[fileCache setName: @"org.gnustep.GSFileURLHandle.cache"];
|
||||
[fileCache setTotalCostLimit: defaultCacheSize];
|
||||
[[NSObject leakAt: &fileCache] release];
|
||||
fileLock = [NSLock new];
|
||||
[[NSObject leakAt: &fileLock] release];
|
||||
}
|
||||
|
||||
- (NSData*) availableResourceData
|
||||
|
@ -704,52 +703,24 @@ static NSLock *fileLock = nil;
|
|||
path = [url path];
|
||||
path = [path stringByStandardizingPath];
|
||||
|
||||
_didLoad = NO;
|
||||
_cached = cached;
|
||||
if (cached == YES)
|
||||
{
|
||||
id obj;
|
||||
|
||||
[fileLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
obj = [fileCache objectForKey: path];
|
||||
if (obj != nil)
|
||||
{
|
||||
DESTROY(self);
|
||||
IF_NO_ARC([obj retain];)
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
obj = nil;
|
||||
[fileLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[fileLock unlock];
|
||||
obj = [fileCache objectForKey: path];
|
||||
if (obj != nil)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
{
|
||||
DESTROY(self);
|
||||
IF_NO_ARC([obj retain];)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
if ((self = [super initWithURL: url cached: cached]) != nil)
|
||||
{
|
||||
_path = [path copy];
|
||||
if (cached == YES)
|
||||
{
|
||||
[fileLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
[fileCache setObject: self forKey: _path];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[fileLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[fileLock unlock];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -763,6 +734,13 @@ static NSLock *fileLock = nil;
|
|||
traverseLink: YES];
|
||||
RELEASE(_attributes);
|
||||
_attributes = [dict mutableCopy];
|
||||
|
||||
if (_cached && !_didLoad)
|
||||
{
|
||||
[fileCache setObject: self forKey: _path cost: [d length]];
|
||||
}
|
||||
_didLoad = YES;
|
||||
|
||||
[self didLoadBytes: d loadComplete: YES];
|
||||
return d;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed lobortis
|
||||
nisl, id suscipit nunc.
|
45
Tests/base/NSURLHandle/caching.m
Normal file
45
Tests/base/NSURLHandle/caching.m
Normal file
|
@ -0,0 +1,45 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "Testing.h"
|
||||
#import "ObjectTesting.h"
|
||||
|
||||
@interface GSFileURLHandle : NSURLHandle
|
||||
+ (void) _setFileCacheSize: (NSUInteger) size;
|
||||
+ (NSCache *) _fileCache;
|
||||
@end
|
||||
|
||||
int main()
|
||||
{
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
NSString *execPath;
|
||||
NSString *path;
|
||||
NSURL *url;
|
||||
NSCache *cache;
|
||||
NSData *data;
|
||||
GSFileURLHandle *fileHandle;
|
||||
Class fileHandleClass;
|
||||
|
||||
|
||||
execPath = [[NSBundle mainBundle] resourcePath];
|
||||
NSLog(@"Resource Path: %@", execPath);
|
||||
// Assuming executable is located in obj subdir
|
||||
path = [NSString stringWithFormat: @"%@/testData.txt", execPath];
|
||||
url = [NSURL fileURLWithPath: path];
|
||||
|
||||
fileHandleClass = [NSURLHandle URLHandleClassForURL: url];
|
||||
fileHandle = [[fileHandleClass alloc] initWithURL: url cached: YES];
|
||||
cache = [GSFileURLHandle _fileCache];
|
||||
|
||||
GSFileURLHandle *h = [cache objectForKey: [url path]];
|
||||
PASS(h == nil, "Cache does not store unloaded file handle");
|
||||
|
||||
data = [fileHandle loadInForeground];
|
||||
PASS(data != nil, "Data is valid");
|
||||
|
||||
h = [cache objectForKey: [url path]];
|
||||
PASS(h != nil, "Cache stores loaded file handle");
|
||||
PASS([fileHandle isEqualTo: h], "File handles are equivalent");
|
||||
|
||||
[fileHandle release];
|
||||
[arp release]; arp = nil;
|
||||
return 0;
|
||||
}
|
|
@ -76,6 +76,8 @@ int main(int argc, char **argv)
|
|||
[t terminate];
|
||||
[t waitUntilExit];
|
||||
}
|
||||
|
||||
END_SET("Keepalive")
|
||||
|
||||
[arp release]; arp = nil ;
|
||||
|
||||
|
|
Loading…
Reference in a new issue