From: helge Date: Tue, 28 Sep 2004 15:32:48 +0000 (+0000) Subject: added pooling X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfe48c9eba8f92c1217075433875d225fe7e5ac5;p=scalable-opengroupware.org added pooling git-svn-id: http://svn.opengroupware.org/SOGo/trunk@326 d1b88da0-ebda-0310-925b-ed51d893ca5b --- diff --git a/SOGo/SoObjects/Mailer/ChangeLog b/SOGo/SoObjects/Mailer/ChangeLog index 87a3e750..a09f9772 100644 --- a/SOGo/SoObjects/Mailer/ChangeLog +++ b/SOGo/SoObjects/Mailer/ChangeLog @@ -1,5 +1,7 @@ 2004-09-28 Helge Hess - + + * SOGoMailManager.m: added connection pooling (v0.9.10) + * v0.9.9 * SOGoMailBaseObject.m: added -mailManager method to retrieve the diff --git a/SOGo/SoObjects/Mailer/README b/SOGo/SoObjects/Mailer/README new file mode 100644 index 00000000..e61ff725 --- /dev/null +++ b/SOGo/SoObjects/Mailer/README @@ -0,0 +1,13 @@ +# README for Mailer SoObjects + +Class Overview +============== + +SOGoMailManager +- backend class connecting to NGImap4, will probably move to SOGoLogic + +Defaults +======== + +SOGoEnableIMAP4Debug YES|NO - enable/disable debugging in SOGoMailManager +SOGoDisableIMAP4Pooling YES|NO - disable IMAP4 connection pooling diff --git a/SOGo/SoObjects/Mailer/SOGoMailManager.h b/SOGo/SoObjects/Mailer/SOGoMailManager.h index 4fa50e5e..0cf0e229 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailManager.h +++ b/SOGo/SoObjects/Mailer/SOGoMailManager.h @@ -30,11 +30,13 @@ Coordinates access to IMAP4 mailboxes, caches folder hierarchies, etc. */ -@class NSString, NSURL, NSArray; +@class NSString, NSURL, NSArray, NSMutableDictionary, NSTimer; @class NGImap4Client; @interface SOGoMailManager : NSObject { + NSMutableDictionary *urlToEntry; + NSTimer *gcTimer; } + (id)defaultMailManager; diff --git a/SOGo/SoObjects/Mailer/SOGoMailManager.m b/SOGo/SoObjects/Mailer/SOGoMailManager.m index 00b0cc42..0cffcabc 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailManager.m +++ b/SOGo/SoObjects/Mailer/SOGoMailManager.m @@ -22,9 +22,38 @@ #include "SOGoMailManager.h" #include "common.h" +@interface SOGoMailConnectionEntry : NSObject +{ +@public + NGImap4Client *client; + NSString *password; + NSDate *creationTime; + NSDictionary *subfolders; +} + +- (id)initWithClient:(NGImap4Client *)_client password:(NSString *)_pwd; + +/* accessors */ + +- (NGImap4Client *)client; +- (BOOL)isValidPassword:(NSString *)_pwd; + +- (NSDate *)creationTime; + +@end + @implementation SOGoMailManager -static BOOL debugOn = YES; +static BOOL debugOn = YES; +static BOOL poolingOff = NO; +static NSTimeInterval PoolScanInterval = 5 * 60; + ++ (void)initialize { + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + debugOn = [ud boolForKey:@"SOGoEnableIMAP4Debug"]; + poolingOff = [ud boolForKey:@"SOGoDisableIMAP4Pooling"]; +} + (id)defaultMailManager { static SOGoMailManager *manager = nil; // THREAD @@ -33,19 +62,65 @@ static BOOL debugOn = YES; return manager; } +- (id)init { + if ((self = [super init])) { + if (!poolingOff) { + self->urlToEntry = [[NSMutableDictionary alloc] initWithCapacity:256]; + } + + self->gcTimer = [[NSTimer scheduledTimerWithTimeInterval: + PoolScanInterval + target:self selector:@selector(_garbageCollect:) + userInfo:nil repeats:YES] retain]; + } + return self; +} + - (void)dealloc { + if (self->gcTimer) [self->gcTimer invalidate]; + [self->gcTimer release]; + + [self->urlToEntry release]; [super dealloc]; } +/* cache */ + +- (id)cacheKeyForURL:(NSURL *)_url { + // protocol, user, host, port + return [NSString stringWithFormat:@"%@://%@@%@:%@", + [_url scheme], [_url user], [_url host], [_url port]]; +} + +- (void)_garbageCollect:(NSTimer *)_timer { + // TODO: scan for old IMAP4 channels + [self debugWithFormat:@"should collect IMAP4 channels (%d active)", + [self->urlToEntry count]]; +} + /* client object */ - (NGImap4Client *)imap4ClientForURL:(NSURL *)_url password:(NSString *)_pwd { // TODO: move to some global IMAP4 connection pool manager + SOGoMailConnectionEntry *entry; NGImap4Client *client; NSDictionary *result; + NSString *cacheKey; if (_url == nil) return nil; + + cacheKey = [self cacheKeyForURL:_url]; + + if ((entry = [self->urlToEntry objectForKey:cacheKey]) != nil) { + if ([entry isValidPassword:_pwd]) { + [self debugWithFormat:@"reused IMAP4 connection for URL: %@", _url]; + return [entry client]; + } + + /* different password, password could have changed! */ + entry = nil; + } if ((client = [NGImap4Client clientWithURL:_url]) == nil) return nil; @@ -55,7 +130,12 @@ static BOOL debugOn = YES; [self logWithFormat:@"ERROR: IMAP4 login failed!"]; return nil; } - + + [self debugWithFormat:@"created new IMAP4 connection for URL: %@", _url]; + entry = [[SOGoMailConnectionEntry alloc] initWithClient:client + password:_pwd]; + [self->urlToEntry setObject:entry forKey:cacheKey]; + [entry release]; entry = nil; return client; } @@ -142,3 +222,46 @@ static BOOL debugOn = YES; } @end /* SOGoMailManager */ + +@implementation SOGoMailConnectionEntry + +- (id)initWithClient:(NGImap4Client *)_client password:(NSString *)_pwd { + if (_client == nil || _pwd == nil) { + [self release]; + return nil; + } + + if ((self = [super init])) { + self->client = [_client retain]; + self->password = [_pwd copy]; + + self->creationTime = [[NSDate alloc] init]; + } + return self; +} +- (id)init { + return [self initWithClient:nil password:nil]; +} + +- (void)dealloc { + [self->creationTime release]; + [self->subfolders release]; + [self->password release]; + [self->client release]; + [super dealloc]; +} + +/* accessors */ + +- (NGImap4Client *)client { + return self->client; +} +- (BOOL)isValidPassword:(NSString *)_pwd { + return [self->password isEqualToString:_pwd]; +} + +- (NSDate *)creationTime { + return self->creationTime; +} + +@end /* SOGoMailConnectionEntry */ diff --git a/SOGo/SoObjects/Mailer/Version b/SOGo/SoObjects/Mailer/Version index 81be7eb6..317960a7 100644 --- a/SOGo/SoObjects/Mailer/Version +++ b/SOGo/SoObjects/Mailer/Version @@ -1,3 +1,3 @@ # $Id$ -SUBMINOR_VERSION:=9 +SUBMINOR_VERSION:=10