📄 failover.c
字号:
for (s = shared_networks; s; s = s -> next) { for (p = s -> pools; p; p = p -> next) { if (p -> failover_peer == state) { for (l = p -> expired; l; l = l -> next) l -> tsfp = state -> me.stos + state -> mclt; if (p -> next_event_time > state -> me.stos + state -> mclt) { p -> next_event_time = state -> me.stos + state -> mclt;#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +%d %s", (int)(cur_time - p -> next_event_time), "pool_timer");#endif add_timeout (p -> next_event_time, pool_timer, p, (tvref_t)pool_reference, (tvunref_t)pool_dereference); } } } } break; default: break; } return ISC_R_SUCCESS;}isc_result_t dhcp_failover_peer_state_changed (dhcp_failover_state_t *state, failover_message_t *msg){ enum failover_state previous_state = state -> partner.state; enum failover_state new_state; int startupp; isc_result_t status; new_state = msg -> server_state; startupp = (msg -> server_flags & FTF_STARTUP) ? 1 : 0; if (state -> partner.state == new_state && state -> me.state) { switch (state -> me.state) { case startup: dhcp_failover_set_state (state, state -> saved_state); return ISC_R_SUCCESS; case unknown_state: case normal: case potential_conflict: case recover_done: case shut_down: case paused: case recover_wait: return ISC_R_SUCCESS; /* If we get a peer state change when we're disconnected, we always process it. */ case partner_down: case communications_interrupted: case resolution_interrupted: case recover: break; } } state -> partner.state = new_state; log_info ("failover peer %s: peer moves from %s to %s", state -> name, dhcp_failover_state_name_print (previous_state), dhcp_failover_state_name_print (state -> partner.state)); if (!write_failover_state (state) || !commit_leases ()) { /* This is bad, but it's not fatal. Of course, if we can't write to the lease database, we're not going to get much done anyway. */ log_error ("Unable to record current failover state for %s", state -> name); } /* Do any state transitions that are required as a result of the peer's state transition. */ switch (state -> me.state == startup ? state -> saved_state : state -> me.state) { case startup: /* can't happen. */ break; case normal: switch (new_state) { case normal: dhcp_failover_state_pool_check (state); break; case communications_interrupted: break; case partner_down: if (state -> me.state == startup) dhcp_failover_set_state (state, recover); else dhcp_failover_set_state (state, potential_conflict); break; case potential_conflict: case resolution_interrupted: /* None of these transitions should ever occur. */ dhcp_failover_set_state (state, shut_down); break; case recover: dhcp_failover_set_state (state, partner_down); break; case shut_down: /* XXX This one is specified, but it's specified in XXX the documentation for the shut_down state, XXX not the normal state. */ dhcp_failover_set_state (state, partner_down); break; case paused: dhcp_failover_set_state (state, communications_interrupted); break; case recover_wait: case recover_done: /* We probably don't need to do anything here. */ break; case unknown_state: case startup: break; } break; case recover: switch (new_state) { case recover: log_info ("failover peer %s: requesting %s", state -> name, "full update from peer"); /* Don't send updreqall if we're really in the startup state, because that will result in two being sent. */ if (state -> me.state == recover) dhcp_failover_send_update_request_all (state); break; case potential_conflict: case resolution_interrupted: case normal: dhcp_failover_set_state (state, potential_conflict); break; case partner_down: case communications_interrupted: /* We're supposed to send an update request at this point. */ /* XXX we don't currently have code here to do any XXX clever detection of when we should send an XXX UPDREQALL message rather than an UPDREQ XXX message. What to do, what to do? */ dhcp_failover_send_update_request (state); break; case shut_down: /* XXX We're not explicitly told what to do in this XXX case, but this transition is consistent with XXX what is elsewhere in the draft. */ dhcp_failover_set_state (state, partner_down); break; /* We can't really do anything in this case. */ case paused: break; /* We should have asked for an update already. */ case recover_done: case recover_wait: break; case unknown_state: case startup: break; } break; case potential_conflict: switch (new_state) { case normal: if (previous_state == potential_conflict && state -> i_am == secondary) dhcp_failover_send_update_request (state); break; case recover_done: case recover_wait: case potential_conflict: case partner_down: case communications_interrupted: case resolution_interrupted: case paused: break; case recover: dhcp_failover_set_state (state, recover); break; case shut_down: dhcp_failover_set_state (state, partner_down); break; case unknown_state: case startup: break; } break; case partner_down: /* Take no action if other server is starting up. */ if (startupp) break; switch (new_state) { /* This is where we should be. */ case recover: case recover_wait: break; case recover_done: dhcp_failover_set_state (state, normal); break; case normal: case potential_conflict: case partner_down: case communications_interrupted: case resolution_interrupted: dhcp_failover_set_state (state, potential_conflict); break; /* These don't change anything. */ case shut_down: case paused: break; case unknown_state: case startup: break; } break; case communications_interrupted: switch (new_state) { case paused: /* Stick with the status quo. */ break; /* If we're in communications-interrupted and an amnesiac peer connects, go to the partner_down state immediately. */ case recover: dhcp_failover_set_state (state, partner_down); break; case normal: case communications_interrupted: case recover_done: case recover_wait: /* XXX so we don't need to do this specially in XXX the CONNECT and CONNECTACK handlers. */ dhcp_failover_send_updates (state); dhcp_failover_set_state (state, normal); break; case potential_conflict: case partner_down: case resolution_interrupted: dhcp_failover_set_state (state, potential_conflict); break; case shut_down: dhcp_failover_set_state (state, partner_down); break; case unknown_state: case startup: break; } break; case resolution_interrupted: switch (new_state) { case normal: case recover: case potential_conflict: case partner_down: case communications_interrupted: case resolution_interrupted: case recover_done: case recover_wait: dhcp_failover_set_state (state, potential_conflict); break; case shut_down: dhcp_failover_set_state (state, partner_down); break; case paused: break; case unknown_state: case startup: break; } break; case recover_done: switch (new_state) { case normal: case recover_done: dhcp_failover_set_state (state, normal); break; case potential_conflict: case partner_down: case communications_interrupted: case resolution_interrupted: case paused: case recover: case recover_wait: break; case shut_down: dhcp_failover_set_state (state, partner_down); break; case unknown_state: case startup: break; } break; /* We are essentially dead in the water when we're in either shut_down or paused states, and do not do any automatic state transitions. */ case shut_down: case paused: break; /* We still have to wait... */ case recover_wait: break; case unknown_state: break; } /* If we didn't make a transition out of startup as a result of the peer's state change, do it now as a result of the fact that we got a state change from the peer. */ if (state -> me.state == startup && state -> saved_state != startup) dhcp_failover_set_state (state, state -> saved_state); /* For now, just set the service state based on the peer's state if necessary. */ dhcp_failover_set_service_state (state); return ISC_R_SUCCESS;}int dhcp_failover_pool_rebalance (dhcp_failover_state_t *state){ int lts; int leases_queued = 0; struct lease *lp = (struct lease *)0; struct lease *next = (struct lease *)0; struct shared_network *s; struct pool *p; int polarity; binding_state_t peer_lease_state; binding_state_t my_lease_state; struct lease **lq; int tenper; if (state -> me.state != normal || state -> i_am == secondary) return 0; for (s = shared_networks; s; s = s -> next) { for (p = s -> pools; p; p = p -> next) { if (p -> failover_peer != state) continue; /* Right now we're giving the peer half of the free leases. If we have more leases than the peer (i.e., more than half), then the number of leases we have, less the number of leases the peer has, will be how many more leases we have than the peer has. So if we send half that number to the peer, we should be even. */ if (p -> failover_peer -> i_am == primary) { lts = (p -> free_leases - p -> backup_leases) / 2; peer_lease_state = FTS_BACKUP; my_lease_state = FTS_FREE; lq = &p -> free; } else { lts = (p -> backup_leases - p -> free_leases) / 2; peer_lease_state = FTS_FREE; my_lease_state = FTS_BACKUP; lq = &p -> backup; } tenper = (p -> backup_leases + p -> free_leases) / 10; if (tenper == 0) tenper = 1; if (lts > tenper) { log_info ("pool %lx %s total %d free %d %s %d lts %d", (unsigned long)p, (p -> shared_network ? p -> shared_network -> name : ""), p -> lease_count, p -> free_leases, "backup", p -> backup_leases, lts); lease_reference (&lp, *lq, MDL); while (lp && lts) { /* Remember the next lease in the list. */ if (next) lease_dereference (&next, MDL); if (lp -> next) lease_reference (&next, lp -> next, MDL); --lts; ++leases_queued; lp -> next_bind
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -