GSFileURLHandle: Use NSCache and limit cache size

This commit is contained in:
hmelder 2024-05-06 10:38:07 +02:00
parent 21a48f6136
commit e1fcc2db35
4 changed files with 81 additions and 54 deletions

View file

@ -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;
}

View file

@ -0,0 +1,2 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed lobortis
nisl, id suscipit nunc.

View 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;
}

View file

@ -76,6 +76,8 @@ int main(int argc, char **argv)
[t terminate];
[t waitUntilExit];
}
END_SET("Keepalive")
[arp release]; arp = nil ;