Monotone-Parent: ff27cb5c0c118c485e7cf9d8e62d4428edafdb32

Monotone-Revision: 8373ee4a182606382fcb3aea7864b142db4aaa95

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-12-12T18:55:12
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2008-12-12 18:55:12 +00:00
parent 5f04a776f0
commit 72efdaa9a1
5 changed files with 231 additions and 51 deletions

View File

@ -23,6 +23,7 @@
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSTimer.h>
#import <Foundation/NSUserDefaults.h>
@ -44,6 +45,10 @@
(eg missing release due to an exception)
*/
#if defined(THREADSAFE)
static NSLock *lock;
#endif
@interface GCSChannelHandle : NSObject
{
@public
@ -82,6 +87,10 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
[[ud objectForKey: @"GCSChannelCollectionTimer"] intValue];
if (ChannelCollectionTimer < 1)
ChannelCollectionTimer = 5*60;
#if defined(THREADSAFE)
lock = [NSLock new];
#endif
}
+ (NSString *) adaptorNameForURLScheme: (NSString *) _scheme
@ -94,8 +103,14 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
{
static GCSChannelManager *cm = nil;
#if defined(THREADSAFE)
[lock lock];
#endif
if (!cm)
cm = [self new];
#if defined(THREADSAFE)
[lock unlock];
#endif
return cm;
}
@ -184,6 +199,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
{
if ((key = [self databaseKeyForURL: _url]))
{
#if defined(THREADSAFE)
[lock lock];
#endif
adaptor = [urlToAdaptor objectForKey: key];
if (adaptor)
[self debugWithFormat: @"using cached adaptor: %@", adaptor];
@ -215,6 +233,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
[urlToAdaptor setObject: adaptor forKey: key];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
}
}
@ -295,6 +316,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
/* look for cached handles */
#if defined(THREADSAFE)
[lock lock];
#endif
handle = [self findAvailChannelHandleForURL: _url];
if (handle)
{
@ -339,6 +363,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
channel, [_url absoluteString]];
}
}
#if defined(THREADSAFE)
[lock unlock];
#endif
return channel;
}
@ -347,6 +374,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
{
GCSChannelHandle *handle;
#if defined(THREADSAFE)
[lock lock];
#endif
handle = [self findBusyChannelHandleForChannel: _channel];
if (handle)
{
@ -380,6 +410,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
[_channel release];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
}
/* checking for tables */
@ -428,6 +461,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
unsigned i, count;
GCSChannelHandle *handle;
#if defined(THREADSAFE)
[lock lock];
#endif
count = [availableChannels count];
if (count)
{
@ -462,6 +498,9 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60;
[handlesToRemove release];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
}
/* debugging */

View File

@ -19,7 +19,23 @@
02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <NGExtensions/NGResourceLocator.h>
#import <unistd.h>
#import "GCSFolderManager.h"
#import "GCSChannelManager.h"
@ -27,11 +43,6 @@
#import "GCSFolder.h"
#import "NSURL+GCS.h"
#import "EOAdaptorChannel+GCS.h"
#import "common.h"
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <NGExtensions/NGResourceLocator.h>
#import <unistd.h>
/*
Required database schema:
@ -64,6 +75,10 @@ static NSString *GCSGenericFolderTypeName = @"Container";
static const char *GCSPathColumnPattern = "c_path%i";
static NSCharacterSet *asciiAlphaNumericCS = nil;
#if defined(THREADSAFE)
static NSLock *lock;
#endif
+ (void) initialize
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
@ -76,6 +91,9 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
debugOn = [ud boolForKey: @"GCSFolderManagerDebugEnabled"];
debugSQLGen = [ud boolForKey: @"GCSFolderManagerSQLDebugEnabled"];
emptyArray = [[NSArray alloc] init];
#if defined(THREADSAFE)
lock = [NSLock new];
#endif
if (!asciiAlphaNumericCS)
{
asciiAlphaNumericCS
@ -90,26 +108,34 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
+ (id)defaultFolderManager {
NSString *s;
NSURL *url;
if (fm) return fm;
s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSFolderInfoURL"];
if ([s length] == 0) {
NSLog(@"ERROR(%s): default 'OCSFolderInfoURL' is not configured.",
__PRETTY_FUNCTION__);
return nil;
}
if ((url = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSFolderInfoURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
if ((fm = [[self alloc] initWithFolderInfoLocation:url]) == nil) {
NSLog(@"ERROR(%s): could not create folder manager with URL: '%@'",
__PRETTY_FUNCTION__, [url absoluteString]);
return nil;
}
NSLog(@"Note: setup default manager at: %@", url);
#if defined(THREADSAFE)
[lock lock];
#endif
if (!fm)
{
s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSFolderInfoURL"];
if ([s length] == 0) {
NSLog(@"ERROR(%s): default 'OCSFolderInfoURL' is not configured.",
__PRETTY_FUNCTION__);
return nil;
}
if ((url = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSFolderInfoURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
if ((fm = [[self alloc] initWithFolderInfoLocation:url]) == nil) {
NSLog(@"ERROR(%s): could not create folder manager with URL: '%@'",
__PRETTY_FUNCTION__, [url absoluteString]);
return nil;
}
NSLog(@"Note: setup default manager at: %@", url);
}
#if defined(THREADSAFE)
[lock unlock];
#endif
return fm;
}
@ -199,6 +225,7 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
ch = [[self channelManager] acquireOpenChannelForURL:
[self folderInfoLocation]];
return ch;
}
- (void)releaseChannel:(EOAdaptorChannel *)_channel {

View File

@ -23,6 +23,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimer.h>
#import <Foundation/NSUserDefaults.h>
@ -38,6 +39,10 @@ static NSString *LDAPContactInfoAttribute = nil;
static BOOL defaultMailDomainIsConfigured = NO;
static BOOL forceImapLoginWithEmail = NO;
#if defined(THREADSAFE)
static NSLock *lock;
#endif
@implementation LDAPUserManager
+ (void) initialize
@ -64,6 +69,9 @@ static BOOL forceImapLoginWithEmail = NO;
}
if (!forceImapLoginWithEmail)
forceImapLoginWithEmail = [ud boolForKey: @"SOGoForceIMAPLoginWithEmail"];
#if defined(THREADSAFE)
lock = [NSLock new];
#endif
}
+ (BOOL) defaultMailDomainIsConfigured
@ -75,8 +83,14 @@ static BOOL forceImapLoginWithEmail = NO;
{
static id sharedUserManager = nil;
#if defined(THREADSAFE)
[lock lock];
#endif
if (!sharedUserManager)
sharedUserManager = [self new];
#if defined(THREADSAFE)
[lock unlock];
#endif
return sharedUserManager;
}
@ -149,16 +163,18 @@ static BOOL forceImapLoginWithEmail = NO;
cleanupInterval = 0.0;
if (cleanupInterval > 0.0)
{
cleanupTimer = [NSTimer scheduledTimerWithTimeInterval: cleanupInterval
target: self
selector: @selector (_cleanupSources)
userInfo: nil
repeats: YES];
cleanupTimer
= [NSTimer scheduledTimerWithTimeInterval: cleanupInterval
target: self
selector: @selector (_cleanupSources)
userInfo: nil
repeats: YES];
[self logWithFormat: @"cleanup interval set every %f seconds",
cleanupInterval];
}
else
[self logWithFormat: @"no cleanup interval set: memory usage will grow"];
[self
logWithFormat: @"no cleanup interval set: memory usage will grow"];
[self _prepareLDAPSourcesWithDefaults: ud];
}
@ -300,6 +316,10 @@ static BOOL forceImapLoginWithEmail = NO;
NSMutableDictionary *currentUser;
NSString *dictPassword;
#if defined(THREADSAFE)
[lock lock];
#endif
currentUser = [users objectForKey: login];
dictPassword = [currentUser objectForKey: @"password"];
if (currentUser && dictPassword)
@ -323,6 +343,10 @@ static BOOL forceImapLoginWithEmail = NO;
[currentUser setObject: cleanupDate forKey: @"cleanupDate"];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
return checkOK;
}
@ -402,12 +426,18 @@ static BOOL forceImapLoginWithEmail = NO;
NSString *key;
NSEnumerator *emails;
#if defined(THREADSAFE)
[lock lock];
#endif
key = [newUser objectForKey: @"c_uid"];
if (key)
[users setObject: newUser forKey: key];
emails = [[newUser objectForKey: @"emails"] objectEnumerator];
while ((key = [emails nextObject]))
[users setObject: newUser forKey: key];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
- (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid
@ -420,6 +450,9 @@ static BOOL forceImapLoginWithEmail = NO;
{
contactInfos = [NSMutableDictionary dictionary];
currentUser = [users objectForKey: uid];
#if defined(THREADSAFE)
[lock lock];
#endif
if (!([currentUser objectForKey: @"emails"]
&& [currentUser objectForKey: @"cn"]))
{
@ -446,6 +479,9 @@ static BOOL forceImapLoginWithEmail = NO;
cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval];
[currentUser setObject: cleanupDate forKey: @"cleanupDate"];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
}
else
currentUser = nil;
@ -453,18 +489,6 @@ static BOOL forceImapLoginWithEmail = NO;
return currentUser;
}
- (void) _fillContactsMailRecords: (NSEnumerator *) contacts
{
NSMutableDictionary *currentContact;
currentContact = [contacts nextObject];
while (currentContact)
{
[self _fillContactMailRecords: currentContact];
currentContact = [contacts nextObject];
}
}
- (NSArray *) _compactAndCompleteContacts: (NSEnumerator *) contacts
{
NSMutableDictionary *compactContacts, *returnContact;
@ -517,10 +541,11 @@ static BOOL forceImapLoginWithEmail = NO;
[returnContact setObject: infoAttribute
forKey: LDAPContactInfoAttribute];
}
[self _fillContactMailRecords: returnContact];
}
}
newContacts = [compactContacts allValues];
[self _fillContactsMailRecords: [newContacts objectEnumerator]];
return newContacts;
}
@ -565,6 +590,10 @@ static BOOL forceImapLoginWithEmail = NO;
NSDate *now;
unsigned int count;
#if defined(THREADSAFE)
[lock lock];
#endif
now = [NSDate date];
count = 0;
@ -583,6 +612,10 @@ static BOOL forceImapLoginWithEmail = NO;
if (count)
[self logWithFormat: @"cleaned %d users records from cache", count];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
@end

View File

@ -25,6 +25,7 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSDistributedNotificationCenter.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimer.h>
#import <Foundation/NSUserDefaults.h>
@ -51,8 +52,19 @@ static NSMutableDictionary *s_userSettings = nil;
static SOGoCache *sharedCache = nil;
#if defined(THREADSAFE)
static NSLock *lock;
#endif
@implementation SOGoCache
#if defined(THREADSAFE)
+ (void) initialize
{
lock = [NSLock new];
}
#endif
+ (NSTimeInterval) cleanupInterval
{
return cleanupInterval;
@ -60,16 +72,28 @@ static SOGoCache *sharedCache = nil;
+ (SOGoCache *) sharedCache
{
#if defined(THREADSAFE)
[lock lock];
#endif
if (!sharedCache)
sharedCache = [self new];
#if defined(THREADSAFE)
[lock unlock];
#endif
return sharedCache;
}
+ (void) killCache
{
#if defined(THREADSAFE)
[lock lock];
#endif
[cache removeAllObjects];
[users removeAllObjects];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
- (id) init
@ -134,7 +158,7 @@ static SOGoCache *sharedCache = nil;
}
- (NSString *) _pathFromObject: (SOGoObject *) container
withName: (NSString *) name
withName: (NSString *) name
{
NSString *fullPath, *nameInContainer;
NSMutableArray *names;
@ -169,13 +193,19 @@ static SOGoCache *sharedCache = nil;
inContainer: [container container]];
fullPath = [self _pathFromObject: container
withName: name];
#if defined(THREADSAFE)
[lock lock];
#endif
if (![cache objectForKey: fullPath])
{
// NSLog (@"registering '%@'", fullPath);
// NSLog (@"registering '%@'", fullPath);
[cache setObject: object forKey: fullPath];
}
// else
// NSLog (@"'%@' already registered", fullPath);
#if defined(THREADSAFE)
[lock unlock];
#endif
// else
// NSLog (@"'%@' already registered", fullPath);
}
}
@ -188,14 +218,20 @@ static SOGoCache *sharedCache = nil;
withName: name];
return [cache objectForKey: fullPath];
// if (object)
// NSLog (@"found cached object '%@'", fullPath);
// if (object)
// NSLog (@"found cached object '%@'", fullPath);
}
- (void) registerUser: (SOGoUser *) user
{
#if defined(THREADSAFE)
[lock lock];
#endif
[users setObject: user
forKey: [user login]];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
- (id) userNamed: (NSString *) name
@ -214,11 +250,17 @@ static SOGoCache *sharedCache = nil;
{
NSDate *cleanupDate;
#if defined(THREADSAFE)
[lock lock];
#endif
cleanupDate = [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]];
[s_userDefaults setObject: [NSDictionary dictionaryWithObjectsAndKeys:
theDefaults, @"dictionary",
cleanupDate, @"cleanupDate", nil]
forKey: login];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
+ (NSDictionary *) cachedUserSettings
@ -231,11 +273,17 @@ static SOGoCache *sharedCache = nil;
{
NSDate *cleanupDate;
#if defined(THREADSAFE)
[lock lock];
#endif
cleanupDate = [[NSDate date] addTimeInterval: [SOGoCache cleanupInterval]];
[s_userSettings setObject: [NSDictionary dictionaryWithObjectsAndKeys:
theSettings, @"dictionary",
cleanupDate, @"cleanupDate", nil]
forKey: login];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
- (void) _userDefaultsHaveChanged: (NSNotification *) theNotification
@ -245,6 +293,9 @@ static SOGoCache *sharedCache = nil;
uid = [[theNotification userInfo] objectForKey: @"uid"];
#if defined(THREADSAFE)
[lock lock];
#endif
if ((user = [users objectForKey: uid]))
{
[[user userDefaults] setValues: [[theNotification userInfo] objectForKey: @"values"]];
@ -254,6 +305,9 @@ static SOGoCache *sharedCache = nil;
{
[s_userDefaults removeObjectForKey: uid];
}
#if defined(THREADSAFE)
[lock unlock];
#endif
}
- (void) _userSettingsHaveChanged: (NSNotification *) theNotification
@ -283,6 +337,10 @@ static SOGoCache *sharedCache = nil;
unsigned int count;
#if defined(THREADSAFE)
[lock lock];
#endif
now = [NSDate date];
// We cleanup the user defaults
@ -317,7 +375,12 @@ static SOGoCache *sharedCache = nil;
}
if (count)
[self logWithFormat: @"cleaned %d users records from user settings cache", count];
[self logWithFormat: @"cleaned %d users records from user settings cache",
count];
#if defined(THREADSAFE)
[lock unlock];
#endif
}
@end

18
configure vendored
View File

@ -18,6 +18,7 @@ ARG_GSMAKE=`gnustep-config --variable=GNUSTEP_MAKEFILES 2>/dev/null`
ARG_CFGMAKE="$PWD/config.make"
ARG_WITH_DEBUG=1
ARG_WITH_STRIP=0
ARG_WITH_THREADS=0
ARG_WITH_LDAP_CONFIG=0
GNUSTEP_INSTALLATION_DOMAIN="LOCAL"
@ -58,6 +59,7 @@ Installation directories:
--configmake=PATH path to the config file being created
--enable-debug turn on debugging and compile time warnings
--enable-strip turn on stripping of debug symbols
--enable-thread-safety turn on thread-safety
--enable-ldap-config enable LDAP based configuration of SOGo
@ -83,6 +85,11 @@ printParas() {
else
echo " strip: no";
fi
if test $ARG_WITH_THREADS = 1; then
echo " thread-safe: yes";
else
echo " thread-safe: no";
fi
if test $ARG_WITH_LDAP_CONFIG = 1; then
echo " ldap-based configuration: yes";
else
@ -261,6 +268,11 @@ genConfigMake() {
fi
cfgwrite ""
if test $ARG_WITH_THREADS = 1; then
cfgwrite "# configured to produce thread-safe code";
cfgwrite "ADDITIONAL_CPPFLAGS += -DTHREADSAFE=1"
fi
cfgwrite "# enforce shared libraries";
cfgwrite "shared:=yes"
cfgwrite ""
@ -393,6 +405,12 @@ processOption() {
"x--disable-strip")
ARG_WITH_STRIP=0
;;
"x--enable-thread-safety")
ARG_WITH_THREADS=1
;;
"x--disable-thread-safety")
ARG_WITH_THREADS=0
;;
"x--enable-ldap-config")
ARG_WITH_LDAP_CONFIG=1