lifecycle: add lif_lifecycle_count_rdepends(), which calculates reverse dependency depth
This commit is contained in:
parent
a5eebda391
commit
2569503afa
4 changed files with 68 additions and 0 deletions
|
@ -290,6 +290,12 @@ ifquery_main(int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lif_lifecycle_count_rdepends(&exec_opts, &collection))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: could not validate dependency tree\n", argv0);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
/* --list --state is not allowed */
|
/* --list --state is not allowed */
|
||||||
if (listing && listing_stat)
|
if (listing && listing_stat)
|
||||||
generic_usage(self_applet, EXIT_FAILURE);
|
generic_usage(self_applet, EXIT_FAILURE);
|
||||||
|
|
|
@ -229,6 +229,12 @@ ifupdown_main(int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lif_lifecycle_count_rdepends(&exec_opts, &collection))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: could not validate dependency tree\n", argv0);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lif_state_sync(&state, &collection))
|
if (!lif_state_sync(&state, &collection))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: could not sync state\n", argv0);
|
fprintf(stderr, "%s: could not sync state\n", argv0);
|
||||||
|
|
|
@ -389,3 +389,58 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
count_interface_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection, struct lif_interface *parent, size_t depth)
|
||||||
|
{
|
||||||
|
/* query our dependents if we don't have them already */
|
||||||
|
if (!lif_lifecycle_query_dependents(opts, parent, parent->ifname))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* set rdepends_count to depth, dependents will be depth + 1 */
|
||||||
|
parent->rdepends_count = depth;
|
||||||
|
|
||||||
|
struct lif_dict_entry *requires = lif_dict_find(&parent->vars, "requires");
|
||||||
|
|
||||||
|
/* no dependents, nothing to worry about */
|
||||||
|
if (requires == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* walk any dependents */
|
||||||
|
char require_ifs[4096] = {};
|
||||||
|
strlcpy(require_ifs, requires->data, sizeof require_ifs);
|
||||||
|
char *bufp = require_ifs;
|
||||||
|
|
||||||
|
for (char *tokenp = lif_next_token(&bufp); *tokenp; tokenp = lif_next_token(&bufp))
|
||||||
|
{
|
||||||
|
struct lif_interface *iface = lif_interface_collection_find(collection, tokenp);
|
||||||
|
|
||||||
|
if (!count_interface_rdepends(opts, collection, iface, depth + 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection)
|
||||||
|
{
|
||||||
|
struct lif_node *iter;
|
||||||
|
|
||||||
|
LIF_DICT_FOREACH(iter, collection)
|
||||||
|
{
|
||||||
|
struct lif_dict_entry *entry = iter->data;
|
||||||
|
struct lif_interface *iface = entry->data;
|
||||||
|
|
||||||
|
/* start depth at interface's rdepends_count, which will be 0 for the root,
|
||||||
|
* but will be more if additional rdepends are found...
|
||||||
|
*/
|
||||||
|
if (!count_interface_rdepends(opts, collection, iface, iface->rdepends_count))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ifupdown: dependency graph is broken for interface %s\n", iface->ifname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
extern bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname);
|
extern bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname);
|
||||||
extern bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up);
|
extern bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up);
|
||||||
extern bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up);
|
extern bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up);
|
||||||
|
extern bool lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue