diff --git a/ChangeLog b/ChangeLog index dc291dd..d2d1468 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2014-10-23 Richard Frith-Macdonald + + * EcCommand.m: + * Control.plist: + Add LaunchOrder config to control the order in which services are + handled by the Command server. By default we now do them in + lexicographic order rather than leaving the order undefined. + 2014-09-16 Richard Frith-Macdonald * EcCommand.m: Simplify handling of loss of process and configuration diff --git a/Control.plist b/Control.plist index faf52c3..1e2c18b 100644 --- a/Control.plist +++ b/Control.plist @@ -8,6 +8,10 @@ /* Common section for all processes on any/all hosts. */ }; + Feep = { + /* Section for the process Feep on any/all hosts. + */ + }; Foo = { /* Section for the process Foo on any/all hosts. */ @@ -20,6 +24,10 @@ /* Common section for any/all processses on localhost. */ }; + Bar = { + /* Section for process Bar on localhost + */ + }; Foo = { /* Section for process Foo on localhost */ @@ -29,12 +37,31 @@ */ Launch = { Foo = { - Prog = "/usr/GNUstep/Local/Tools/Foo"; // Path to binary + Prog = "/usr/GNUstep/Local/Tools/Foo"; // Full path to binary Home = "~xxx/Test"; // Directory to run in Args = ("-Debug", "YES"); // Args to launch with Auto = NO; // Auto-launch? }; + Bar = { + Prog = "Bar"; // RName of binary + Home = "~xxx/Test"; // Directory to run in + Args = ("-Debug", "YES"); // Args to launch with + Auto = YES; // Auto-launch? + }; + Feep = { + Prog = "Feep"; // RName of binary + Home = "~xxx/Test"; // Directory to run in + Auto = YES; // Auto-launch? + }; }; + /* Specify launch order ... Feep first, Bar second + * Processes not listed here are launched in lexicographical order + * after any processes which are listed. + */ + LaunchOrder = ( + Feep, // Launch Feep first + Bar // Launch Bar second + ); }; }; } diff --git a/EcCommand.m b/EcCommand.m index a419375..fcaf7fd 100644 --- a/EcCommand.m +++ b/EcCommand.m @@ -126,6 +126,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSString *logname; NSMutableDictionary *config; NSDictionary *launchInfo; + NSArray *launchOrder; NSDictionary *environment; NSMutableDictionary *launches; NSMutableSet *launching; @@ -306,9 +307,11 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) d = [config objectForKey: [self cmdName]]; DESTROY(launchInfo); + DESTROY(launchOrder); DESTROY(environment); if ([d isKindOfClass: [NSDictionary class]] == YES) { + id o; NSMutableDictionary *m; NSString *k; NSString *err = nil; @@ -446,6 +449,67 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) } } RETAIN(launchInfo); + + o = [d objectForKey: @"LaunchOrder"]; + if (NO == [o isKindOfClass: [NSArray class]]) + { + if (nil != o) + { + NSLog(@"bad 'LaunchOrder' config (not an array) ignored"); + } + /* The default launch order is alphabetical by server name. + */ + o = [[launchInfo allKeys] sortedArrayUsingSelector: + @selector(compare:)]; + launchOrder = RETAIN(o); + } + else + { + NSMutableArray *m; + NSEnumerator *e; + NSString *k; + NSUInteger c; + + m = AUTORELEASE([o mutableCopy]); + c = [m count]; + while (c-- > 0) + { + o = [m objectAtIndex: c]; + if (NO == [o isKindOfClass: [NSString class]]) + { + NSLog(@"bad 'LaunchOrder' item ('%@' at %u) ignored" + @" (not a server name)", o, (unsigned)c); + [m removeObjectAtIndex: c]; + } + else if ([m indexOfObject: o] != c) + { + NSLog(@"bad 'LaunchOrder' item ('%@' at %u) ignored" + @" (repeat of earlier item)", o, (unsigned)c); + [m removeObjectAtIndex: c]; + } + else if (nil == [launchInfo objectForKey: o]) + { + NSLog(@"bad 'LaunchOrder' item ('%@' at %u) ignored" + @" (not in 'Launch' dictionary)", o, (unsigned)c); + [m removeObjectAtIndex: c]; + } + } + /* Any missing servers are launched after others + * they are in lexicographic order. + */ + o = [[launchInfo allKeys] sortedArrayUsingSelector: + @selector(compare:)]; + e = [o objectEnumerator]; + while (nil != (k = [e nextObject])) + { + if (NO == [m containsObject: k]) + { + [m addObject: k]; + } + } + launchOrder = [m copy]; + } + environment = [d objectForKey: @"Environment"]; if ([environment isKindOfClass: [NSDictionary class]] == NO) { @@ -774,7 +838,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSString *nam = [cmd objectAtIndex: 1]; BOOL found = NO; - enumerator = [launchInfo keyEnumerator]; + enumerator = [launchOrder objectEnumerator]; if ([nam caseInsensitiveCompare: @"all"] == NSOrderedSame) { NSMutableArray *names = [NSMutableArray array]; @@ -1058,7 +1122,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSEnumerator *enumerator; NSString *key; - enumerator = [launchInfo keyEnumerator]; + enumerator = [launchOrder objectEnumerator]; while ((key = [enumerator nextObject]) != nil) { if (comp(wd, key) >= 0) @@ -1424,6 +1488,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) RELEASE(host); RELEASE(clients); RELEASE(launchInfo); + RELEASE(launchOrder); RELEASE(environment); RELEASE(lastUnanswered); [super dealloc]; @@ -1625,7 +1690,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSDate *firstDate = nil; NSDate *now = [NSDate date]; - enumerator = [launchInfo keyEnumerator]; + enumerator = [launchOrder objectEnumerator]; while ((key = [enumerator nextObject]) != nil) { EcClientI *r = [self findIn: clients byName: key]; @@ -1880,7 +1945,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos) NSEnumerator *enumerator; NSString *key; - enumerator = [launchInfo keyEnumerator]; + enumerator = [launchOrder objectEnumerator]; while ((key = [enumerator nextObject]) != nil) { [launches setObject: [NSDate distantFuture] forKey: key];