]> err.no Git - scalable-opengroupware.org/commitdiff
added uid caching to mailer manager
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 5 Oct 2004 22:26:01 +0000 (22:26 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 5 Oct 2004 22:26:01 +0000 (22:26 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@364 d1b88da0-ebda-0310-925b-ed51d893ca5b

SOGo/SoObjects/Mailer/ChangeLog
SOGo/SoObjects/Mailer/GNUmakefile
SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.h [new file with mode: 0644]
SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.m [new file with mode: 0644]
SOGo/SoObjects/Mailer/SOGoMailFolder.m
SOGo/SoObjects/Mailer/SOGoMailManager.h
SOGo/SoObjects/Mailer/SOGoMailManager.m
SOGo/SoObjects/Mailer/Version

index ac1e41875782d34bb4ece470851ec7a5bde4aca3..fd6f649bab0c5295b07dd504871a59297e9e9bed 100644 (file)
@@ -1,3 +1,16 @@
+2004-10-06  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v0.9.26
+
+       * SOGoMailConnectionEntry.m: added caching of sorted UIDs sets
+
+       * SOGoMailManager.m: moved SOGoMailConnectionEntry class to own file
+
+2004-10-05  Helge Hess  <helge.hess@opengroupware.org>
+
+       * SOGoMailManager: removed range argument from -fetchUIDsInURL:..,
+         since IMAP4 doesn't support ranges anyway ... (v0.9.25)
+
 2004-10-04  Helge Hess  <helge.hess@opengroupware.org>
 
        * SOGoMailBodyPart.m: improved MIME type generation (v0.9.24)
index a372e0015b05c8302e96762de5ed2a0ea0ff1908..2dc7d24439fa58cf581b5e3df7d7dbda09d3a7ae 100644 (file)
@@ -7,16 +7,17 @@ BUNDLE_NAME = Mailer
 Mailer_PRINCIPAL_CLASS = SOGoMailerProduct
 
 Mailer_OBJC_FILES += \
-       Product.m               \
+       Product.m                       \
        \
-       SOGoMailManager.m       \
+       SOGoMailManager.m               \
+       SOGoMailConnectionEntry.m       \
        \
-       SOGoMailBaseObject.m    \
-       SOGoMailAccounts.m      \
-       SOGoMailAccount.m       \
-       SOGoMailFolder.m        \
-       SOGoMailObject.m        \
-       SOGoMailBodyPart.m      \
+       SOGoMailBaseObject.m            \
+       SOGoMailAccounts.m              \
+       SOGoMailAccount.m               \
+       SOGoMailFolder.m                \
+       SOGoMailObject.m                \
+       SOGoMailBodyPart.m              \
 
 Mailer_RESOURCE_FILES += \
        Version         \
diff --git a/SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.h b/SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.h
new file mode 100644 (file)
index 0000000..69970fb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#ifndef __SOGo_SOGoMailConnectionEntry_H__
+#define __SOGo_SOGoMailConnectionEntry_H__
+
+#import <Foundation/NSObject.h>
+
+/* 
+   SOGoMailConnectionEntry
+   
+   A cached connection to an IMAP4 server plus some cached objects.
+*/
+
+@class NSString, NSDate, NSArray, NSDictionary, NSURL;
+@class NGImap4Client;
+
+@interface SOGoMailConnectionEntry : NSObject
+{
+@public
+  NGImap4Client *client;
+  NSString      *password;
+  NSDate        *creationTime;
+  NSDictionary  *subfolders;
+  
+  /* uids cache */
+  NSArray *cachedUIDs;
+  NSURL   *uidFolderURL;
+  id      uidSortOrdering;
+}
+
+- (id)initWithClient:(NGImap4Client *)_client password:(NSString *)_pwd;
+
+/* accessors */
+
+- (NGImap4Client *)client;
+- (BOOL)isValidPassword:(NSString *)_pwd;
+
+- (NSDate *)creationTime;
+
+- (void)cacheHierarchyResults:(NSDictionary *)_hierarchy;
+- (NSDictionary *)cachedHierarchyResults;
+
+- (id)cachedUIDsForURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so;
+- (void)cacheUIDs:(NSArray *)_uids forURL:(NSURL *)_url
+  qualifier:(id)_q sortOrdering:(id)_so;
+
+@end
+
+#endif /* __SOGo_SOGoMailConnectionEntry_H__ */
diff --git a/SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.m b/SOGo/SoObjects/Mailer/SOGoMailConnectionEntry.m
new file mode 100644 (file)
index 0000000..bb2d486
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "SOGoMailConnectionEntry.h"
+#include "common.h"
+
+@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->cachedUIDs      release];
+  [self->uidFolderURL    release];
+  [self->uidSortOrdering release];
+  [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;
+}
+
+- (void)cacheHierarchyResults:(NSDictionary *)_hierarchy {
+  ASSIGNCOPY(self->subfolders, _hierarchy);
+}
+- (NSDictionary *)cachedHierarchyResults {
+  return self->subfolders;
+}
+
+- (id)cachedUIDsForURL:(NSURL *)_url qualifier:(id)_q sortOrdering:(id)_so {
+  if (_q != nil)
+    return nil;
+  if (![_so isEqual:self->uidSortOrdering])
+    return nil;
+  if (![self->uidFolderURL isEqual:_url])
+    return nil;
+  
+  return self->cachedUIDs;
+}
+
+- (void)cacheUIDs:(NSArray *)_uids forURL:(NSURL *)_url
+  qualifier:(id)_q sortOrdering:(id)_so
+{
+  if (_q != nil)
+    return;
+
+  ASSIGNCOPY(self->uidSortOrdering, _so);
+  ASSIGNCOPY(self->uidFolderURL,    _url);
+  ASSIGNCOPY(self->cachedUIDs,      _uids);
+}
+
+@end /* SOGoMailConnectionEntry */
index 5025b04991b3928cf73c1204057c208b3313aeb9..b158dc5ff909dcdac53b0a0463eff58cbd909e8b 100644 (file)
@@ -45,7 +45,6 @@
 - (NSArray *)fetchUIDsMatchingQualifier:(id)_q sortOrdering:(id)_so {
   return [[self mailManager] fetchUIDsInURL:[self imap4URL]
                             qualifier:_q sortOrdering:_so
-                            range:NSMakeRange(0, 100000)
                             password:[self imap4Password]];
 }
 
index 36a4099492834bfb3948e9d14428b90b05aaba14..3eb874a2baa93154563fec8caff765ccb0d48b65 100644 (file)
@@ -55,7 +55,7 @@
 /* messages */
 
 - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_q
-  sortOrdering:(id)_so range:(NSRange)_range password:(NSString *)_pwd;
+  sortOrdering:(id)_so password:(NSString *)_pwd;
 - (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url
   parts:(NSArray *)_parts password:(NSString *)_pwd;
 
index 7f46fce67fd55482bc58a5db55bdb84e9a62fc85..b3c507cf62cba88125be810b7c3cbd16e08e526d 100644 (file)
 */
 
 #include "SOGoMailManager.h"
+#include "SOGoMailConnectionEntry.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;
-
-- (void)cacheHierarchyResults:(NSDictionary *)_hierarchy;
-- (NSDictionary *)cachedHierarchyResults;
-
-@end
+// TODO: need a way to refresh caches on get mail!
 
 @implementation SOGoMailManager
 
@@ -119,6 +99,46 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
          [self->urlToEntry count]];
 }
 
+- (id)entryForURL:(NSURL *)_url password:(NSString *)_pwd {
+  /*
+    Three cases:
+    a) not yet connected             => create new entry and connect
+    b) connected, correct password   => return cached entry
+    c) connected, different password => try to recreate entry
+  */
+  SOGoMailConnectionEntry *entry;
+  NGImap4Client *client;
+
+  /* check cache */
+  
+  if ((entry = [self entryForURL:_url]) != nil) {
+    if ([entry isValidPassword:_pwd]) {
+      if (debugCache)
+       [self logWithFormat:@"valid password, reusing cache entry ..."];
+      return entry;
+    }
+    
+    /* different password, password could have changed! */
+    if (debugCache)
+      [self logWithFormat:@"different password than cached entry: %@", _url];
+    entry = nil;
+  }
+  else
+    [self debugWithFormat:@"no connection cached yet for url: %@", _url];
+  
+  /* try to login */
+  
+  client = [entry isValidPassword:_pwd]
+    ? [entry client]
+    : [self imap4ClientForURL:_url password:_pwd];
+  
+  if (client == nil)
+    return nil;
+  
+  /* sideeffect of -imap4ClientForURL:password: is to create a cache entry */
+  return [self entryForURL:_url];
+}
+
 /* client object */
 
 - (NGImap4Client *)imap4ClientForURL:(NSURL *)_url password:(NSString *)_pwd {
@@ -273,43 +293,26 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
 - (NSArray *)subfoldersForURL:(NSURL *)_url password:(NSString *)_pwd {
   // TODO: add caching
   SOGoMailConnectionEntry *entry;
-  NGImap4Client *client;
   NSDictionary  *result;
 
   if (debugKeys)
     [self debugWithFormat:@"subfolders for URL: %@ ...",[_url absoluteString]];
   
-  /* check cache */
-  
-  if ((entry = [self entryForURL:_url]) != nil) {
-    if ([entry isValidPassword:_pwd]) {
-      NSDictionary *allFolders;
-      
-      if (debugCache)
-       [self logWithFormat:@"valid password, reusing folder cache .."];
-      if ((allFolders = [entry cachedHierarchyResults]) != nil)
-       return [self extractSubfoldersForURL:_url fromResultSet:allFolders];
-      
-      [self debugWithFormat:@"  no folders cached yet .."];
-    }
-    
-    /* different password, password could have changed! */
-    entry = nil;
-  }
-  else
-    [self debugWithFormat:@"no connection cached yet for url: %@", _url];
-
-  /* get client */
+  /* check connection cache */
   
-  client = [entry isValidPassword:_pwd]
-    ? [entry client]
-    : [self imap4ClientForURL:_url password:_pwd];
-  if (client == nil)
+  if ((entry = [self entryForURL:_url password:_pwd]) == nil)
     return nil;
   
+  /* check hierarchy cache */
+  
+  if ((result = [entry cachedHierarchyResults]) != nil)
+      return [self extractSubfoldersForURL:_url fromResultSet:result];
+  
+  [self debugWithFormat:@"  no folders cached yet .."];
+  
   /* fetch _all_ folders */
   
-  result = [client list:@"INBOX" pattern:@"*"];
+  result = [[entry client] list:@"INBOX" pattern:@"*"];
   if (![[result valueForKey:@"result"] boolValue]) {
     [self logWithFormat:@"ERROR: listing of folder failed!"];
     return nil;
@@ -336,25 +339,37 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
 /* messages */
 
 - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier
-  sortOrdering:(id)_so range:(NSRange)_range password:(NSString *)_pwd
+  sortOrdering:(id)_so password:(NSString *)_pwd
 {
   /* 
      sortOrdering can be an NSString, an EOSortOrdering or an array of EOS.
   */
-  NGImap4Client *client;
+  SOGoMailConnectionEntry *entry;
   NSDictionary  *result;
   NSArray       *uids;
   
-  if ((client = [self imap4ClientForURL:_url password:_pwd]) == nil)
+  /* check connection cache */
+  
+  if ((entry = [self entryForURL:_url password:_pwd]) == nil)
     return nil;
   
-  result = [client select:[self imap4FolderNameForURL:_url]];
+  /* check cache */
+  
+  uids = [entry cachedUIDsForURL:_url qualifier:_qualifier sortOrdering:_so];
+  if (uids != nil) {
+    [self logWithFormat:@"REUSE UID CACHE!"];
+    return [uids isNotNull] ? uids : nil;
+  }
+  
+  /* select folder and fetch */
+  
+  result = [[entry client] select:[self imap4FolderNameForURL:_url]];
   if (![[result valueForKey:@"result"] boolValue]) {
     [self logWithFormat:@"ERROR: could not select URL: %@: %@", _url, result];
     return nil;
   }
   
-  result = [client sort:_so qualifier:_qualifier encoding:@"UTF-8"];
+  result = [[entry client] sort:_so qualifier:_qualifier encoding:@"UTF-8"];
   if (![[result valueForKey:@"result"] boolValue]) {
     [self logWithFormat:@"ERROR: could not sort contents of URL: %@", _url];
     return nil;
@@ -366,14 +381,9 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
     return nil;
   }
   
-  // TODO: improve to use a single range call?
-  if (_range.location > 0) {
-    uids = [uids subarrayWithRange:NSMakeRange(_range.location,
-                                              [uids count]-_range.location)];
-  }
-  if ([uids count] > _range.length && _range.length != 0)
-    uids = [uids subarrayWithRange:NSMakeRange(0, _range.length)];
+  /* cache */
   
+  [entry cacheUIDs:uids forURL:_url qualifier:_qualifier sortOrdering:_so];
   return uids;
 }
 
@@ -416,10 +426,10 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
   
   /* fetch parts */
   
-#warning TODO: split uids into batches, otherwise Cyrus will complain
-  // not really important because we batch before (in the sort)
-  // if the list is too long, we get a:
-  //   "* BYE Fatal error: word too long"
+  // TODO: split uids into batches, otherwise Cyrus will complain
+  //       => not really important because we batch before (in the sort)
+  //       if the list is too long, we get a:
+  //       "* BYE Fatal error: word too long"
   
   result = [client fetchUids:_uids parts:_parts];
   if (![[result valueForKey:@"result"] boolValue]) {
@@ -427,6 +437,7 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
            [_uids count],_url];
     return nil;
   }
+  
   //[self logWithFormat:@"RESULT: %@", result];
   return (id)result;
 }
@@ -510,53 +521,3 @@ static NSTimeInterval PoolScanInterval = 5 * 60;
 }
 
 @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;
-}
-
-- (void)cacheHierarchyResults:(NSDictionary *)_hierarchy {
-  ASSIGNCOPY(self->subfolders, _hierarchy);
-}
-- (NSDictionary *)cachedHierarchyResults {
-  return self->subfolders;
-}
-
-@end /* SOGoMailConnectionEntry */
index a281cca1594d733d2ec92e26d77e63bf0f1045e6..9c8dad696fbf09aeea17bac42db877c2327d5bbb 100644 (file)
@@ -1,3 +1,3 @@
 # $Id$
 
-SUBMINOR_VERSION:=24
+SUBMINOR_VERSION:=26