Skip to content

Commit

Permalink
Warm reboot: Add common warm start functions to be used by all SWSS p…
Browse files Browse the repository at this point in the history
…rocesses (#547)

* Add common warm start functions to be used by all SWSS processes

Signed-off-by: Jipan Yang <[email protected]>

* Use updated state schema

Signed-off-by: Jipan Yang <[email protected]>

* Adapt to the new warm reboot schema

Signed-off-by: Jipan Yang <[email protected]>

* Use the new Table::getEntry() and Table::setEntry to replace redisClient operations

Signed-off-by: Jipan Yang <[email protected]>

* use the new Table:hget() and Table:hset() APIs

Signed-off-by: Jipan Yang <[email protected]>

* Add illustration about warm start knob usage

Signed-off-by: Jipan Yang <[email protected]>
  • Loading branch information
jipanyang authored and lguohan committed Aug 9, 2018
1 parent bfce363 commit 8779018
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
115 changes: 115 additions & 0 deletions warmrestart/warm_restart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include <string>
#include "logger.h"
#include "schema.h"
#include "warm_restart.h"

namespace swss {

const WarmStart::WarmStartStateNameMap WarmStart::warmStartStateNameMap =
{
{INIT, "init"},
{RESTORED, "restored"},
{RECONCILED, "reconciled"}
};

WarmStart &WarmStart::getInstance()
{
static WarmStart m_warmStart;
return m_warmStart;
}

/*
* <1> Upon system reboot, the system enable knob will be checked.
* If enabled, database data will be preserved, if not, database will be flushed.
* No need to check docker level knobs in this case since the whole system is being rebooted .
* <2> Upon docker service start, first to check system knob.
* if enabled, docker warm start should be performed, otherwise system warm reboot will be ruined.
* If system knob disabled, while docker knob enabled, this is likely an individual docker warm restart request.
* Within each application which should take care warm start case,
* when the system knob or docker knob enabled, we do further check on the
* actual warm start state ( restart_count), if no warm start state data available,
* the database has been flushed, do cold start. Otherwise warm start.
*/

// Check warm start flag at the very begining of application, do it once for each process.
bool WarmStart::checkWarmStart(const std::string &app_name, const std::string &docker_name)
{
auto& warmStart = getInstance();

if (warmStart.m_stateDb)
{
return true;
}

warmStart.m_stateDb = std::make_shared<swss::DBConnector>(STATE_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0);
warmStart.m_stateWarmRestartTable = std::unique_ptr<Table>(new Table(warmStart.m_stateDb.get(), STATE_WARM_RESTART_TABLE_NAME));

warmStart.m_cfgDb = std::make_shared<swss::DBConnector>(CONFIG_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0);
warmStart.m_cfgWarmRestartTable = std::unique_ptr<Table>(new Table(warmStart.m_cfgDb.get(), CFG_WARM_RESTART_TABLE_NAME));

warmStart.enabled = false;

std::string value;
// Check system level warm restart config first
warmStart.m_cfgWarmRestartTable->hget("system", "enable", value);
if (value == "true")
{
warmStart.enabled = true;
}

// docker level warm restart configuration
warmStart.m_cfgWarmRestartTable->hget(docker_name, "enable", value);
if (value == "true")
{
warmStart.enabled = true;
}

// For cold start, the whole state db will be flushed including warm start table.
// Create the entry for this app here.
if (!warmStart.enabled)
{
warmStart.m_stateWarmRestartTable->hset(app_name, "restart_count", "0");
return true;
}

uint32_t restart_count = 0;
warmStart.m_stateWarmRestartTable->hget(app_name, "restart_count", value);
if (value == "")
{
SWSS_LOG_WARN("%s doing warm start, but restart_count not found in stateDB %s table, fall back to cold start",
app_name.c_str(), STATE_WARM_RESTART_TABLE_NAME);
warmStart.enabled = false;
warmStart.m_stateWarmRestartTable->hset(app_name, "restart_count", "0");
return true;
}
else
{
restart_count = (uint32_t)stoul(value);
}

restart_count++;
warmStart.m_stateWarmRestartTable->hset(app_name, "restart_count", std::to_string(restart_count));
SWSS_LOG_NOTICE("%s doing warm start, restart count %d", app_name.c_str(), restart_count);

return true;
}

bool WarmStart::isWarmStart()
{
auto& warmStart = getInstance();

return warmStart.enabled;
}

// Set the state restored flag
void WarmStart::setWarmStartState(const std::string &app_name, WarmStartState state)
{
auto& warmStart = getInstance();

warmStart.m_stateWarmRestartTable->hset(app_name, "state", warmStartStateNameMap.at(state).c_str());
SWSS_LOG_NOTICE("%s warm start state changed to %s", app_name.c_str(), warmStartStateNameMap.at(state).c_str());
}

}
38 changes: 38 additions & 0 deletions warmrestart/warm_restart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef SWSS_WARM_RESTART_H
#define SWSS_WARM_RESTART_H

#include <string>
#include "dbconnector.h"
#include "table.h"

namespace swss {

class WarmStart
{
public:
enum WarmStartState
{
INIT,
RESTORED,
RECONCILED,
};

typedef std::map<WarmStartState, std::string> WarmStartStateNameMap;
static const WarmStartStateNameMap warmStartStateNameMap;

static WarmStart &getInstance();

static bool checkWarmStart(const std::string &app_name, const std::string &docker_name = "swss");
static bool isWarmStart();
static void setWarmStartState(const std::string &app_name, WarmStartState state);
private:
std::shared_ptr<swss::DBConnector> m_stateDb;
std::shared_ptr<swss::DBConnector> m_cfgDb;
std::unique_ptr<Table> m_stateWarmRestartTable;
std::unique_ptr<Table> m_cfgWarmRestartTable;
bool enabled;
};

}

#endif

0 comments on commit 8779018

Please sign in to comment.