Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion sope-mime/NGImap4/NGImap4ConnectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@
This class manages and pools NGImap4Connection objects.
*/

@class NSString, NSTimer, NSMutableDictionary, NSURL;
@class NSString, NSTimer, NSMutableDictionary, NSLock, NSURL;
@class NGImap4Connection, NGImap4Client;

@interface NGImap4ConnectionManager : NSObject
{
NSMutableDictionary *urlToEntry;
NSLock *entryLock;
NSTimer *gcTimer;
}

Expand Down
86 changes: 76 additions & 10 deletions sope-mime/NGImap4/NGImap4ConnectionManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include "NGImap4Client.h"
#include "imCommon.h"

#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSThread.h>

@implementation NGImap4ConnectionManager

static BOOL debugOn = NO;
Expand Down Expand Up @@ -79,6 +83,7 @@ - (id)init {
if ((self = [super init])) {
if (!poolingOff) {
self->urlToEntry = [[NSMutableDictionary alloc] initWithCapacity:256];
self->entryLock = [[NSLock alloc] init];
self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval:
PoolScanInterval
target:self selector:@selector(_garbageCollect:)
Expand All @@ -91,6 +96,7 @@ - (id)init {
- (void)dealloc {
[self->gcTimer invalidate];
[self->urlToEntry release];
[self->entryLock release];
[self->gcTimer release];
[super dealloc];
}
Expand All @@ -104,39 +110,99 @@ - (id)cacheKeyForURL:(NSURL *)_url {
}

- (NGImap4Connection *)entryForURL:(NSURL *)_url {
NGImap4Connection *entry;

if (_url == nil)
return nil;

return [self->urlToEntry objectForKey:[self cacheKeyForURL:_url]];

[self->entryLock lock];
entry = [[self->urlToEntry objectForKey:[self cacheKeyForURL:_url]] retain];
[self->entryLock unlock];

return [entry autorelease];
}
- (void)cacheEntry:(NGImap4Connection *)_entry forURL:(NSURL *)_url {
if (_entry == nil) _entry = (id)[NSNull null];
[self->entryLock lock];
[self->urlToEntry setObject:_entry forKey:[self cacheKeyForURL:_url]];
[self->entryLock unlock];
}

- (unsigned int)poolEntryCount {
unsigned int count;

[self->entryLock lock];
count = [self->urlToEntry count];
[self->entryLock unlock];

return count;
}

- (void)_logoutClients:(NSArray *)_clients {
NSAutoreleasePool *pool;
NGImap4Client *client;
unsigned int i, count;

pool = [[NSAutoreleasePool alloc] init];
count = [_clients count];

for (i = 0; i < count; i++)
{
client = [_clients objectAtIndex:i];

NS_DURING
[client logout];
NS_HANDLER
[self logWithFormat:@"could not logout expired IMAP4 connection: %@",
localException];
NS_ENDHANDLER;
}

[_clients release];
[pool release];
}

- (void)_garbageCollect:(NSTimer *)_timer {
// TODO: scan for old IMAP4 channels
NGImap4Connection *entry;
NSMutableArray *clientsToLogout;
NSDate *now;
NSArray *a;
int i;
NSString *key;
NSArray *clients;
unsigned int i, count;

a = [self->urlToEntry allKeys];
clientsToLogout = [NSMutableArray arrayWithCapacity:16];
now = [NSDate date];

for (i = 0; i < [a count]; i++)
[self->entryLock lock];
a = [self->urlToEntry allKeys];
count = [a count];

for (i = 0; i < count; i++)
{
entry = [self->urlToEntry objectForKey: [a objectAtIndex: i]];
key = [a objectAtIndex: i];
entry = [self->urlToEntry objectForKey: key];

if ([now timeIntervalSinceDate: [entry creationTime]] > PoolScanInterval)
if ([entry isKindOfClass:[NGImap4Connection class]]
&& [now timeIntervalSinceDate: [entry creationTime]] > PoolScanInterval)
{
[[entry client] logout];
[self->urlToEntry removeObjectForKey: [a objectAtIndex: i]];
[clientsToLogout addObject: [entry client]];
[self->urlToEntry removeObjectForKey: key];
}
}
[self->entryLock unlock];

if ([clientsToLogout count] > 0)
{
clients = [clientsToLogout copy];
[NSThread detachNewThreadSelector:@selector(_logoutClients:)
toTarget:self
withObject:clients];
}

[self debugWithFormat:@"should collect IMAP4 channels (%d active)",
[self->urlToEntry count]];
[self poolEntryCount]];
}

- (NGImap4Connection *)connectionForURL:(NSURL *)_url password:(NSString *)_p {
Expand Down