diff -pur monit-4.6/p.y monit-4.6.toposort/p.y --- monit-4.6/p.y 2005-09-13 00:08:40.000000000 +0200 +++ monit-4.6.toposort/p.y 2005-12-08 22:17:52.000000000 +0100 @@ -3100,43 +3100,63 @@ static void check_hostname(char *hostnam } - /* - * Check the dependency graph for errors and if dependencies are - * present reshuffle the service list in a depending order. + * Check the dependency graph for errors + * by doing a topological sort, thereby finding any cycles. + * Assures that graph is a Directed Acyclic Graph (DAG). */ static void check_depend() { - - Service_T s; - int has_depend= FALSE; - - for(s= servicelist; s; s= s->next) { - if(s->visited) - continue; - validate_depend(s, &has_depend); - reset_depend(); - } - - if(has_depend) { - - Service_T d; - + Service_T s, depends_on; + depend_list = NULL; /* depend_list will be the topological sorted servicelist */ + Service_T* dlt = &depend_list; /* the current tail of it */ + int done; /* no unvisited nodes left? */ + int found_some; /* last iteration found anything new ? */ + + do { + done = TRUE; + found_some = FALSE; for(s= servicelist; s; s= s->next) { + Dependant_T d; if(s->visited) continue; - order_depend(s); + done = FALSE; // still unvisited nodes + depends_on = NULL; + for(d= s->dependantlist; d; d= d->next) { + Service_T dp = Util_getService(d->dependant); + if(!dp) { + log("%s: Error: Depend service '%s' is not defined in the " + "control file\n", prog, d->dependant); + exit(1); + } + if (!dp->visited) { + depends_on = dp; + } + } + + if (!depends_on) { + s->visited = TRUE; + found_some = TRUE; + *dlt = s; + dlt = &s->next_depend; + } } + } while(found_some && !done); + + if (!done) + { + ASSERT(depends_on); + log("%s: Error: Found a depend loop in the control file " + "involving the service '%s'\n", prog, depends_on->name); + exit(1); + } - ASSERT(depend_list); - servicelist= depend_list; + ASSERT(depend_list); + servicelist= depend_list; - for(d= depend_list; d; d= d->next_depend) - d->next= d->next_depend; + for(s= depend_list; s; s= s->next_depend) + s->next= s->next_depend; - } - reset_depend(); - } @@ -3183,77 +3203,3 @@ static int cleanup_hash_string(char *has } - -/* - * Search for any errors in the service dependency graph - */ -static void validate_depend(Service_T s, int *has_depend) { - - ASSERT(s); - - if(s->visited) - return; - - if(s->dependantlist) { - - Dependant_T d; - - for(d= s->dependantlist; d; d= d->next) { - - Service_T dp= Util_getService(d->dependant); - - if(!dp) { - log("%s: Error: Depend service '%s' is not defined in the " - "control file\n", prog, d->dependant); - exit(1); - } - - if(dp->depend_visited) { - log("%s: Error: Found a depend loop in the control file " - "involving the service '%s'\n", prog, s->name); - exit(1); - } - - *has_depend= TRUE; - dp->depend_visited= TRUE; - validate_depend(dp, has_depend); - - } - } - - s->visited= TRUE; - -} - - -/* - * Order the service list with the most "depending" service last and - * the least first. - */ -static void order_depend(Service_T s) { - - ASSERT(s); - - if(s->visited) - return; - - s->visited= TRUE; - - if(s->dependantlist) { - - Dependant_T d; - - for(d= s->dependantlist; d; d= d->next) { - - Service_T dp= Util_getService(d->dependant); - - order_depend(dp); - - } - } - - s->next_depend= depend_list; - depend_list= s; - -} -