case HA_COMMUNICATION_RECOVERY_ST:
case HA_PARTNER_DOWN_ST:
case HA_PARTNER_IN_MAINTENANCE_ST:
- case HA_READY_ST:
verboseTransition(HA_WAITING_ST);
break;
+ case HA_READY_ST:
+ // If partner allocated new leases for which it didn't send lease updates
+ // to us we should synchronize our database.
+ if (communication_state_->hasPartnerNewUnsentUpdates()) {
+ verboseTransition(HA_WAITING_ST);
+ } else {
+ // We did not miss any lease updates. There is no need to synchronize
+ // the database.
+ verboseTransition(getNormalState());
+ }
+ break;
+
case HA_TERMINATED_ST:
verboseTransition(HA_TERMINATED_ST);
break;
// if we failed here.
}
+ auto unsent_update_count = args->get("unsent-update-count");
+ if (unsent_update_count) {
+ if (unsent_update_count->getType() != Element::integer) {
+ isc_throw(CtrlChannelError, "unsent-update-count returned in"
+ " the ha-heartbeat response is not an integer");
+ }
+ communication_state_->setPartnerUnsentUpdateCount(static_cast<uint64_t>(unsent_update_count->intValue()));
+ }
+
} catch (const std::exception& ex) {
LOG_WARN(ha_logger, HA_HEARTBEAT_FAILED)
.arg(partner_config->getLogLabel())
arguments->set("date-time", Element::create(HttpDateTime().rfc1123Format()));
}
+ // Insert unsent-update-count if not present.
+ if (arguments && !arguments->contains("unsent-update-count")) {
+ arguments->set("unsent-update-count", Element::create(int64_t(0)));
+ }
+
response_body->add(boost::const_pointer_cast<Element>
(createAnswer(control_result, "response returned",
arguments)));
const TestHttpResponseCreatorFactoryPtr& factory,
const std::string& initial_state = "waiting")
: listener_(listener), factory_(factory), running_(false),
- static_date_time_(), static_scopes_() {
+ static_date_time_(), static_scopes_(),
+ static_unsent_update_count_(0) {
transition(initial_state);
}
}
response_arguments->set("scopes", json_scopes);
}
+ if (static_unsent_update_count_ >= 0) {
+ response_arguments->set("unsent-update-count", Element::create(static_unsent_update_count_));
+ }
factory_->getResponseCreator()->setArguments(response_arguments);
}
+ /// @brief Sets static value of unsent update count.
+ ///
+ /// @param unsent_update_count new value of the unsent update count.
+ /// Specify a negative value to exclude the count from the response.
+ void setUnsentUpdateCount(int64_t unsent_update_count) {
+ static_unsent_update_count_ = unsent_update_count;
+ }
private:
/// @brief Static scopes to be reported.
std::set<std::string> static_scopes_;
+
+ /// @brief Static count of lease updates not sent by the partner
+ /// because the other server was unavailable.
+ int64_t static_unsent_update_count_;
};
/// @brief Shared pointer to a partner.
// Partner shows up and (eventually) transitions to READY state.
HAPartner partner(listener2_, factory2_);
partner.setScopes({ "server1", "server2" });
+ partner.setUnsentUpdateCount(10);
partner.transition("ready");
partner.startup();
EXPECT_EQ(HA_PARTNER_DOWN_ST, service_->getCurrState());
// Partner shows up and (eventually) transitions to READY state.
- partner_.reset(new HAPartner(listener_, factory_, "ready"));
+ partner_.reset(new HAPartner(listener_, factory_));
+ partner_->setUnsentUpdateCount(10);
+ partner_->transition("ready");
partner_->startup();
// PARTNER DOWN state: receive a response from the partner indicating that
FinalState(HA_WAITING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_READY_ST),
- FinalState(HA_WAITING_ST));
+ FinalState(HA_LOAD_BALANCING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_SYNCING_ST),
FinalState(HA_PARTNER_DOWN_ST));
FinalState(HA_WAITING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_READY_ST),
- FinalState(HA_WAITING_ST));
+ FinalState(HA_LOAD_BALANCING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_SYNCING_ST),
FinalState(HA_PARTNER_DOWN_ST));
EXPECT_TRUE(service_->unpause());
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_READY_ST),
- FinalState(HA_WAITING_ST));
+ FinalState(HA_LOAD_BALANCING_ST));
EXPECT_TRUE(state_->isHeartbeatRunning());
}
FinalState(HA_WAITING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_READY_ST),
- FinalState(HA_WAITING_ST));
+ FinalState(HA_HOT_STANDBY_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_SYNCING_ST),
FinalState(HA_PARTNER_DOWN_ST));
FinalState(HA_WAITING_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_READY_ST),
- FinalState(HA_WAITING_ST));
+ FinalState(HA_HOT_STANDBY_ST));
testTransition(MyState(HA_PARTNER_DOWN_ST), PartnerState(HA_SYNCING_ST),
FinalState(HA_PARTNER_DOWN_ST));