mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-14 15:41:00 +00:00
Rewrite launching to make the LaunchInfo instances control most of the work and to use individual timers for each instance with the aim of simplifying launch and shutdown logic and alarms
This commit is contained in:
parent
48d84025c4
commit
9934bbbdf2
7 changed files with 1787 additions and 1100 deletions
|
@ -51,6 +51,7 @@ inner_main()
|
|||
|
||||
defs = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"NO", @"Daemon",
|
||||
@"YES", @"Transient",
|
||||
#if defined(EC_REGISTRATION_DOMAIN)
|
||||
EC_REGISTRATION_DOMAIN
|
||||
#endif
|
||||
|
|
11
EcClientI.h
11
EcClientI.h
|
@ -42,34 +42,39 @@
|
|||
id<CmdClient> theServer;
|
||||
id obj; /* The proxy object of client. */
|
||||
NSString *name; /* The name of the client. */
|
||||
NSDate *lastUnanswered; /* Last unanswered ping. */
|
||||
NSDate *outstanding; /* Time of outstanding ping. */
|
||||
NSDate *delayed; /* When we had a ping delay. */
|
||||
NSDate *recovered; /* Time of recovery from delay. */
|
||||
unsigned fwdSequence; /* Last ping sent TO client. */
|
||||
unsigned revSequence; /* Last gnip sent BY client. */
|
||||
NSMutableSet *files; /* Want update info for these. */
|
||||
NSData *config; /* Config info for client. */
|
||||
BOOL pingOk; /* Can remote end accept ping? */
|
||||
BOOL transient; /* Is this a transient client? */
|
||||
BOOL unregistered; /* Has client unregistered? */
|
||||
int processIdentifier; /* Process ID if known (or 0). */
|
||||
}
|
||||
- (NSComparisonResult) compare: (EcClientI*)other;
|
||||
- (NSData*) config;
|
||||
- (NSDate*) delayed;
|
||||
- (NSMutableSet*) files;
|
||||
- (BOOL) gnip: (unsigned)seq;
|
||||
- (id) initFor: (id)obj
|
||||
name: (NSString*)n
|
||||
with: (id<CmdClient>)svr;
|
||||
- (NSDate*) lastUnanswered;
|
||||
- (NSDate*) outstanding;
|
||||
- (NSString*) name;
|
||||
- (id) obj;
|
||||
- (void) ping;
|
||||
- (int) processIdentifier;
|
||||
- (NSDate*) recovered;
|
||||
- (void) setConfig: (NSData*)c;
|
||||
- (void) setName: (NSString*)n;
|
||||
- (void) setObj: (id)o;
|
||||
- (void) setProcessIdentifier: (int)p;
|
||||
- (void) setServer: (id<CmdClient>)s;
|
||||
- (void) setTransient: (BOOL)flag;
|
||||
- (void) setUnregistered: (BOOL)flag;
|
||||
- (BOOL) transient;
|
||||
- (BOOL) unregistered;
|
||||
@end
|
||||
|
||||
|
|
65
EcClientI.m
65
EcClientI.m
|
@ -71,7 +71,9 @@
|
|||
}
|
||||
RELEASE(c);
|
||||
}
|
||||
DESTROY(lastUnanswered);
|
||||
DESTROY(outstanding);
|
||||
DESTROY(delayed);
|
||||
DESTROY(recovered);
|
||||
DESTROY(config);
|
||||
DESTROY(files);
|
||||
DESTROY(name);
|
||||
|
@ -79,6 +81,11 @@
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSDate*) delayed
|
||||
{
|
||||
return delayed;
|
||||
}
|
||||
|
||||
- (NSMutableSet*) files
|
||||
{
|
||||
return files;
|
||||
|
@ -95,9 +102,16 @@
|
|||
}
|
||||
}
|
||||
revSequence = s;
|
||||
if (nil == recovered && nil != delayed)
|
||||
{
|
||||
/* We were in a sequence of delayed pings, so we need to record
|
||||
* that we have ended that sequence.
|
||||
*/
|
||||
ASSIGN(recovered, [NSDate date]);
|
||||
}
|
||||
DESTROY(outstanding);
|
||||
if (revSequence == fwdSequence)
|
||||
{
|
||||
DESTROY(lastUnanswered);
|
||||
return YES; /* up to date */
|
||||
}
|
||||
else
|
||||
|
@ -113,20 +127,17 @@
|
|||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
theServer = s;
|
||||
files = [NSMutableSet new];
|
||||
[self setObj: o];
|
||||
[self setName: n];
|
||||
pingOk = [o respondsToSelector: @selector(cmdPing:sequence:extra:)];
|
||||
if (pingOk == NO)
|
||||
NSLog(@"Warning - %@ is an old server ... it can't be pinged", n);
|
||||
[self setServer: s];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDate*) lastUnanswered
|
||||
- (NSDate*) outstanding
|
||||
{
|
||||
return lastUnanswered;
|
||||
return outstanding;
|
||||
}
|
||||
|
||||
- (NSString*) name
|
||||
|
@ -141,13 +152,9 @@
|
|||
|
||||
- (void) ping
|
||||
{
|
||||
if (pingOk == NO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fwdSequence == revSequence)
|
||||
{
|
||||
lastUnanswered = [[NSDate date] retain];
|
||||
ASSIGN(outstanding, [NSDate date]);
|
||||
NS_DURING
|
||||
{
|
||||
[obj cmdPing: theServer sequence: ++fwdSequence extra: nil];
|
||||
|
@ -160,6 +167,23 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
if (recovered != nil)
|
||||
{
|
||||
/* The connection had recovered from a late ping response,
|
||||
* but now we have another delayed ping, so we discard the
|
||||
* information about the previous delay/recovery sequence
|
||||
* in order to start another.
|
||||
*/
|
||||
DESTROY(recovered);
|
||||
DESTROY(delayed);
|
||||
}
|
||||
if (nil == delayed)
|
||||
{
|
||||
/* This ping is the first one delayed, so we need to record
|
||||
* the timestamp at which the delay started.
|
||||
*/
|
||||
ASSIGN(delayed, outstanding);
|
||||
}
|
||||
NSLog(@"Ping to %@ when one is already in progress.", name);
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +193,11 @@
|
|||
return processIdentifier;
|
||||
}
|
||||
|
||||
- (NSDate*) recovered
|
||||
{
|
||||
return recovered;
|
||||
}
|
||||
|
||||
- (void) setConfig: (NSData*)c
|
||||
{
|
||||
ASSIGN(config, c);
|
||||
|
@ -189,6 +218,11 @@
|
|||
processIdentifier = p;
|
||||
}
|
||||
|
||||
- (void) setServer: (id<CmdClient>)s
|
||||
{
|
||||
theServer = s;
|
||||
}
|
||||
|
||||
- (void) setTransient: (BOOL)flag
|
||||
{
|
||||
transient = flag ? YES : NO;
|
||||
|
@ -206,6 +240,11 @@
|
|||
{
|
||||
return transient;
|
||||
}
|
||||
|
||||
- (BOOL) unregistered
|
||||
{
|
||||
return unregistered;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
|
2714
EcCommand.m
2714
EcCommand.m
File diff suppressed because it is too large
Load diff
|
@ -2395,7 +2395,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
|
|||
while (count-- > 0)
|
||||
{
|
||||
EcClientI *r = [commands objectAtIndex: count];
|
||||
NSDate *d = [r lastUnanswered];
|
||||
NSDate *d = [r outstanding];
|
||||
|
||||
if (d != nil && [d timeIntervalSinceDate: now] < -pingDelay)
|
||||
{
|
||||
|
@ -2424,7 +2424,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
|
|||
while (count-- > 0)
|
||||
{
|
||||
EcClientI *r = [consoles objectAtIndex: count];
|
||||
NSDate *d = [r lastUnanswered];
|
||||
NSDate *d = [r outstanding];
|
||||
|
||||
if (d != nil && [d timeIntervalSinceDate: now] < -pingDelay)
|
||||
{
|
||||
|
|
|
@ -97,7 +97,7 @@ typedef enum {
|
|||
@end
|
||||
|
||||
/** The CmdConfig protocol is needed by objects that send and receive
|
||||
* configuarion information.
|
||||
* configuration information.
|
||||
*/
|
||||
@protocol CmdConfig
|
||||
- (oneway void) requestConfigFor: (id<CmdConfig>)c;
|
||||
|
|
90
EcProcess.m
90
EcProcess.m
|
@ -2779,6 +2779,8 @@ static BOOL ecDidAwaken = NO;
|
|||
[ecLock lock];
|
||||
if (0.0 == beganQuitting)
|
||||
{
|
||||
NSLog(@"-[%@ ecQuit: %@ for: %ld]", NSStringFromClass([self class]),
|
||||
reason, (long)status);
|
||||
ASSIGN(ecQuitReason, reason);
|
||||
ecQuitStatus = status;
|
||||
}
|
||||
|
@ -3718,9 +3720,10 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
- (int) ecRun
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
NSConnection *c;
|
||||
NSRunLoop *loop;
|
||||
NSDate *future;
|
||||
NSSocketPortNameServer *ns;
|
||||
NSString *name;
|
||||
NSRunLoop *loop;
|
||||
NSDate *future;
|
||||
|
||||
if (YES == cmdIsTransient)
|
||||
{
|
||||
|
@ -3730,17 +3733,14 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
return 1;
|
||||
}
|
||||
|
||||
NSAssert(nil == EcProcConnection, NSGenericException);
|
||||
c = [[NSConnection alloc] initWithReceivePort: (NSPort*)[NSSocketPort port]
|
||||
sendPort: nil];
|
||||
[c setRootObject: self];
|
||||
|
||||
if ([c registerName: [self cmdName]
|
||||
withNameServer: [NSSocketPortNameServer sharedInstance]] == NO)
|
||||
NSAssert(nil != EcProcConnection, NSGenericException);
|
||||
ns = [NSSocketPortNameServer sharedInstance];
|
||||
name = [self cmdName];
|
||||
if ([EcProcConnection registerName: name withNameServer: ns] == NO)
|
||||
{
|
||||
EcAlarm *a;
|
||||
|
||||
DESTROY(c);
|
||||
DESTROY(EcProcConnection);
|
||||
NSLog(@"Unable to register with name server. Perhaps a copy of this process is already running (or is hung or blocked waiting for a database query etc), or perhaps an old version was killed and is still registered. Check the state of any running process and and check the process registration with gdomap.");
|
||||
|
||||
a = [EcAlarm alarmForManagedObject: nil
|
||||
|
@ -3774,16 +3774,21 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
[self alarm: a];
|
||||
}
|
||||
|
||||
[c setDelegate: self];
|
||||
[EcProcConnection setDelegate: self];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(cmdConnectionBecameInvalid:)
|
||||
name: NSConnectionDidDieNotification
|
||||
object: c];
|
||||
EcProcConnection = c;
|
||||
object: EcProcConnection];
|
||||
|
||||
[self _connectionRegistered];
|
||||
|
||||
/* Now that startup has completed and we are registered under our normal
|
||||
* name, we should remove the name used during startup.
|
||||
*/
|
||||
name = [name stringByAppendingString: @" (starting)"];
|
||||
[ns removePortForName: name];
|
||||
|
||||
/* Called to permit subclasses to initialise before entering run loop.
|
||||
*/
|
||||
[self ecAwaken];
|
||||
|
@ -5232,6 +5237,8 @@ With two parameters ('maximum' and a number),\n\
|
|||
[ecLock lock];
|
||||
if (0.0 == beganQuitting)
|
||||
{
|
||||
NSLog(@"-[%@ cmdQuit: %ld]", NSStringFromClass([self class]),
|
||||
(long)status);
|
||||
ASSIGN(ecQuitReason, nil);
|
||||
ecQuitStatus = status;
|
||||
}
|
||||
|
@ -5280,6 +5287,47 @@ With two parameters ('maximum' and a number),\n\
|
|||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) ecPrepareUnique
|
||||
{
|
||||
NSSocketPortNameServer *ns = [NSSocketPortNameServer sharedInstance];
|
||||
NSString *name = [self cmdName];
|
||||
NSString *prep = [name stringByAppendingString: @" (starting)"];
|
||||
NSPort *p;
|
||||
|
||||
/* First try registering as a non-functional process using our unique
|
||||
* name with th suffix '(starting)' to prevent other instances trying
|
||||
* to start up at the same time.
|
||||
*/
|
||||
p = (NSPort*)[NSSocketPort port];
|
||||
EcProcConnection = [[NSConnection alloc] initWithReceivePort: p
|
||||
sendPort: nil];
|
||||
[EcProcConnection setRootObject: self];
|
||||
if ([EcProcConnection registerName: prep withNameServer: ns] == NO)
|
||||
{
|
||||
p = [ns portForName: prep onHost: @""];
|
||||
DESTROY(EcProcConnection);
|
||||
NSLog(@"There is already a process: %@, on %@", prep, p);
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Now check to see if there is an instance already running.
|
||||
*/
|
||||
p = [ns portForName: name onHost: @""];
|
||||
if (nil != p)
|
||||
{
|
||||
[ns removePortForName: prep];
|
||||
DESTROY(EcProcConnection);
|
||||
NSLog(@"There is already a process: %@, on %@", name, p);
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Yippee ... there is no other copy of this process running and we have
|
||||
* grabbed the name of a process starting up, so no other process can
|
||||
* conflict with our startup.
|
||||
*/
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id) initWithDefaults: (NSDictionary*) defs
|
||||
{
|
||||
[ecLock lock];
|
||||
|
@ -5386,6 +5434,17 @@ With two parameters ('maximum' and a number),\n\
|
|||
return nil;
|
||||
}
|
||||
|
||||
cmdIsTransient = [cmdDefs boolForKey: @"Transient"];
|
||||
if (NO == cmdIsTransient)
|
||||
{
|
||||
if (NO == [self ecPrepareUnique])
|
||||
{
|
||||
RELEASE(self);
|
||||
[ecLock unlock];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
switch (i)
|
||||
|
@ -5457,6 +5516,7 @@ With two parameters ('maximum' and a number),\n\
|
|||
hdl = [self cmdLogFile: cmdDebugName];
|
||||
if (hdl == nil)
|
||||
{
|
||||
DESTROY(EcProcConnection);
|
||||
[ecLock unlock];
|
||||
exit(1);
|
||||
}
|
||||
|
@ -5478,8 +5538,6 @@ With two parameters ('maximum' and a number),\n\
|
|||
|
||||
[self cmdDefaultsChanged: nil];
|
||||
|
||||
cmdIsTransient = [cmdDefs boolForKey: @"Transient"];
|
||||
|
||||
if ([cmdDefs objectForKey: @"CmdInterval"] != nil)
|
||||
{
|
||||
[self setCmdInterval: [cmdDefs floatForKey: @"CmdInterval"]];
|
||||
|
|
Loading…
Reference in a new issue