Commit d630dfc7 authored by Marcin Siodelski's avatar Marcin Siodelski

[3534] It is now possible to revert to a selected previous configuration.

parent f5dbfe79
......@@ -396,6 +396,39 @@ CfgMgr::rollback() {
}
}
void
CfgMgr::revert(const size_t index) {
ensureCurrentAllocated();
if (index == 0) {
isc_throw(isc::OutOfRange, "invalid commit index 0 when reverting"
" to an old configuration");
} else if (index > configs_.size() - 1) {
isc_throw(isc::OutOfRange, "unable to revert to commit index '"
<< index << "', only '" << configs_.size() - 1
<< "' previous commits available");
}
// Let's rollback an existing configuration to make sure that the last
// configuration on the list is the current one. Note that all remaining
// operations in this function should be exception free so there shouldn't
// be a problem that the revert operation fails and the staging
// configuration is destroyed by this rollback.
rollback();
// Get the iterator to the current configuration and then advance to the
// desired one.
ConfigurationList::const_reverse_iterator it = configs_.rbegin();
std::advance(it, index);
// Copy the desired configuration to the new staging configuration. The
// staging configuration is re-created here because we rolled back earlier
// in this function.
(*it)->copy(*getStagingCfg());
// Make the staging configuration a current one.
commit();
}
ConstConfigurationPtr
CfgMgr::getCurrentCfg() {
ensureCurrentAllocated();
......
......@@ -424,6 +424,23 @@ public:
/// This function is exception safe.
void rollback();
/// @brief Reverts to one of the previous configurations.
///
/// This function reverts to selected previous configuration. The previous
/// configuration is entirely copied to a new @c Configuration instance. This
/// new instance has a unique sequence id (sequence id is not copied). The
/// previous configuration (being copied) is not modified by this operation.
///
/// The configuration to be copied is identified by the index value which
/// is the distance between the current (most recent) and desired
/// configuration. If the index is out of range an exception is thrown.
///
/// @warning Revert operation will rollback any changes to the staging
/// configuration (if it exists).
///
/// @throw isc::OutOfRange if the specified index is out of range.
void revert(const size_t index);
/// @brief Returns a pointer to the current configuration.
///
/// This function returns pointer to the current configuration. If the
......
......@@ -1209,6 +1209,54 @@ TEST_F(CfgMgrTest, staging) {
EXPECT_EQ(0, config->getLoggingInfo().size());
}
// This test verifies that it is possible to revert to an old configuration.
TEST_F(CfgMgrTest, revert) {
CfgMgr& cfg_mgr = CfgMgr::instance();
// Let's create 5 unique configurations: differing by a debug level in the
// range of 10 to 14.
for (int i = 0; i < 5; ++i) {
ConfigurationPtr config = cfg_mgr.getStagingCfg();
LoggingInfo logging_info;
logging_info.debuglevel_ = i + 10;
config->addLoggingInfo(logging_info);
cfg_mgr.commit();
}
// Now we have 5 configurations with:
// - debuglevel = 99 (a default one)
// - debuglevel = 10
// - debuglevel = 11
// - debuglevel = 12
// - debuglevel = 13
// - debuglevel = 14 (current)
// Hence, the maximum index of the configuration to revert is 5 (which
// points to the configuration with debuglevel = 99). For the index greater
// than 5 we should get an exception.
ASSERT_THROW(cfg_mgr.revert(6), isc::OutOfRange);
// Value of 0 also doesn't make sense.
ASSERT_THROW(cfg_mgr.revert(0), isc::OutOfRange);
// We should be able to revert to configuration with debuglevel = 10.
ASSERT_NO_THROW(cfg_mgr.revert(4));
// And this configuration should be now the current one and the debuglevel
// of this configuration is 10.
EXPECT_EQ(10, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
// The new set of configuration is now as follows:
// - debuglevel = 99
// - debuglevel = 10
// - debuglevel = 11
// - debuglevel = 12
// - debuglevel = 13
// - debuglevel = 14
// - debuglevel = 10 (current)
// So, reverting to configuration having index 3 means that the debug level
// of the current configuration will become 12.
ASSERT_NO_THROW(cfg_mgr.revert(3));
EXPECT_EQ(12, cfg_mgr.getCurrentCfg()->getLoggingInfo()[0].debuglevel_);
}
/// @todo Add unit-tests for testing:
/// - addActiveIface() with invalid interface name
/// - addActiveIface() with the same interface twice
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment