199b44c3bSlianep /* 299b44c3bSlianep * CDDL HEADER START 399b44c3bSlianep * 499b44c3bSlianep * The contents of this file are subject to the terms of the 599b44c3bSlianep * Common Development and Distribution License (the "License"). 699b44c3bSlianep * You may not use this file except in compliance with the License. 799b44c3bSlianep * 899b44c3bSlianep * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 999b44c3bSlianep * or http://www.opensolaris.org/os/licensing. 1099b44c3bSlianep * See the License for the specific language governing permissions 1199b44c3bSlianep * and limitations under the License. 1299b44c3bSlianep * 1399b44c3bSlianep * When distributing Covered Code, include this CDDL HEADER in each 1499b44c3bSlianep * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1599b44c3bSlianep * If applicable, add the following below this CDDL HEADER, with the 1699b44c3bSlianep * fields enclosed by brackets "[]" replaced with your own identifying 1799b44c3bSlianep * information: Portions Copyright [yyyy] [name of copyright owner] 1899b44c3bSlianep * 1999b44c3bSlianep * CDDL HEADER END 2099b44c3bSlianep */ 2199b44c3bSlianep /* 22*845e9415SRenaud Manus * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2399b44c3bSlianep * Use is subject to license terms. 2499b44c3bSlianep */ 2599b44c3bSlianep 2699b44c3bSlianep 2799b44c3bSlianep /* 2899b44c3bSlianep * transition.c - Graph State Machine 2999b44c3bSlianep * 3099b44c3bSlianep * The graph state machine is implemented here, with a typical approach 3199b44c3bSlianep * of a function per state. Separating the implementation allows more 3299b44c3bSlianep * clarity into the actions taken on notification of state change, as well 3399b44c3bSlianep * as a place for future expansion including hooks for configurable actions. 3499b44c3bSlianep * All functions are called with dgraph_lock held. 3599b44c3bSlianep * 3699b44c3bSlianep * The start action for this state machine is not explicit. The states 3756e23938Sbustos * (ONLINE and DEGRADED) which need to know when they're entering the state 3899b44c3bSlianep * due to a daemon restart implement this understanding by checking for 3999b44c3bSlianep * transition from uninitialized. In the future, this would likely be better 4099b44c3bSlianep * as an explicit start action instead of relying on an overloaded transition. 4199b44c3bSlianep * 4299b44c3bSlianep * All gt_enter functions use the same set of return codes. 4399b44c3bSlianep * 0 success 4499b44c3bSlianep * ECONNABORTED repository connection aborted 4599b44c3bSlianep */ 4699b44c3bSlianep 4799b44c3bSlianep #include "startd.h" 4899b44c3bSlianep 4999b44c3bSlianep static int 5099b44c3bSlianep gt_running(restarter_instance_state_t state) 5199b44c3bSlianep { 5299b44c3bSlianep if (state == RESTARTER_STATE_ONLINE || 5399b44c3bSlianep state == RESTARTER_STATE_DEGRADED) 5499b44c3bSlianep return (1); 5599b44c3bSlianep 5699b44c3bSlianep return (0); 5799b44c3bSlianep } 5899b44c3bSlianep 5999b44c3bSlianep static int 6099b44c3bSlianep gt_enter_uninit(scf_handle_t *h, graph_vertex_t *v, 6199b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 6299b44c3bSlianep { 6399b44c3bSlianep int err; 6499b44c3bSlianep scf_instance_t *inst; 6599b44c3bSlianep 6699b44c3bSlianep /* Initialize instance by refreshing it. */ 6799b44c3bSlianep 6899b44c3bSlianep err = libscf_fmri_get_instance(h, v->gv_name, &inst); 6999b44c3bSlianep switch (err) { 7099b44c3bSlianep case 0: 7199b44c3bSlianep break; 7299b44c3bSlianep 7399b44c3bSlianep case ECONNABORTED: 7499b44c3bSlianep return (ECONNABORTED); 7599b44c3bSlianep 7699b44c3bSlianep case ENOENT: 7799b44c3bSlianep return (0); 7899b44c3bSlianep 7999b44c3bSlianep case EINVAL: 8099b44c3bSlianep case ENOTSUP: 8199b44c3bSlianep default: 8299b44c3bSlianep bad_error("libscf_fmri_get_instance", err); 8399b44c3bSlianep } 8499b44c3bSlianep 8599b44c3bSlianep err = refresh_vertex(v, inst); 8699b44c3bSlianep if (err == 0) 8799b44c3bSlianep graph_enable_by_vertex(v, v->gv_flags & GV_ENABLED, 0); 8899b44c3bSlianep 8999b44c3bSlianep scf_instance_destroy(inst); 9099b44c3bSlianep 9199b44c3bSlianep /* If the service was running, propagate a stop event. */ 9299b44c3bSlianep if (gt_running(old_state)) { 9399b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n", 9499b44c3bSlianep v->gv_name); 9599b44c3bSlianep 96cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr); 9799b44c3bSlianep } 9899b44c3bSlianep 9999b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_UNINIT, old_state); 10099b44c3bSlianep return (0); 10199b44c3bSlianep } 10299b44c3bSlianep 10356e23938Sbustos /* ARGSUSED */ 10499b44c3bSlianep static int 10599b44c3bSlianep gt_enter_maint(scf_handle_t *h, graph_vertex_t *v, 10699b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 10799b44c3bSlianep { 108207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE; 109207246e9SRenaud Manus 110cd3bce3eSlianep /* 111cd3bce3eSlianep * If the service was running, propagate a stop event. If the 112cd3bce3eSlianep * service was not running the maintenance transition may satisfy 113cd3bce3eSlianep * optional dependencies and should be propagated to determine 114cd3bce3eSlianep * whether new dependents are satisfiable. 115aca380d7SRenaud Manus * Instances that transition to maintenance and have the GV_TOOFFLINE 116aca380d7SRenaud Manus * flag are special because they can expose new subtree leaves so 117aca380d7SRenaud Manus * propagate the offline to the instance dependencies. 118cd3bce3eSlianep */ 119207246e9SRenaud Manus 120207246e9SRenaud Manus /* instance transitioning to maintenance is considered disabled */ 121207246e9SRenaud Manus v->gv_flags &= ~GV_TODISABLE; 122207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE; 123207246e9SRenaud Manus 12499b44c3bSlianep if (gt_running(old_state)) { 125aca380d7SRenaud Manus /* 126aca380d7SRenaud Manus * Handle state change during instance disabling. 127aca380d7SRenaud Manus * Propagate offline to the new exposed leaves. 128aca380d7SRenaud Manus */ 129207246e9SRenaud Manus if (to_offline) { 130aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n", 131aca380d7SRenaud Manus v->gv_name); 132207246e9SRenaud Manus 133aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h); 134aca380d7SRenaud Manus } 135aca380d7SRenaud Manus 136cd3bce3eSlianep log_framework(LOG_DEBUG, "Propagating maintenance (stop) of " 137cd3bce3eSlianep "%s.\n", v->gv_name); 13899b44c3bSlianep 139cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr); 140cd3bce3eSlianep } else { 14199b44c3bSlianep log_framework(LOG_DEBUG, "Propagating maintenance of %s.\n", 14299b44c3bSlianep v->gv_name); 14399b44c3bSlianep 144cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_SAT, rerr); 14599b44c3bSlianep } 14699b44c3bSlianep 14799b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_MAINT, old_state); 14899b44c3bSlianep return (0); 14999b44c3bSlianep } 15099b44c3bSlianep 15156e23938Sbustos /* ARGSUSED */ 15299b44c3bSlianep static int 15399b44c3bSlianep gt_enter_offline(scf_handle_t *h, graph_vertex_t *v, 15499b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 15599b44c3bSlianep { 156207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE; 157207246e9SRenaud Manus 158207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE; 159207246e9SRenaud Manus 16099b44c3bSlianep /* 16199b44c3bSlianep * If the instance should be enabled, see if we can start it. 16299b44c3bSlianep * Otherwise send a disable command. 163aca380d7SRenaud Manus * If a instance has the GV_TOOFFLINE flag set then it must 164aca380d7SRenaud Manus * remains offline until the disable process completes. 16599b44c3bSlianep */ 16699b44c3bSlianep if (v->gv_flags & GV_ENABLED) { 167207246e9SRenaud Manus if (to_offline == 0) 16899b44c3bSlianep graph_start_if_satisfied(v); 16999b44c3bSlianep } else { 17099b44c3bSlianep if (gt_running(old_state) && v->gv_post_disable_f) 17199b44c3bSlianep v->gv_post_disable_f(); 172aca380d7SRenaud Manus 17399b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE); 17499b44c3bSlianep } 17599b44c3bSlianep 17673b709eaSrm88369 /* 17773b709eaSrm88369 * If the service was running, propagate a stop event. If the 17873b709eaSrm88369 * service was not running the offline transition may satisfy 17973b709eaSrm88369 * optional dependencies and should be propagated to determine 18073b709eaSrm88369 * whether new dependents are satisfiable. 181aca380d7SRenaud Manus * Instances that transition to offline and have the GV_TOOFFLINE flag 182aca380d7SRenaud Manus * are special because they can expose new subtree leaves so propagate 183aca380d7SRenaud Manus * the offline to the instance dependencies. 18473b709eaSrm88369 */ 18599b44c3bSlianep if (gt_running(old_state)) { 186aca380d7SRenaud Manus /* 187aca380d7SRenaud Manus * Handle state change during instance disabling. 188aca380d7SRenaud Manus * Propagate offline to the new exposed leaves. 189aca380d7SRenaud Manus */ 190207246e9SRenaud Manus if (to_offline) { 191aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n", 192aca380d7SRenaud Manus v->gv_name); 193207246e9SRenaud Manus 194aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h); 195aca380d7SRenaud Manus } 196aca380d7SRenaud Manus 19799b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n", 19899b44c3bSlianep v->gv_name); 19999b44c3bSlianep 200cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr); 201207246e9SRenaud Manus 202207246e9SRenaud Manus /* 203207246e9SRenaud Manus * The offline transition may satisfy require_any/restart 204207246e9SRenaud Manus * dependencies and should be propagated to determine 205207246e9SRenaud Manus * whether new dependents are satisfiable. 206207246e9SRenaud Manus */ 207207246e9SRenaud Manus graph_transition_propagate(v, PROPAGATE_SAT, rerr); 20873b709eaSrm88369 } else { 20973b709eaSrm88369 log_framework(LOG_DEBUG, "Propagating offline of %s.\n", 21073b709eaSrm88369 v->gv_name); 21173b709eaSrm88369 21273b709eaSrm88369 graph_transition_propagate(v, PROPAGATE_SAT, rerr); 21399b44c3bSlianep } 21499b44c3bSlianep 21599b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_OFFLINE, old_state); 21699b44c3bSlianep return (0); 21799b44c3bSlianep } 21899b44c3bSlianep 21956e23938Sbustos /* ARGSUSED */ 22099b44c3bSlianep static int 22199b44c3bSlianep gt_enter_disabled(scf_handle_t *h, graph_vertex_t *v, 22299b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 22399b44c3bSlianep { 224207246e9SRenaud Manus int to_offline = v->gv_flags & GV_TOOFFLINE; 225207246e9SRenaud Manus 226207246e9SRenaud Manus v->gv_flags &= ~GV_TODISABLE; 227207246e9SRenaud Manus v->gv_flags &= ~GV_TOOFFLINE; 228aca380d7SRenaud Manus 22999b44c3bSlianep /* 23099b44c3bSlianep * If the instance should be disabled, no problem. Otherwise, 23199b44c3bSlianep * send an enable command, which should result in the instance 232aca380d7SRenaud Manus * moving to OFFLINE unless the instance is part of a subtree 233aca380d7SRenaud Manus * (non root) and in this case the result is unpredictable. 23499b44c3bSlianep */ 23599b44c3bSlianep if (v->gv_flags & GV_ENABLED) { 23699b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_ENABLE); 23799b44c3bSlianep } else if (gt_running(old_state) && v->gv_post_disable_f) { 23899b44c3bSlianep v->gv_post_disable_f(); 23999b44c3bSlianep } 24099b44c3bSlianep 24199b44c3bSlianep /* 242cd3bce3eSlianep * If the service was running, propagate this as a stop. If the 243cd3bce3eSlianep * service was not running the disabled transition may satisfy 244cd3bce3eSlianep * optional dependencies and should be propagated to determine 245cd3bce3eSlianep * whether new dependents are satisfiable. 24699b44c3bSlianep */ 24799b44c3bSlianep if (gt_running(old_state)) { 248aca380d7SRenaud Manus /* 249aca380d7SRenaud Manus * We need to propagate the offline to new exposed leaves in 250aca380d7SRenaud Manus * case we've just disabled an instance that was part of a 251aca380d7SRenaud Manus * subtree. 252aca380d7SRenaud Manus */ 253207246e9SRenaud Manus if (to_offline) { 254aca380d7SRenaud Manus log_framework(LOG_DEBUG, "%s removed from subtree\n", 255aca380d7SRenaud Manus v->gv_name); 256aca380d7SRenaud Manus 257aca380d7SRenaud Manus /* 258aca380d7SRenaud Manus * Handle state change during instance disabling. 259aca380d7SRenaud Manus * Propagate offline to the new exposed leaves. 260aca380d7SRenaud Manus */ 261aca380d7SRenaud Manus graph_offline_subtree_leaves(v, (void *)h); 262aca380d7SRenaud Manus } 263aca380d7SRenaud Manus 264aca380d7SRenaud Manus 26599b44c3bSlianep log_framework(LOG_DEBUG, "Propagating stop of %s.\n", 26699b44c3bSlianep v->gv_name); 26799b44c3bSlianep 268cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr); 26999b44c3bSlianep 270cd3bce3eSlianep } else { 27199b44c3bSlianep log_framework(LOG_DEBUG, "Propagating disable of %s.\n", 27299b44c3bSlianep v->gv_name); 27399b44c3bSlianep 274cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_SAT, rerr); 27599b44c3bSlianep } 27699b44c3bSlianep 27799b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_DISABLED, old_state); 27899b44c3bSlianep return (0); 27999b44c3bSlianep } 28099b44c3bSlianep 28199b44c3bSlianep static int 28299b44c3bSlianep gt_internal_online_or_degraded(scf_handle_t *h, graph_vertex_t *v, 28399b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 28499b44c3bSlianep { 28599b44c3bSlianep int r; 28699b44c3bSlianep 28799b44c3bSlianep /* 28899b44c3bSlianep * If the instance has just come up, update the start 28999b44c3bSlianep * snapshot. 29099b44c3bSlianep */ 29199b44c3bSlianep if (gt_running(old_state) == 0) { 29299b44c3bSlianep /* 29399b44c3bSlianep * Don't fire if we're just recovering state 29499b44c3bSlianep * after a restart. 29599b44c3bSlianep */ 29699b44c3bSlianep if (old_state != RESTARTER_STATE_UNINIT && 29799b44c3bSlianep v->gv_post_online_f) 29899b44c3bSlianep v->gv_post_online_f(); 29999b44c3bSlianep 30099b44c3bSlianep r = libscf_snapshots_poststart(h, v->gv_name, B_TRUE); 30199b44c3bSlianep switch (r) { 30299b44c3bSlianep case 0: 30399b44c3bSlianep case ENOENT: 30499b44c3bSlianep /* 30599b44c3bSlianep * If ENOENT, the instance must have been 30699b44c3bSlianep * deleted. Pretend we were successful since 30799b44c3bSlianep * we should get a delete event later. 30899b44c3bSlianep */ 30999b44c3bSlianep break; 31099b44c3bSlianep 31199b44c3bSlianep case ECONNABORTED: 31299b44c3bSlianep return (ECONNABORTED); 31399b44c3bSlianep 31499b44c3bSlianep case EACCES: 31599b44c3bSlianep case ENOTSUP: 31699b44c3bSlianep default: 31799b44c3bSlianep bad_error("libscf_snapshots_poststart", r); 31899b44c3bSlianep } 31999b44c3bSlianep } 320*845e9415SRenaud Manus 321*845e9415SRenaud Manus if (!(v->gv_flags & GV_ENABLED)) { 32299b44c3bSlianep vertex_send_event(v, RESTARTER_EVENT_TYPE_DISABLE); 323*845e9415SRenaud Manus } else if (v->gv_flags & GV_TOOFFLINE) { 324*845e9415SRenaud Manus /* 325*845e9415SRenaud Manus * If the vertex has the GV_TOOFFLINE flag set then that's 326*845e9415SRenaud Manus * because the instance was transitioning from offline to 327*845e9415SRenaud Manus * online and the reverse disable algorithm doesn't offline 328*845e9415SRenaud Manus * those instances because it was already appearing offline. 329*845e9415SRenaud Manus * So do it now. 330*845e9415SRenaud Manus */ 331*845e9415SRenaud Manus offline_vertex(v); 332*845e9415SRenaud Manus } 33399b44c3bSlianep 33499b44c3bSlianep if (gt_running(old_state) == 0) { 33599b44c3bSlianep log_framework(LOG_DEBUG, "Propagating start of %s.\n", 33699b44c3bSlianep v->gv_name); 33799b44c3bSlianep 338cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_START, rerr); 33999b44c3bSlianep } else if (rerr == RERR_REFRESH) { 34099b44c3bSlianep /* For refresh we'll get a message sans state change */ 34199b44c3bSlianep 34299b44c3bSlianep log_framework(LOG_DEBUG, "Propagating refresh of %s.\n", 34399b44c3bSlianep v->gv_name); 34499b44c3bSlianep 345cd3bce3eSlianep graph_transition_propagate(v, PROPAGATE_STOP, rerr); 34699b44c3bSlianep } 34799b44c3bSlianep 34899b44c3bSlianep return (0); 34999b44c3bSlianep } 35099b44c3bSlianep 35199b44c3bSlianep static int 35299b44c3bSlianep gt_enter_online(scf_handle_t *h, graph_vertex_t *v, 35399b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 35499b44c3bSlianep { 35599b44c3bSlianep int r; 35699b44c3bSlianep 35799b44c3bSlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr); 35899b44c3bSlianep if (r != 0) 35999b44c3bSlianep return (r); 36099b44c3bSlianep 36199b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_ONLINE, old_state); 36299b44c3bSlianep return (0); 36399b44c3bSlianep } 36499b44c3bSlianep 36599b44c3bSlianep static int 36699b44c3bSlianep gt_enter_degraded(scf_handle_t *h, graph_vertex_t *v, 36799b44c3bSlianep restarter_instance_state_t old_state, restarter_error_t rerr) 36899b44c3bSlianep { 36999b44c3bSlianep int r; 37099b44c3bSlianep 37199b44c3bSlianep r = gt_internal_online_or_degraded(h, v, old_state, rerr); 37299b44c3bSlianep if (r != 0) 37399b44c3bSlianep return (r); 37499b44c3bSlianep 37599b44c3bSlianep graph_transition_sulogin(RESTARTER_STATE_DEGRADED, old_state); 37699b44c3bSlianep return (0); 37799b44c3bSlianep } 37899b44c3bSlianep 37999b44c3bSlianep /* 38099b44c3bSlianep * gt_transition() implements the state transition for the graph 38199b44c3bSlianep * state machine. It can return: 38299b44c3bSlianep * 0 success 38399b44c3bSlianep * ECONNABORTED repository connection aborted 384cd3bce3eSlianep * 385cd3bce3eSlianep * v->gv_state should be set to the state we're transitioning to before 386cd3bce3eSlianep * calling this function. 38799b44c3bSlianep */ 38899b44c3bSlianep int 38999b44c3bSlianep gt_transition(scf_handle_t *h, graph_vertex_t *v, restarter_error_t rerr, 390cd3bce3eSlianep restarter_instance_state_t old_state) 39199b44c3bSlianep { 39256e23938Sbustos int err; 39356e23938Sbustos int lost_repository = 0; 39499b44c3bSlianep 39599b44c3bSlianep /* 39699b44c3bSlianep * If there's a common set of work to be done on exit from the 39799b44c3bSlianep * old_state, include it as a separate set of functions here. For 39899b44c3bSlianep * now there's no such work, so there are no gt_exit functions. 39999b44c3bSlianep */ 40099b44c3bSlianep 40156e23938Sbustos err = vertex_subgraph_dependencies_shutdown(h, v, old_state); 40256e23938Sbustos switch (err) { 40356e23938Sbustos case 0: 40456e23938Sbustos break; 40556e23938Sbustos 40656e23938Sbustos case ECONNABORTED: 40756e23938Sbustos lost_repository = 1; 40856e23938Sbustos break; 40956e23938Sbustos 41056e23938Sbustos default: 41156e23938Sbustos bad_error("vertex_subgraph_dependencies_shutdown", err); 41256e23938Sbustos } 41356e23938Sbustos 41499b44c3bSlianep /* 41599b44c3bSlianep * Now call the appropriate gt_enter function for the new state. 41699b44c3bSlianep */ 417cd3bce3eSlianep switch (v->gv_state) { 41899b44c3bSlianep case RESTARTER_STATE_UNINIT: 41999b44c3bSlianep err = gt_enter_uninit(h, v, old_state, rerr); 42099b44c3bSlianep break; 42199b44c3bSlianep 42299b44c3bSlianep case RESTARTER_STATE_DISABLED: 42399b44c3bSlianep err = gt_enter_disabled(h, v, old_state, rerr); 42499b44c3bSlianep break; 42599b44c3bSlianep 42699b44c3bSlianep case RESTARTER_STATE_OFFLINE: 42799b44c3bSlianep err = gt_enter_offline(h, v, old_state, rerr); 42899b44c3bSlianep break; 42999b44c3bSlianep 43099b44c3bSlianep case RESTARTER_STATE_ONLINE: 43199b44c3bSlianep err = gt_enter_online(h, v, old_state, rerr); 43299b44c3bSlianep break; 43399b44c3bSlianep 43499b44c3bSlianep case RESTARTER_STATE_DEGRADED: 43599b44c3bSlianep err = gt_enter_degraded(h, v, old_state, rerr); 43699b44c3bSlianep break; 43799b44c3bSlianep 43899b44c3bSlianep case RESTARTER_STATE_MAINT: 43999b44c3bSlianep err = gt_enter_maint(h, v, old_state, rerr); 44099b44c3bSlianep break; 44199b44c3bSlianep 44299b44c3bSlianep default: 443cd3bce3eSlianep /* Shouldn't be in an invalid state. */ 44499b44c3bSlianep #ifndef NDEBUG 44556e23938Sbustos uu_warn("%s:%d: Invalid state %d.\n", __FILE__, __LINE__, 446cd3bce3eSlianep v->gv_state); 44799b44c3bSlianep #endif 44899b44c3bSlianep abort(); 44999b44c3bSlianep } 45099b44c3bSlianep 45156e23938Sbustos switch (err) { 45256e23938Sbustos case 0: 45356e23938Sbustos break; 45456e23938Sbustos 45556e23938Sbustos case ECONNABORTED: 45656e23938Sbustos lost_repository = 1; 45756e23938Sbustos break; 45856e23938Sbustos 45956e23938Sbustos default: 46056e23938Sbustos #ifndef NDEBUG 46156e23938Sbustos uu_warn("%s:%d: " 46256e23938Sbustos "gt_enter_%s() failed with unexpected error %d.\n", 46356e23938Sbustos __FILE__, __LINE__, instance_state_str[v->gv_state], err); 46456e23938Sbustos #endif 46556e23938Sbustos abort(); 46656e23938Sbustos } 46756e23938Sbustos 46856e23938Sbustos return (lost_repository ? ECONNABORTED : 0); 46999b44c3bSlianep } 470