4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * transition.c - Graph State Machine
29 *
30 * The graph state machine is implemented here, with a typical approach
31 * of a function per state. Separating the implementation allows more
32 * clarity into the actions taken on notification of state change, as well
33 * as a place for future expansion including hooks for configurable actions.
34 * All functions are called with dgraph_lock held.
35 *
36 * The start action for this state machine is not explicit. The states
37 * (ONLINE and DEGRADED) which need to know when they're entering the state
38 * due to a daemon restart implement this understanding by checking for
39 * transition from uninitialized. In the future, this would likely be better
40 * as an explicit start action instead of relying on an overloaded transition.
41 *
42 * All gt_enter functions use the same set of return codes.
43 * 0 success
120 /* instance transitioning to maintenance is considered disabled */
121 v->gv_flags &= ~GV_TODISABLE;
122 v->gv_flags &= ~GV_TOOFFLINE;
123
124 if (gt_running(old_state)) {
125 /*
126 * Handle state change during instance disabling.
127 * Propagate offline to the new exposed leaves.
128 */
129 if (to_offline) {
130 log_framework(LOG_DEBUG, "%s removed from subtree\n",
131 v->gv_name);
132
133 graph_offline_subtree_leaves(v, (void *)h);
134 }
135
136 log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
137 "%s.\n", v->gv_name);
138
139 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
140 } else {
141 log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
142 v->gv_name);
143
144 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
145 }
146
147 graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
148 return (0);
149 }
150
151 /* ARGSUSED */
152 static int
153 gt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
154 restarter_instance_state_t old_state, restarter_error_t rerr)
155 {
156 int to_offline = v->gv_flags & GV_TOOFFLINE;
157
158 v->gv_flags &= ~GV_TOOFFLINE;
159
250 * case we've just disabled an instance that was part of a
251 * subtree.
252 */
253 if (to_offline) {
254 log_framework(LOG_DEBUG, "%s removed from subtree\n",
255 v->gv_name);
256
257 /*
258 * Handle state change during instance disabling.
259 * Propagate offline to the new exposed leaves.
260 */
261 graph_offline_subtree_leaves(v, (void *)h);
262 }
263
264
265 log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
266 v->gv_name);
267
268 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
269
270 } else {
271 log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
272 v->gv_name);
273
274 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
275 }
276
277 graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
278 return (0);
279 }
280
281 static int
282 gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
283 restarter_instance_state_t old_state, restarter_error_t rerr)
284 {
285 int r;
286
287 /*
288 * If the instance has just come up, update the start
289 * snapshot.
309 break;
310
311 case ECONNABORTED:
312 return (ECONNABORTED);
313
314 case EACCES:
315 case ENOTSUP:
316 default:
317 bad_error("libscf_snapshots_poststart", r);
318 }
319 }
320
321 if (!(v->gv_flags & GV_ENABLED)) {
322 vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
323 } else if (v->gv_flags & GV_TOOFFLINE) {
324 /*
325 * If the vertex has the GV_TOOFFLINE flag set then that's
326 * because the instance was transitioning from offline to
327 * online and the reverse disable algorithm doesn't offline
328 * those instances because it was already appearing offline.
329 * So do it now.
330 */
331 offline_vertex(v);
332 }
333
334 if (gt_running(old_state) == 0) {
335 log_framework(LOG_DEBUG, "Propagating start of %s.\n",
336 v->gv_name);
337
338 graph_transition_propagate(v, PROPAGATE_START, rerr);
339 } else if (rerr == RERR_REFRESH) {
340 /* For refresh we'll get a message sans state change */
341
342 log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
343 v->gv_name);
344
345 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
346 }
347
348 return (0);
349 }
350
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2016 RackTop Systems.
26 */
27
28
29 /*
30 * transition.c - Graph State Machine
31 *
32 * The graph state machine is implemented here, with a typical approach
33 * of a function per state. Separating the implementation allows more
34 * clarity into the actions taken on notification of state change, as well
35 * as a place for future expansion including hooks for configurable actions.
36 * All functions are called with dgraph_lock held.
37 *
38 * The start action for this state machine is not explicit. The states
39 * (ONLINE and DEGRADED) which need to know when they're entering the state
40 * due to a daemon restart implement this understanding by checking for
41 * transition from uninitialized. In the future, this would likely be better
42 * as an explicit start action instead of relying on an overloaded transition.
43 *
44 * All gt_enter functions use the same set of return codes.
45 * 0 success
122 /* instance transitioning to maintenance is considered disabled */
123 v->gv_flags &= ~GV_TODISABLE;
124 v->gv_flags &= ~GV_TOOFFLINE;
125
126 if (gt_running(old_state)) {
127 /*
128 * Handle state change during instance disabling.
129 * Propagate offline to the new exposed leaves.
130 */
131 if (to_offline) {
132 log_framework(LOG_DEBUG, "%s removed from subtree\n",
133 v->gv_name);
134
135 graph_offline_subtree_leaves(v, (void *)h);
136 }
137
138 log_framework(LOG_DEBUG, "Propagating maintenance (stop) of "
139 "%s.\n", v->gv_name);
140
141 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
142
143 /*
144 * The maintenance transition may satisfy optional_all/restart
145 * dependencies and should be propagated to determine
146 * whether new dependents are satisfiable.
147 */
148 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
149 } else {
150 log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n",
151 v->gv_name);
152
153 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
154 }
155
156 graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state);
157 return (0);
158 }
159
160 /* ARGSUSED */
161 static int
162 gt_enter_offline(scf_handle_t *h, graph_vertex_t *v,
163 restarter_instance_state_t old_state, restarter_error_t rerr)
164 {
165 int to_offline = v->gv_flags & GV_TOOFFLINE;
166
167 v->gv_flags &= ~GV_TOOFFLINE;
168
259 * case we've just disabled an instance that was part of a
260 * subtree.
261 */
262 if (to_offline) {
263 log_framework(LOG_DEBUG, "%s removed from subtree\n",
264 v->gv_name);
265
266 /*
267 * Handle state change during instance disabling.
268 * Propagate offline to the new exposed leaves.
269 */
270 graph_offline_subtree_leaves(v, (void *)h);
271 }
272
273
274 log_framework(LOG_DEBUG, "Propagating stop of %s.\n",
275 v->gv_name);
276
277 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
278
279 /*
280 * The disable transition may satisfy optional_all/restart
281 * dependencies and should be propagated to determine
282 * whether new dependents are satisfiable.
283 */
284 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
285 } else {
286 log_framework(LOG_DEBUG, "Propagating disable of %s.\n",
287 v->gv_name);
288
289 graph_transition_propagate(v, PROPAGATE_SAT, rerr);
290 }
291
292 graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state);
293 return (0);
294 }
295
296 static int
297 gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v,
298 restarter_instance_state_t old_state, restarter_error_t rerr)
299 {
300 int r;
301
302 /*
303 * If the instance has just come up, update the start
304 * snapshot.
324 break;
325
326 case ECONNABORTED:
327 return (ECONNABORTED);
328
329 case EACCES:
330 case ENOTSUP:
331 default:
332 bad_error("libscf_snapshots_poststart", r);
333 }
334 }
335
336 if (!(v->gv_flags & GV_ENABLED)) {
337 vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE);
338 } else if (v->gv_flags & GV_TOOFFLINE) {
339 /*
340 * If the vertex has the GV_TOOFFLINE flag set then that's
341 * because the instance was transitioning from offline to
342 * online and the reverse disable algorithm doesn't offline
343 * those instances because it was already appearing offline.
344 * Try to do it now.
345 */
346 if (insubtree_dependents_down(v))
347 offline_vertex(v);
348 }
349
350 if (gt_running(old_state) == 0) {
351 log_framework(LOG_DEBUG, "Propagating start of %s.\n",
352 v->gv_name);
353
354 graph_transition_propagate(v, PROPAGATE_START, rerr);
355 } else if (rerr == RERR_REFRESH) {
356 /* For refresh we'll get a message sans state change */
357
358 log_framework(LOG_DEBUG, "Propagating refresh of %s.\n",
359 v->gv_name);
360
361 graph_transition_propagate(v, PROPAGATE_STOP, rerr);
362 }
363
364 return (0);
365 }
366
|