Print this page
7267 SMF is fast and loose with optional dependencies
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Albert Lee <trisk@omniti.com>

*** 20,29 **** --- 20,30 ---- */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Syneto S.R.L. All rights reserved. + * Copyright 2016 RackTop Systems. */ /* * graph.c - master restarter graph engine *
*** 205,215 **** (state) == RESTARTER_STATE_DEGRADED || \ (state) == RESTARTER_STATE_OFFLINE) #define is_depgrp_bypassed(v) ((v->gv_type == GVT_GROUP) && \ ((v->gv_depgroup == DEPGRP_EXCLUDE_ALL) || \ - (v->gv_depgroup == DEPGRP_OPTIONAL_ALL) || \ (v->gv_restart < RERR_RESTART))) static uu_list_pool_t *graph_edge_pool, *graph_vertex_pool; static uu_list_t *dgraph; static pthread_mutex_t dgraph_lock; --- 206,215 ----
*** 1326,1346 **** edge = uu_list_next(groupv->gv_dependencies, edge)) { v = edge->ge_vertex; switch (v->gv_type) { case GVT_INST: ! /* Skip missing or disabled instances */ ! if ((v->gv_flags & (GV_CONFIGURED | GV_ENABLED)) != ! (GV_CONFIGURED | GV_ENABLED)) continue; if (v->gv_state == RESTARTER_STATE_MAINT) continue; - if (v->gv_flags & GV_TOOFFLINE) - continue; - any_qualified = B_TRUE; if (v->gv_state == RESTARTER_STATE_OFFLINE) { /* * For offline dependencies, treat unsatisfiable * as satisfied. --- 1326,1342 ---- edge = uu_list_next(groupv->gv_dependencies, edge)) { v = edge->ge_vertex; switch (v->gv_type) { case GVT_INST: ! /* Skip missing instances */ ! if ((v->gv_flags & GV_CONFIGURED) == 0) continue; if (v->gv_state == RESTARTER_STATE_MAINT) continue; any_qualified = B_TRUE; if (v->gv_state == RESTARTER_STATE_OFFLINE) { /* * For offline dependencies, treat unsatisfiable * as satisfied.
*** 1348,1362 **** i = dependency_satisfied(v, B_TRUE); if (i == -1) i = 1; } else if (v->gv_state == RESTARTER_STATE_DISABLED) { /* ! * The service is enabled, but hasn't ! * transitioned out of disabled yet. Treat it ! * as unsatisfied (not unsatisfiable). */ ! i = 0; } else { i = dependency_satisfied(v, satbility); } break; --- 1344,1358 ---- i = dependency_satisfied(v, B_TRUE); if (i == -1) i = 1; } else if (v->gv_state == RESTARTER_STATE_DISABLED) { /* ! * If the instance is transitioning out of ! * disabled the dependency is temporarily ! * unsatisfied (not unsatisfiable). */ ! i = v->gv_flags & GV_ENABLED ? 0 : 1; } else { i = dependency_satisfied(v, satbility); } break;
*** 1365,1436 **** i = dependency_satisfied(v, satbility); break; case GVT_SVC: { - boolean_t svc_any_qualified; - boolean_t svc_satisfied; - boolean_t svc_satisfiable; - graph_vertex_t *v2; - graph_edge_t *e2; - - svc_any_qualified = B_FALSE; - svc_satisfied = B_FALSE; - svc_satisfiable = B_FALSE; - - for (e2 = uu_list_first(v->gv_dependencies); - e2 != NULL; - e2 = uu_list_next(v->gv_dependencies, e2)) { - v2 = e2->ge_vertex; - assert(v2->gv_type == GVT_INST); - - if ((v2->gv_flags & - (GV_CONFIGURED | GV_ENABLED)) != - (GV_CONFIGURED | GV_ENABLED)) - continue; - - if (v2->gv_state == RESTARTER_STATE_MAINT) - continue; - - if (v2->gv_flags & GV_TOOFFLINE) - continue; - - svc_any_qualified = B_TRUE; - - if (v2->gv_state == RESTARTER_STATE_OFFLINE) { - /* - * For offline dependencies, treat - * unsatisfiable as satisfied. - */ - i = dependency_satisfied(v2, B_TRUE); - if (i == -1) - i = 1; - } else if (v2->gv_state == - RESTARTER_STATE_DISABLED) { - i = 0; - } else { - i = dependency_satisfied(v2, satbility); - } - - if (i == 1) { - svc_satisfied = B_TRUE; - break; - } - if (i == 0) - svc_satisfiable = B_TRUE; - } - - if (!svc_any_qualified) - continue; any_qualified = B_TRUE; ! if (svc_satisfied) { ! i = 1; ! } else if (svc_satisfiable) { ! i = 0; ! } else { ! i = -1; ! } break; } case GVT_GROUP: default: --- 1361,1373 ---- i = dependency_satisfied(v, satbility); break; case GVT_SVC: { any_qualified = B_TRUE; ! i = optional_all_satisfied(v, satbility); ! break; } case GVT_GROUP: default:
*** 1606,1620 **** } return (-1); } /* ! * Any vertex with the GV_TOOFFLINE flag set is guaranteed ! * to have its dependencies unsatisfiable. */ ! if (v->gv_flags & GV_TOOFFLINE) return (-1); switch (v->gv_state) { case RESTARTER_STATE_ONLINE: case RESTARTER_STATE_DEGRADED: return (1); --- 1543,1560 ---- } return (-1); } /* ! * Any vertex with the GV_TODISABLE flag set is guaranteed ! * to have its dependencies unsatisfiable. Any vertex with ! * GV_TOOFFLINE may be satisfied after it transitions. */ ! if (v->gv_flags & GV_TODISABLE) return (-1); + if (v->gv_flags & GV_TOOFFLINE) + return (0); switch (v->gv_state) { case RESTARTER_STATE_ONLINE: case RESTARTER_STATE_DEGRADED: return (1);
*** 1726,1735 **** --- 1666,1678 ---- */ /*ARGSUSED*/ static int satbility_cb(graph_vertex_t *v, void *arg) { + if (v->gv_flags & GV_TOOFFLINE) + return (UU_WALK_NEXT); + if (v->gv_type == GVT_INST) graph_start_if_satisfied(v); return (UU_WALK_NEXT); }
*** 1740,1768 **** graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL); } static void propagate_stop(graph_vertex_t *, void *); ! /* ARGSUSED */ static void propagate_start(graph_vertex_t *v, void *arg) { switch (v->gv_type) { case GVT_INST: graph_start_if_satisfied(v); break; case GVT_GROUP: if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) { graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART); break; } /* FALLTHROUGH */ case GVT_SVC: ! graph_walk_dependents(v, propagate_start, NULL); break; case GVT_FILE: #ifndef NDEBUG uu_warn("%s:%d: propagate_start() encountered GVT_FILE.\n", --- 1683,1733 ---- graph_walk(v, WALK_DEPENDENTS, satbility_cb, NULL, NULL); } static void propagate_stop(graph_vertex_t *, void *); ! /* ! * propagate_start() ! * ! * This function is used to propagate a start event to the dependents of the ! * given vertex. Any dependents that are offline but have their dependencies ! * satisfied are started. Any dependents that are online and have restart_on ! * set to "restart" or "refresh" are restarted because their dependencies have ! * just changed. This only happens with optional_all dependencies. ! */ static void propagate_start(graph_vertex_t *v, void *arg) { + restarter_error_t err = (restarter_error_t)arg; + + if (v->gv_flags & GV_TOOFFLINE) + return; + switch (v->gv_type) { case GVT_INST: + /* Restarter */ + if (inst_running(v)) { + if (err == RERR_RESTART || err == RERR_REFRESH) { + vertex_send_event(v, + RESTARTER_EVENT_TYPE_STOP_RESET); + } + } else { graph_start_if_satisfied(v); + } break; case GVT_GROUP: if (v->gv_depgroup == DEPGRP_EXCLUDE_ALL) { graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART); break; } + err = v->gv_restart; /* FALLTHROUGH */ case GVT_SVC: ! graph_walk_dependents(v, propagate_start, (void *)err); break; case GVT_FILE: #ifndef NDEBUG uu_warn("%s:%d: propagate_start() encountered GVT_FILE.\n",
*** 1778,1794 **** #endif abort(); } } static void propagate_stop(graph_vertex_t *v, void *arg) { - graph_edge_t *e; - graph_vertex_t *svc; restarter_error_t err = (restarter_error_t)arg; switch (v->gv_type) { case GVT_INST: /* Restarter */ if (err > RERR_NONE && inst_running(v)) { if (err == RERR_RESTART || err == RERR_REFRESH) { --- 1743,1769 ---- #endif abort(); } } + /* + * propagate_stop() + * + * This function is used to propagate a stop event to the dependents of the + * given vertex. Any dependents that are online (or in degraded state) with + * the restart_on property set to "restart" or "refresh" will be stopped as + * their dependencies have just changed, propagate_start() will start them + * again once their dependencies have been re-satisfied. + */ static void propagate_stop(graph_vertex_t *v, void *arg) { restarter_error_t err = (restarter_error_t)arg; + if (v->gv_flags & GV_TOOFFLINE) + return; + switch (v->gv_type) { case GVT_INST: /* Restarter */ if (err > RERR_NONE && inst_running(v)) { if (err == RERR_RESTART || err == RERR_REFRESH) {
*** 1819,1841 **** } if (err == RERR_NONE || err > v->gv_restart) break; ! assert(uu_list_numnodes(v->gv_dependents) == 1); ! e = uu_list_first(v->gv_dependents); ! svc = e->ge_vertex; ! ! if (inst_running(svc)) { ! if (err == RERR_RESTART || err == RERR_REFRESH) { ! vertex_send_event(svc, ! RESTARTER_EVENT_TYPE_STOP_RESET); ! } else { ! vertex_send_event(svc, ! RESTARTER_EVENT_TYPE_STOP); ! } ! } break; default: #ifndef NDEBUG uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__, --- 1794,1804 ---- } if (err == RERR_NONE || err > v->gv_restart) break; ! graph_walk_dependents(v, propagate_stop, arg); break; default: #ifndef NDEBUG uu_warn("%s:%d: Unknown vertex type %d.\n", __FILE__, __LINE__,
*** 4396,4408 **** if ((vv->gv_state == RESTARTER_STATE_ONLINE) || (vv->gv_state == RESTARTER_STATE_DEGRADED)) return (B_FALSE); } else { /* ! * Skip all excluded and optional_all dependencies ! * and decide whether to offline the service based ! * on restart_on attribute. */ if (is_depgrp_bypassed(vv)) continue; /* --- 4359,4371 ---- if ((vv->gv_state == RESTARTER_STATE_ONLINE) || (vv->gv_state == RESTARTER_STATE_DEGRADED)) return (B_FALSE); } else { /* ! * Skip all excluded dependents and decide whether ! * to offline the service based on the restart_on ! * on attribute. */ if (is_depgrp_bypassed(vv)) continue; /*
*** 4963,4973 **** restarter_error_t rerr) { if (type == PROPAGATE_STOP) { graph_walk_dependents(v, propagate_stop, (void *)rerr); } else if (type == PROPAGATE_START || type == PROPAGATE_SAT) { ! graph_walk_dependents(v, propagate_start, NULL); if (type == PROPAGATE_SAT) propagate_satbility(v); } else { #ifndef NDEBUG --- 4926,4936 ---- restarter_error_t rerr) { if (type == PROPAGATE_STOP) { graph_walk_dependents(v, propagate_stop, (void *)rerr); } else if (type == PROPAGATE_START || type == PROPAGATE_SAT) { ! graph_walk_dependents(v, propagate_start, (void *)RERR_NONE); if (type == PROPAGATE_SAT) propagate_satbility(v); } else { #ifndef NDEBUG
*** 5034,5044 **** graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART); v->gv_flags &= ~GV_CONFIGURED; v->gv_flags &= ~GV_DEATHROW; ! graph_walk_dependents(v, propagate_start, NULL); propagate_satbility(v); /* * If there are no (non-service) dependents, the vertex can be * completely removed. --- 4997,5007 ---- graph_walk_dependents(v, propagate_stop, (void *)RERR_RESTART); v->gv_flags &= ~GV_CONFIGURED; v->gv_flags &= ~GV_DEATHROW; ! graph_walk_dependents(v, propagate_start, (void *)RERR_NONE); propagate_satbility(v); /* * If there are no (non-service) dependents, the vertex can be * completely removed.
*** 5459,5470 **** v->gv_flags |= GV_TOOFFLINE; log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name); break; case GVT_GROUP: /* ! * Skip all excluded and optional_all dependencies and decide ! * whether to offline the service based on restart_on attribute. */ if (is_depgrp_bypassed(v)) return (UU_WALK_NEXT); break; } --- 5422,5433 ---- v->gv_flags |= GV_TOOFFLINE; log_framework(LOG_DEBUG, "%s added to subtree\n", v->gv_name); break; case GVT_GROUP: /* ! * Skip all excluded dependents and decide whether to offline ! * the service based on the restart_on attribute. */ if (is_depgrp_bypassed(v)) return (UU_WALK_NEXT); break; }