]> err.no Git - scalable-opengroupware.org/commitdiff
replaced SOGoLRUCache with NSMutableDictionary
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 21 Jul 2005 13:40:52 +0000 (13:40 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 21 Jul 2005 13:40:52 +0000 (13:40 +0000)
added a new shared-mailbox fetch method

git-svn-id: http://svn.opengroupware.org/SOGo/trunk@872 d1b88da0-ebda-0310-925b-ed51d893ca5b

SOGo/SoObjects/SOGo/AgenorUserManager.h
SOGo/SoObjects/SOGo/AgenorUserManager.m
SOGo/SoObjects/SOGo/ChangeLog
SOGo/SoObjects/SOGo/README
SOGo/SoObjects/SOGo/SOGoLRUCache.h
SOGo/SoObjects/SOGo/SOGoLRUCache.m
SOGo/SoObjects/SOGo/Version

index 9b1c4f0505176c3345f92998bd38f7208532aec4..957349b00fffe5d7480feddf2935ea6d54979e42 100644 (file)
   TODO: document
 */
 
-@class NSString, NSArray, NSURL, NSUserDefaults;
-@class SOGoLRUCache;
+@class NSString, NSArray, NSURL, NSUserDefaults, NSMutableDictionary, NSTimer;
+@class NSDictionary;
 @class iCalPerson;
 
 @interface AgenorUserManager : NSObject
 {
-  SOGoLRUCache *cnCache;
-  SOGoLRUCache *serverCache;
-  SOGoLRUCache *uidCache;
-  SOGoLRUCache *emailCache;
-  SOGoLRUCache *shareStoreCache;
-  SOGoLRUCache *shareEMailCache;
-  SOGoLRUCache *changeInternetAccessCache;
-  SOGoLRUCache *internetAutoresponderFlagCache;
-  SOGoLRUCache *intranetAutoresponderFlagCache;
+  NSMutableDictionary *cnCache;
+  NSMutableDictionary *serverCache;
+  NSMutableDictionary *uidCache;
+  NSMutableDictionary *emailCache;
+  NSMutableDictionary *shareStoreCache;
+  NSMutableDictionary *shareEMailCache;
+  NSMutableDictionary *changeInternetAccessCache;
+  NSMutableDictionary *internetAutoresponderFlagCache;
+  NSMutableDictionary *intranetAutoresponderFlagCache;
+  NSTimer *gcTimer;
 }
 
 + (id)sharedUserManager;
@@ -68,6 +69,7 @@
 
 - (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid;
 - (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid;
+- (NSDictionary *)getSharedMailboxesAndEMailsForUID:(NSString *)_uid;
 
 - (NSURL *)getFreeBusyURLForUID:(NSString *)_uid;
 
index fa7d3c7dcef7895568e59aca449db2e96ef2830b..b4cd12943190b836f8caca044f5be8be35382624 100644 (file)
@@ -67,6 +67,8 @@ static NSURL    *AgenorProfileURL             = nil;
 
 static NSArray *fromEMailAttrs = nil;
 
+static unsigned PoolScanInterval = 5 * 60 /* every five minutes */;
+
 + (void)initialize {
   static BOOL didInit = NO;
   NSUserDefaults *ud;
@@ -106,6 +108,13 @@ static NSArray *fromEMailAttrs = nil;
     NSLog(@"ERROR: could not parse AgenorProfileURL: '%@'", tmp);
   else
     NSLog(@"Note: using profile at: %@", [AgenorProfileURL absoluteString]);
+  
+  PoolScanInterval = [[ud objectForKey:@"AgenorCacheCheckInterval"] intValue];
+  if (PoolScanInterval == 0) 
+    PoolScanInterval = 60 * 60 /* every hour */;
+  NSLog(@"AgenorUserManager: flushing caches every %d minutes "
+       @"(AgenorCacheCheckInterval)",
+       PoolScanInterval / 60);
 }
 
 + (id)sharedUserManager {
@@ -118,23 +127,35 @@ static NSArray *fromEMailAttrs = nil;
 - (id)init {
   self = [super init];
   if(self) {
-    self->serverCache     = [[SOGoLRUCache alloc] initWithCacheSize:10000];
-    self->cnCache         = [[SOGoLRUCache alloc] initWithCacheSize:10000];
-    self->uidCache        = [[SOGoLRUCache alloc] initWithCacheSize:10000];
-    self->emailCache      = [[SOGoLRUCache alloc] initWithCacheSize:10000];
-    self->shareStoreCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
-    self->shareEMailCache = [[SOGoLRUCache alloc] initWithCacheSize:10000];
+    self->serverCache     = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    self->cnCache         = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    self->uidCache        = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    self->emailCache      = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    self->shareStoreCache = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    self->shareEMailCache = 
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
     self->changeInternetAccessCache =
-      [[SOGoLRUCache alloc] initWithCacheSize:10000];
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
     self->internetAutoresponderFlagCache =
-      [[SOGoLRUCache alloc] initWithCacheSize:10000];
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
     self->intranetAutoresponderFlagCache =
-      [[SOGoLRUCache alloc] initWithCacheSize:10000];
+      [[NSMutableDictionary alloc] initWithCapacity:10000];
+    
+    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->serverCache     release];
   [self->cnCache         release];
   [self->uidCache        release];
@@ -144,9 +165,32 @@ static NSArray *fromEMailAttrs = nil;
   [self->changeInternetAccessCache      release];
   [self->internetAutoresponderFlagCache release];
   [self->intranetAutoresponderFlagCache release];
+  [self->gcTimer release];
   [super dealloc];
 }
 
+/* cache */
+
+- (void)flush {
+  [self->cnCache         removeAllObjects];
+  [self->serverCache     removeAllObjects];
+  [self->uidCache        removeAllObjects];
+  [self->emailCache      removeAllObjects];
+  [self->shareStoreCache removeAllObjects];
+  [self->shareEMailCache removeAllObjects];
+  
+  [self->changeInternetAccessCache      removeAllObjects];
+  [self->internetAutoresponderFlagCache removeAllObjects];
+  [self->intranetAutoresponderFlagCache removeAllObjects];
+}
+
+- (void)_garbageCollect:(NSTimer *)_timer {
+  [self debugWithFormat:@"flushing caches."];
+  [self flush];
+}
+
+/* LDAP */
+
 - (NGLdapConnection *)ldapConnection {
   static NGLdapConnection *ldapConnection = nil;
   if(!ldapConnection) {
@@ -164,7 +208,7 @@ static NSArray *fromEMailAttrs = nil;
 
 - (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid {
   if (_cn == nil) return;
-  [self->cnCache addObject:_cn forKey:_uid];
+  [self->cnCache setObject:_cn forKey:_uid];
 }
 - (NSString *)_cachedCNForUID:(NSString *)_uid {
   return [self->cnCache objectForKey:_uid];
@@ -172,7 +216,7 @@ static NSArray *fromEMailAttrs = nil;
 
 - (void)_cacheServer:(NSString *)_server forUID:(NSString *)_uid {
   if (_server == nil) return;
-  [self->serverCache addObject:_server forKey:_uid];
+  [self->serverCache setObject:_server forKey:_uid];
 }
 - (NSString *)_cachedServerForUID:(NSString *)_uid {
   return [self->serverCache objectForKey:_uid];
@@ -180,7 +224,7 @@ static NSArray *fromEMailAttrs = nil;
 
 - (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid {
   if (_email == nil) return;
-  [self->emailCache addObject:_email forKey:_uid];
+  [self->emailCache setObject:_email forKey:_uid];
 }
 - (NSString *)_cachedEmailForUID:(NSString *)_uid {
   return [self->emailCache objectForKey:_uid];
@@ -188,7 +232,7 @@ static NSArray *fromEMailAttrs = nil;
 
 - (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email {
   if (_uid == nil) return;
-  [self->uidCache addObject:_uid forKey:_email];
+  [self->uidCache setObject:_uid forKey:_email];
 }
 - (NSString *)_cachedUIDForEmail:(NSString *)_email {
   return [self->uidCache objectForKey:_email];
@@ -305,15 +349,13 @@ static NSArray *fromEMailAttrs = nil;
   for (i = 0; i < count; i++) {
     iCalPerson *p;
     id         uid;
-
+    
     p   = [_persons objectAtIndex:i];
     uid = [self getUIDForICalPerson:p];
-    if (uid) {
+    if (uid != nil)
       [ma addObject:uid];
-    }
-    else if (!uid && _mapStrictly) {
+    else if (uid == nil && _mapStrictly)
       [ma addObject:sharedNull];
-    }
   }
   return ma;
 }
@@ -487,6 +529,8 @@ static NSArray *fromEMailAttrs = nil;
                               @"uid", /* required for shares */
                               @"mineqMelRoutage", 
                               @"mineqMelServeurPrincipal",
+                              @"mineqMelPartages",
+                              mailEmissionAttrName,
                             nil];
   }
   return attrs;
@@ -689,6 +733,135 @@ static NSArray *fromEMailAttrs = nil;
 /* shared mailboxes */
 
 - (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid {
+  NSArray *k;
+  
+  k = [[self getSharedMailboxesAndEMailsForUID:_uid] allKeys];
+  
+  /* ensure that ordering is always the same */
+  return [k sortedArrayUsingSelector:@selector(compare:)];
+}
+
+- (NSString *)emissionEMailFromEntry:(NGLdapEntry *)_entry {
+  id emissionAttr;
+  
+  emissionAttr = [_entry attributeWithName:mailEmissionAttrName];
+  if ([emissionAttr count] == 0) {
+    [self logWithFormat:@"WARNING: share has no %@ attr: %@",
+           mailEmissionAttrName, [_entry dn]];
+    return nil;
+  }
+    
+  if ([emissionAttr count] > 1) {
+    [self logWithFormat:
+           @"WARNING: share has more than one value in %@ attr: %@",
+           mailEmissionAttrName, [_entry dn]];
+    return nil;
+  }
+  
+  return [emissionAttr stringValueAtIndex:0];
+}
+
+- (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid {
+  NSMutableArray   *shares = nil;
+  NGLdapConnection *conn;
+  EOQualifier      *q;
+  NSString         *gPattern, *cPattern;
+  NSEnumerator     *resultEnum;
+  NGLdapEntry      *entry;
+  
+  if ([_uid length] == 0)
+    return nil;
+  
+  if (!useLDAP) {
+    [self logWithFormat:
+           @"Note: LDAP access is disabled, returning no shared froms."];
+    return nil;
+  }
+  
+  /* check cache */
+  if ((shares = [self->shareEMailCache objectForKey:_uid]) != nil)
+    return shares;
+  
+  /* G and C mean "emission access" */
+  gPattern = [_uid stringByAppendingString:@":G"];
+  cPattern = [_uid stringByAppendingString:@":C"];
+  
+  q = [EOQualifier qualifierWithQualifierFormat:
+                    @"((mineqMelPartages = %@) OR (mineqMelPartages = %@)) "
+                    @"AND (objectclass = %@)",
+                  gPattern, cPattern, shareLDAPClass];
+  
+  conn = [self ldapConnection];
+  
+  resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+                    qualifier:q
+                    attributes:fromEMailAttrs];
+  
+  while ((entry = [resultEnum nextObject]) != nil) {
+    NSString *emissionAttr;
+
+    if ((emissionAttr = [self emissionEMailFromEntry:entry]) == nil)
+      continue;
+    
+    if (shares == nil) shares = [NSMutableArray arrayWithCapacity:4];
+    [shares addObject:emissionAttr];
+  }
+  
+  /* ensure that ordering is always the same */
+  [shares sortUsingSelector:@selector(compare:)];
+  
+  /* cache */
+  shares = (shares == nil) ? [NSArray array] : [[shares copy] autorelease];
+  [self->shareEMailCache setObject:shares forKey:_uid];
+  return shares;
+}
+
+/* identities */
+
+- (BOOL)hasUser:(NSString *)_uid partageAccess:(char *)_rightset
+  inEntry:(NGLdapEntry *)_entry
+{
+  NGLdapAttribute *attr;
+  unsigned i, count;
+  
+  attr = [_entry attributeWithName:@"mineqMelPartages"];
+  if ((count = [attr count]) == 0) {
+    [self logWithFormat:@"WARNING: share has no 'mineqMelPartages' attr: %@",
+           [_entry dn]];
+    return NO;
+  }
+  
+  for (i = 0; i < count; i++) {
+    NSString *p;
+    NSRange  r;
+    unichar  c;
+    register unsigned j;
+    
+    p = [attr stringValueAtIndex:i];
+    r = [p rangeOfString:@":"];
+    if (r.length == 0) {
+      [self errorWithFormat:@"Invalid mineqMelPartages value: '%@'", p];
+      continue;
+    }
+    
+    /* check whether prefix matches, eg: "helian.h:G" */
+    if (r.location != [_uid length]) /* check length */
+      continue;
+    if (![p hasPrefix:_uid])
+      continue;
+    
+    c = [p characterAtIndex:(r.location + r.length)];
+    
+    /* check whether permissions match */
+    for (j = 0; _rightset[j] != '\0'; j++) {
+      if (c == _rightset[j])
+       return YES;
+    }
+  }
+  return NO;
+}
+
+- (NSDictionary *)getSharedMailboxesAndEMailsForUID:(NSString *)_uid {
   /*
     Sample:
       "(&(mineqMelPartages=guizmo.g:*)(objectclass=mineqMelBoite))"
@@ -699,8 +872,12 @@ static NSArray *fromEMailAttrs = nil;
       (uid + ".-." + share-uid)
     
     Note: shared mailboxes can be on different hosts!
+    
+    This returns a dictionary where the keys are the IMAP4 connect strings
+    while the values are the emitter addresses for the box or NSNull if the
+    uid is not allowed to emit for this box.
   */
-  NSMutableArray   *shares = nil;
+  NSMutableDictionary *shares = nil;
   NGLdapConnection *conn;
   EOQualifier      *q;
   NSString         *sharePattern;
@@ -733,8 +910,10 @@ static NSArray *fromEMailAttrs = nil;
                     attributes:[self mailServerDiscoveryAttributes]];
   
   while ((entry = [resultEnum nextObject]) != nil) {
-    NSString *server, *shareLogin;
+    NSString *server, *shareLogin, *emitterAddress;
     id shareUid;
+
+    /* calculate server connect string */
     
     if ([(server = [self serverFromEntry:entry]) length] == 0) {
       [self errorWithFormat:@"found no mail server host for share: %@",
@@ -753,86 +932,28 @@ static NSArray *fromEMailAttrs = nil;
     shareLogin = [shareLogin stringByAppendingString:shareUid];
     
     if (shares == nil)
-      shares = [NSMutableArray arrayWithCapacity:4];
+      shares = [NSMutableDictionary dictionaryWithCapacity:4];
     
     shareLogin = [shareLogin stringByAppendingString:@"@"];
     shareLogin = [shareLogin stringByAppendingString:server];
-    [shares addObject:shareLogin];
-  }
-  
-  /* ensure that ordering is always the same */
-  [shares sortUsingSelector:@selector(compare:)];
-  
-  /* cache */
-  shares = (shares == nil) ? [NSArray array] : [[shares copy] autorelease];
-  [self->shareStoreCache addObject:shares forKey:_uid];
-  return shares;
-}
-
-- (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid {
-  NSMutableArray   *shares = nil;
-  NGLdapConnection *conn;
-  EOQualifier      *q;
-  NSString         *gPattern, *cPattern;
-  NSEnumerator     *resultEnum;
-  NGLdapEntry      *entry;
-  
-  if ([_uid length] == 0)
-    return nil;
-  
-  if (!useLDAP) {
-    [self logWithFormat:
-           @"Note: LDAP access is disabled, returning no shared froms."];
-    return nil;
-  }
-  
-  /* check cache */
-  if ((shares = [self->shareEMailCache objectForKey:_uid]) != nil)
-    return shares;
-  
-  /* G and C mean "emission access" */
-  gPattern = [_uid stringByAppendingString:@":G"];
-  cPattern = [_uid stringByAppendingString:@":C"];
-  
-  q = [EOQualifier qualifierWithQualifierFormat:
-                    @"((mineqMelPartages = %@) OR (mineqMelPartages = %@)) "
-                    @"AND (objectclass = %@)",
-                  gPattern, cPattern, shareLDAPClass];
-  
-  conn = [self ldapConnection];
-  
-  resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
-                    qualifier:q
-                    attributes:fromEMailAttrs];
-  
-  while ((entry = [resultEnum nextObject]) != nil) {
-    id emissionAttr;
     
-    emissionAttr = [entry attributeWithName:mailEmissionAttrName];
-    if ([emissionAttr count] == 0) {
-      [self logWithFormat:@"WARNING: share has no %@ attr: %@",
-             mailEmissionAttrName, [entry dn]];
-      continue;
-    }
+    /* calculate emitter address (check for proper access right) */
     
-    if ([emissionAttr count] > 1) {
-      [self logWithFormat:
-             @"WARNING: share has more than one value in %@ attr: %@",
-             mailEmissionAttrName, [entry dn]];
-      continue;
-    }
+    emitterAddress = [self hasUser:_uid partageAccess:"GC" inEntry:entry]
+      ? [self emissionEMailFromEntry:entry]
+      : nil;
     
-    emissionAttr = [emissionAttr stringValueAtIndex:0];
-    if (shares == nil) shares = [NSMutableArray arrayWithCapacity:4];
-    [shares addObject:emissionAttr];
+    /* set value */
+    
+    [shares setObject:(emitterAddress ? emitterAddress : (id)[NSNull null])
+           forKey:shareLogin];
   }
   
-  /* ensure that ordering is always the same */
-  [shares sortUsingSelector:@selector(compare:)];
-  
   /* cache */
-  shares = (shares == nil) ? [NSArray array] : [[shares copy] autorelease];
-  [self->shareEMailCache addObject:shares forKey:_uid];
+  shares = (shares == nil) 
+    ? [NSDictionary dictionary] 
+    : [[shares copy] autorelease];
+  [self->shareStoreCache setObject:shares forKey:_uid];
   return shares;
 }
 
@@ -872,7 +993,7 @@ static NSArray *fromEMailAttrs = nil;
     
     value = [self primaryIsUserAllowedToChangeSOGoInternetAccess:_uid];
     bv    = [NSNumber numberWithBool:value];
-    [self->changeInternetAccessCache addObject:bv forKey:_uid];
+    [self->changeInternetAccessCache setObject:bv forKey:_uid];
   }
   return [bv boolValue];
 }
@@ -925,7 +1046,7 @@ static NSArray *fromEMailAttrs = nil;
     
     value = [self primaryIsInternetAutoresponderEnabledForUser:_uid];
     bv    = [NSNumber numberWithBool:value];
-    [self->internetAutoresponderFlagCache addObject:bv forKey:_uid];
+    [self->internetAutoresponderFlagCache setObject:bv forKey:_uid];
   }
   return [bv boolValue];
 }
@@ -947,7 +1068,7 @@ static NSArray *fromEMailAttrs = nil;
     
     value = [self primaryIsIntranetAutoresponderEnabledForUser:_uid];
     bv    = [NSNumber numberWithBool:value];
-    [self->intranetAutoresponderFlagCache addObject:bv forKey:_uid];
+    [self->intranetAutoresponderFlagCache setObject:bv forKey:_uid];
   }
   return [bv boolValue];
 }
index f5b83e2676a3c37a2cbf5be9666e67f62c7c43ea..c319091940222387170cfa534cb405c2ceccd3b0 100644 (file)
@@ -1,3 +1,10 @@
+2005-07-21  Helge Hess  <helge.hess@opengroupware.org>
+
+       * AgenorUserManager.m: rewrote to use NSMutableDictionary instead of
+         SOGoLRUCache. Flush caches every hour (configurable using
+         'AgenorCacheCheckInterval' default). Added method to retrieve the
+         shares and the emitter emails in one step. (v0.9.67)
+
 2005-07-20  Helge Hess  <helge.hess@opengroupware.org>
 
        * v0.9.66
index 08d4f335629eeeebd6d7971ca47a976fb21472f4..69151e4a746c63c3d4b4a3aa14204aea0748f7d6 100644 (file)
@@ -20,3 +20,10 @@ Class Hierarchy
 TODO
 ====
 - why is SOGoUserFolder an OCS folder?
+
+
+Defaults
+========
+
+AgenorCacheCheckInterval - int (default: 1 hour == 3600s)
+- how often to flush the LDAP caches
index 1d29a504ed8cd49b907be24e0a9bf1b30ebe2f2a..a7cee3c21251ad8a4cb39a8896d1b0d37b718a11 100644 (file)
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
  */
-// $Id$
-
 
 #ifndef        __SOGoLRUCache_H_
 #define        __SOGoLRUCache_H_
 
-
 #import <Foundation/Foundation.h>
 
-
 @interface SOGoLRUCache : NSObject
 {
   unsigned size;
index 3233f7715a1ec331709bbeae9d5d3a31fcd1b738..9fdacf5ca800d53b53befa013b1e87484af8d706 100644 (file)
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
  */
-// $Id$
 
-
-#import "SOGoLRUCache.h"
-#import "common.h"
+#include "SOGoLRUCache.h"
+#include "common.h"
 
 @interface SOGoLRUCacheItem : NSObject
 {
index 46a957653c7c3b9c0d3e2b2f2b6a8de1c9c2ca2e..191e256f179a57f74107541df1590a3971133520 100644 (file)
@@ -1,6 +1,6 @@
 # version file
 
-SUBMINOR_VERSION:=66
+SUBMINOR_VERSION:=67
 
 # v0.9.63 requires libNGiCal          v4.5.54
 # v0.9.60 requires libNGiCal          v4.5.49