mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 08:41:03 +00:00
Limit size of http url handle cache.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24172 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ea66a0858c
commit
acd9220a76
2 changed files with 39 additions and 29 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2006-11-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/GSHTTPURLHandle.m: Limit size of handle cache to 16 to
|
||||||
|
avoid increasing memory usage indefinitely if a program keeps
|
||||||
|
loading different URLs.
|
||||||
|
|
||||||
2006-11-29 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-11-29 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/GSPrivate.h:
|
* Source/GSPrivate.h:
|
||||||
|
|
|
@ -214,7 +214,10 @@ static NSString *httpVersion = @"1.1";
|
||||||
*/
|
*/
|
||||||
@implementation GSHTTPURLHandle
|
@implementation GSHTTPURLHandle
|
||||||
|
|
||||||
|
#define MAX_CACHED 16
|
||||||
|
|
||||||
static NSMutableDictionary *urlCache = nil;
|
static NSMutableDictionary *urlCache = nil;
|
||||||
|
static NSMutableArray *urlOrder = nil;
|
||||||
static NSLock *urlLock = nil;
|
static NSLock *urlLock = nil;
|
||||||
|
|
||||||
static Class sslClass = 0;
|
static Class sslClass = 0;
|
||||||
|
@ -282,7 +285,12 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
//NSLog(@"Lookup for handle for '%@'", page);
|
//NSLog(@"Lookup for handle for '%@'", page);
|
||||||
[urlLock lock];
|
[urlLock lock];
|
||||||
obj = [urlCache objectForKey: page];
|
obj = [urlCache objectForKey: page];
|
||||||
AUTORELEASE(RETAIN(obj));
|
if (obj != nil)
|
||||||
|
{
|
||||||
|
[urlOrder removeObjectIdenticalTo: obj];
|
||||||
|
[urlOrder addObject: obj];
|
||||||
|
AUTORELEASE(RETAIN(obj));
|
||||||
|
}
|
||||||
[urlLock unlock];
|
[urlLock unlock];
|
||||||
//NSLog(@"Found handle %@", obj);
|
//NSLog(@"Found handle %@", obj);
|
||||||
}
|
}
|
||||||
|
@ -294,6 +302,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
if (self == [GSHTTPURLHandle class])
|
if (self == [GSHTTPURLHandle class])
|
||||||
{
|
{
|
||||||
urlCache = [NSMutableDictionary new];
|
urlCache = [NSMutableDictionary new];
|
||||||
|
urlOrder = [NSMutableArray new];
|
||||||
urlLock = [GSLazyLock new];
|
urlLock = [GSLazyLock new];
|
||||||
debugLock = [GSLazyLock new];
|
debugLock = [GSLazyLock new];
|
||||||
debugFile = [NSString stringWithFormat: @"%@/GSHTTP.%d",
|
debugFile = [NSString stringWithFormat: @"%@/GSHTTP.%d",
|
||||||
|
@ -313,14 +322,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
{
|
{
|
||||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||||
|
|
||||||
/*
|
[nc removeObserver: self name: nil object: sock];
|
||||||
* We might be in an idle state with an outstanding read on the
|
|
||||||
* socket, keeping the connection alive, but waiting for the
|
|
||||||
* remote end to drop it.
|
|
||||||
*/
|
|
||||||
[nc removeObserver: self
|
|
||||||
name: NSFileHandleReadCompletionNotification
|
|
||||||
object: sock];
|
|
||||||
[sock closeFile];
|
[sock closeFile];
|
||||||
DESTROY(sock);
|
DESTROY(sock);
|
||||||
}
|
}
|
||||||
|
@ -354,10 +356,23 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
connectionState = idle;
|
connectionState = idle;
|
||||||
if (cached == YES)
|
if (cached == YES)
|
||||||
{
|
{
|
||||||
NSString *page = [newUrl absoluteString];
|
NSString *page = [newUrl absoluteString];
|
||||||
|
GSHTTPURLHandle *obj;
|
||||||
|
|
||||||
[urlLock lock];
|
[urlLock lock];
|
||||||
|
obj = [urlCache objectForKey: page];
|
||||||
[urlCache setObject: self forKey: page];
|
[urlCache setObject: self forKey: page];
|
||||||
|
if (obj != nil)
|
||||||
|
{
|
||||||
|
[urlOrder removeObjectIdenticalTo: obj];
|
||||||
|
}
|
||||||
|
[urlOrder addObject: self];
|
||||||
|
while ([urlOrder count] > MAX_CACHED)
|
||||||
|
{
|
||||||
|
obj = [urlOrder objectAtIndex: 0];
|
||||||
|
[urlCache removeObjectForKey: [obj->url absoluteString]];
|
||||||
|
[urlOrder removeObjectAtIndex: 0];
|
||||||
|
}
|
||||||
[urlLock unlock];
|
[urlLock unlock];
|
||||||
//NSLog(@"Cache handle %@ for '%@'", self, page);
|
//NSLog(@"Cache handle %@ for '%@'", self, page);
|
||||||
}
|
}
|
||||||
|
@ -535,8 +550,9 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
*/
|
*/
|
||||||
if (debug == YES && [d length] != 0)
|
if (debug == YES && [d length] != 0)
|
||||||
{
|
{
|
||||||
NSLog(@"%@ %s Unexpected data from remote!",
|
NSLog(@"%@ %s Unexpected data (%*.*s) from remote!",
|
||||||
NSStringFromSelector(_cmd), keepalive?"K":"");
|
NSStringFromSelector(_cmd), keepalive?"K":"",
|
||||||
|
[d length], [d length], [d bytes]);
|
||||||
}
|
}
|
||||||
[nc removeObserver: self
|
[nc removeObserver: self
|
||||||
name: NSFileHandleReadCompletionNotification
|
name: NSFileHandleReadCompletionNotification
|
||||||
|
@ -593,14 +609,12 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
float ver;
|
float ver;
|
||||||
|
|
||||||
connectionState = idle;
|
connectionState = idle;
|
||||||
|
[nc removeObserver: self name: nil object: sock];
|
||||||
|
|
||||||
ver = [[[document headerNamed: @"http"] value] floatValue];
|
ver = [[[document headerNamed: @"http"] value] floatValue];
|
||||||
val = [[document headerNamed: @"connection"] value];
|
val = [[document headerNamed: @"connection"] value];
|
||||||
if (ver < 1.1 || (val != nil && [val isEqual: @"close"] == YES))
|
if (ver < 1.1 || (val != nil && [val isEqual: @"close"] == YES))
|
||||||
{
|
{
|
||||||
[nc removeObserver: self
|
|
||||||
name: NSFileHandleReadCompletionNotification
|
|
||||||
object: sock];
|
|
||||||
[sock closeFile];
|
[sock closeFile];
|
||||||
DESTROY(sock);
|
DESTROY(sock);
|
||||||
}
|
}
|
||||||
|
@ -808,16 +822,8 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
if (connectionState != idle)
|
if (connectionState != idle)
|
||||||
{
|
{
|
||||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||||
NSString *name;
|
|
||||||
|
|
||||||
if (connectionState == connecting)
|
[nc removeObserver: self name: nil object: sock];
|
||||||
name = GSFileHandleConnectCompletionNotification;
|
|
||||||
else if (connectionState == writing)
|
|
||||||
name = GSFileHandleWriteCompletionNotification;
|
|
||||||
else
|
|
||||||
name = NSFileHandleReadCompletionNotification;
|
|
||||||
|
|
||||||
[nc removeObserver: self name: name object: sock];
|
|
||||||
[sock closeFile];
|
[sock closeFile];
|
||||||
DESTROY(sock);
|
DESTROY(sock);
|
||||||
connectionState = idle;
|
connectionState = idle;
|
||||||
|
@ -1017,9 +1023,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
* then we may try again with a new connection.
|
* then we may try again with a new connection.
|
||||||
*/
|
*/
|
||||||
nc = [NSNotificationCenter defaultCenter];
|
nc = [NSNotificationCenter defaultCenter];
|
||||||
[nc removeObserver: self
|
[nc removeObserver: self name: nil object: sock];
|
||||||
name: GSFileHandleWriteCompletionNotification
|
|
||||||
object: sock];
|
|
||||||
[sock closeFile];
|
[sock closeFile];
|
||||||
DESTROY(sock);
|
DESTROY(sock);
|
||||||
connectionState = idle;
|
connectionState = idle;
|
||||||
|
@ -1221,7 +1225,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
NSFileHandle *test = RETAIN(sock);
|
NSFileHandle *test = RETAIN(sock);
|
||||||
|
|
||||||
[nc addObserver: self
|
[nc addObserver: self
|
||||||
selector: @selector(bgdTunnelRead:)
|
selector: @selector(bgdRead:)
|
||||||
name: NSFileHandleReadCompletionNotification
|
name: NSFileHandleReadCompletionNotification
|
||||||
object: test];
|
object: test];
|
||||||
if ([test readInProgress] == NO)
|
if ([test readInProgress] == NO)
|
||||||
|
@ -1231,7 +1235,7 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
||||||
[loop acceptInputForMode: NSDefaultRunLoopMode
|
[loop acceptInputForMode: NSDefaultRunLoopMode
|
||||||
beforeDate: nil];
|
beforeDate: nil];
|
||||||
[nc removeObserver: self
|
[nc removeObserver: self
|
||||||
name: NSFileHandleReadCompletionNotification
|
name: nil
|
||||||
object: test];
|
object: test];
|
||||||
RELEASE(test);
|
RELEASE(test);
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue