From ed715a03418e04cc7d3848a56587ea95cad849f9 Mon Sep 17 00:00:00 2001 From: CaS Date: Wed, 2 Oct 2002 12:11:48 +0000 Subject: [PATCH] Fixups. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14628 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 5 ++ Source/NSDistributedLock.m | 139 +++++++++++++++++++++++++------------ 2 files changed, 101 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9df86f838..2edfbbd5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-10-01 Richard Frith-Macdonald + + * Source/NSDistributedLock.m: Document and tidy. + * Source/NSTimeZone.m: Don't set system zone prematurely. + 2002-10-01 Adam Fedor * config/pathxml.m4: Filter -L/usr/lib out of XML_LIBS. diff --git a/Source/NSDistributedLock.m b/Source/NSDistributedLock.m index ad059d30e..3a72ad1cd 100644 --- a/Source/NSDistributedLock.m +++ b/Source/NSDistributedLock.m @@ -34,24 +34,50 @@ #include +static NSFileManager *mgr = nil; + @implementation NSDistributedLock ++ (void) initialize +{ + if (mgr == nil) + { + mgr = RETAIN([NSFileManager defaultManager]); + } +} + + (NSDistributedLock*) lockWithPath: (NSString*)aPath { return AUTORELEASE([[self alloc] initWithPath: aPath]); } +/** + * Forces release of the lock whether the receiver owns it or not.
+ * Raises an NSGenericException if unable to remove the lock. + */ - (void) breakLock { - NSFileManager *fileManager; + NSDictionary *attributes; - fileManager = [NSFileManager defaultManager]; - if ([fileManager removeFileAtPath: _lockPath handler: nil] == NO) - [NSException raise: NSGenericException - format: @"Failed to remove lock directory '%@' - %s", - _lockPath, GSLastErrorStr(errno)]; - RELEASE(_lockTime); - _lockTime = nil; + DESTROY(_lockTime); + attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES]; + if (attributes != nil) + { + NSDate *modDate = [attributes fileModificationDate]; + + if ([mgr removeFileAtPath: _lockPath handler: nil] == NO) + { + NSString *err = GSLastErrorStr(errno); + + attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES]; + if ([modDate isEqual: [attributes fileModificationDate]] == YES) + { + [NSException raise: NSGenericException + format: @"Failed to remove lock directory '%@' - %s", + _lockPath, err]; + } + } + } } - (void) dealloc @@ -61,18 +87,21 @@ [super dealloc]; } +/** + * Initialises the reciever with the specified filesystem path.
+ * The location in the filesystem must be accessible for this + * to be usable. + */ - (NSDistributedLock*) initWithPath: (NSString*)aPath { - NSFileManager *fileManager; NSString *lockDir; BOOL isDirectory; _lockPath = [aPath copy]; _lockTime = nil; - fileManager = [NSFileManager defaultManager]; lockDir = [_lockPath stringByDeletingLastPathComponent]; - if ([fileManager fileExistsAtPath: lockDir isDirectory: &isDirectory] == NO) + if ([mgr fileExistsAtPath: lockDir isDirectory: &isDirectory] == NO) { NSLog(@"part of the path to the lock file '%@' is missing\n", _lockPath); RELEASE(self); @@ -85,13 +114,13 @@ RELEASE(self); return nil; } - if ([fileManager isWritableFileAtPath: lockDir] == NO) + if ([mgr isWritableFileAtPath: lockDir] == NO) { NSLog(@"parent directory of lock file '%@' is not writable\n", _lockPath); RELEASE(self); return nil; } - if ([fileManager isExecutableFileAtPath: lockDir] == NO) + if ([mgr isExecutableFileAtPath: lockDir] == NO) { NSLog(@"parent directory of lock file '%@' is not accessible\n", _lockPath); @@ -101,30 +130,35 @@ return self; } +/** + * Returns the date at which the lock was aquired by any + * NSDistributedLock using the same path. If nothing has + * the lock, this returns nil. + */ - (NSDate*) lockDate { - NSFileManager *fileManager; NSDictionary *attributes; - fileManager = [NSFileManager defaultManager]; - attributes = [fileManager fileAttributesAtPath: _lockPath traverseLink: YES]; - return [attributes objectForKey: NSFileModificationDate]; + attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES]; + return [attributes fileModificationDate]; } +/** + * Attempt to aquire the lock and return YES on success, NO on failure.
+ * May raise an NSGenericException if a problem occurs. + */ - (BOOL) tryLock { - NSFileManager *fileManager; NSMutableDictionary *attributesToSet; NSDictionary *attributes; BOOL locked; - fileManager = [NSFileManager defaultManager]; attributesToSet = [NSMutableDictionary dictionaryWithCapacity: 1]; [attributesToSet setObject: [NSNumber numberWithUnsignedInt: 0755] forKey: NSFilePosixPermissions]; - locked = [fileManager createDirectoryAtPath: _lockPath - attributes: attributesToSet]; + locked = [mgr createDirectoryAtPath: _lockPath + attributes: attributesToSet]; if (locked == NO) { BOOL dir; @@ -135,10 +169,10 @@ * then either the other process has removed it's lock (and we can retry) * or we have a severe problem! */ - if ([fileManager fileExistsAtPath: _lockPath isDirectory: &dir] == NO) + if ([mgr fileExistsAtPath: _lockPath isDirectory: &dir] == NO) { - locked = [fileManager createDirectoryAtPath: _lockPath - attributes: attributesToSet]; + locked = [mgr createDirectoryAtPath: _lockPath + attributes: attributesToSet]; if (locked == NO) { NSLog(@"Failed to create lock directory '%@' - %s", @@ -149,47 +183,66 @@ if (locked == NO) { - RELEASE(_lockTime); - _lockTime = nil; return NO; } else { - attributes = [fileManager fileAttributesAtPath: _lockPath - traverseLink: YES]; - RELEASE(_lockTime); - _lockTime = RETAIN([attributes objectForKey: NSFileModificationDate]); + attributes = [mgr fileAttributesAtPath: _lockPath + traverseLink: YES]; + if (attributes == nil) + { + [NSException raise: NSGenericException + format: @"Unable to get attributes of lock file we made"]; + } + ASSIGN(_lockTime, [attributes fileModificationDate]); return YES; } } +/** + * Releases the lock. Raises an NSGenericException if unable to release + * the lock (for instance if the receiver does not own it or another + * process has broken it). + */ - (void) unlock { - NSFileManager *fileManager; NSDictionary *attributes; if (_lockTime == nil) - [NSException raise: NSGenericException format: @"not locked by us"]; + { + [NSException raise: NSGenericException format: @"not locked by us"]; + } /* * Don't remove the lock if it has already been broken by someone * else and re-created. Unfortunately, there is a window between * testing and removing, but we do the bset we can. */ - fileManager = [NSFileManager defaultManager]; - attributes = [fileManager fileAttributesAtPath: _lockPath traverseLink: YES]; - if ([_lockTime isEqual: [attributes objectForKey: NSFileModificationDate]]) + attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES]; + if (attributes == nil) { - if ([fileManager removeFileAtPath: _lockPath handler: nil] == NO) - [NSException raise: NSGenericException - format: @"Failed to remove lock directory '%@' - %s", - _lockPath, GSLastErrorStr(errno)]; + DESTROY(_lockTime); + [NSException raise: NSGenericException + format: @"lock '%@' already broken", _lockPath]; + } + if ([_lockTime isEqual: [attributes fileModificationDate]]) + { + DESTROY(_lockTime); + if ([mgr removeFileAtPath: _lockPath handler: nil] == NO) + { + [NSException raise: NSGenericException + format: @"Failed to remove lock directory '%@' - %s", + _lockPath, GSLastErrorStr(errno)]; + } } else - NSLog(@"lock '%@' already broken and in use again\n", _lockPath); - - RELEASE(_lockTime); - _lockTime = nil; + { + DESTROY(_lockTime); + [NSException raise: NSGenericException + format: @"lock '%@' already broken and in use again", + _lockPath]; + } + DESTROY(_lockTime); } @end