From c429ddbe5bd355f6008ecfb92adda4d1ff0308c7 Mon Sep 17 00:00:00 2001 From: Qi Luo Date: Fri, 10 Aug 2018 17:46:37 -0700 Subject: [PATCH] Warm reboot for general Orch (#572) * Warm reboot for BufferOrch * Add log for warm reboot * Add bake() interface * OrchDaemon supports warm start --- orchagent/orch.cpp | 67 ++++++++++++++++++++++++++++++---------- orchagent/orch.h | 17 +++++++--- orchagent/orchdaemon.cpp | 6 ++++ orchagent/portsorch.cpp | 3 -- orchagent/portsorch.h | 2 +- 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/orchagent/orch.cpp b/orchagent/orch.cpp index f86dd849cea3..48b8e5b4271f 100644 --- a/orchagent/orch.cpp +++ b/orchagent/orch.cpp @@ -66,14 +66,14 @@ vector Orch::getSelectables() return selectables; } -void Consumer::addToSync(std::deque &entries) +size_t Consumer::addToSync(std::deque &entries) { SWSS_LOG_ENTER(); /* Nothing popped */ if (entries.empty()) { - return; + return 0; } for (auto& entry: entries) @@ -120,10 +120,11 @@ void Consumer::addToSync(std::deque &entries) m_toSync[key] = KeyOpFieldsValuesTuple(key, op, existing_values); } } + return entries.size(); } // TODO: Table should be const -void Consumer::refillToSync(Table* table) +size_t Consumer::refillToSync(Table* table) { std::deque entries; vector keys; @@ -142,15 +143,28 @@ void Consumer::refillToSync(Table* table) entries.push_back(kco); } - addToSync(entries); + return addToSync(entries); } -void Consumer::refillToSync() +size_t Consumer::refillToSync() { - auto db = getConsumerTable()->getDbConnector(); - string tableName = getConsumerTable()->getTableName(); - auto table = Table(db, tableName); - refillToSync(&table); + ConsumerTableBase *consumerTable = getConsumerTable(); + + auto subTable = dynamic_cast(consumerTable); + if (subTable != NULL) + { + std::deque entries; + subTable->pops(entries); + return addToSync(entries); + } + else + { + // consumerTable is either ConsumerStateTable or ConsumerTable + auto db = consumerTable->getDbConnector(); + string tableName = consumerTable->getTableName(); + auto table = Table(db, tableName); + return refillToSync(&table); + } } void Consumer::execute() @@ -171,31 +185,50 @@ void Consumer::drain() m_orch->doTask(*this); } -bool Orch::addExistingData(const string& tableName) +size_t Orch::addExistingData(const string& tableName) { - Consumer* consumer = dynamic_cast(getExecutor(tableName)); + auto consumer = dynamic_cast(getExecutor(tableName)); if (consumer == NULL) { SWSS_LOG_ERROR("No consumer %s in Orch", tableName.c_str()); - return false; + return 0; } - consumer->refillToSync(); - return true; + return consumer->refillToSync(); } // TODO: Table should be const -bool Orch::addExistingData(Table *table) +size_t Orch::addExistingData(Table *table) { string tableName = table->getTableName(); Consumer* consumer = dynamic_cast(getExecutor(tableName)); if (consumer == NULL) { SWSS_LOG_ERROR("No consumer %s in Orch", tableName.c_str()); - return false; + return 0; + } + + return consumer->refillToSync(table); +} + +bool Orch::bake() +{ + SWSS_LOG_ENTER(); + + for(auto &it : m_consumerMap) + { + string executorName = it.first; + auto executor = it.second; + auto consumer = dynamic_cast(executor.get()); + if (consumer == NULL) + { + continue; + } + + size_t refilled = consumer->refillToSync(); + SWSS_LOG_NOTICE("Add warm input: %s, %zd", executorName.c_str(), refilled); } - consumer->refillToSync(table); return true; } diff --git a/orchagent/orch.h b/orchagent/orch.h index 902192f16be2..14fde1c78a6b 100644 --- a/orchagent/orch.h +++ b/orchagent/orch.h @@ -116,15 +116,18 @@ class Consumer : public Executor { return getConsumerTable()->getTableName(); } - void addToSync(std::deque &entries); - void refillToSync(); - void refillToSync(Table* table); + size_t refillToSync(); + size_t refillToSync(Table* table); void execute(); void drain(); /* Store the latest 'golden' status */ // TODO: hide? SyncMap m_toSync; + +protected: + // Returns: the number of entries added to m_toSync + size_t addToSync(std::deque &entries); }; typedef map> ConsumerMap; @@ -153,9 +156,13 @@ class Orch vector getSelectables(); // add the existing table data (left by warm reboot) to the consumer todo task list. - bool addExistingData(Table *table); - bool addExistingData(const string& tableName); + size_t addExistingData(Table *table); + size_t addExistingData(const string& tableName); + // Prepare for warm start if Redis contains valid input data + // otherwise fallback to cold start + virtual bool bake(); + /* Iterate all consumers in m_consumerMap and run doTask(Consumer) */ void doTask(); diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 26bd446da279..787a07584cda 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -274,6 +274,12 @@ void OrchDaemon::start() { SWSS_LOG_ENTER(); + // Try warm start + for (Orch *o : m_orchList) + { + o->bake(); + } + for (Orch *o : m_orchList) { m_select->addSelectables(o->getSelectables()); diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 8d6f58988c58..74c23723fceb 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -245,9 +245,6 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_portStatusNotificationConsumer = new swss::NotificationConsumer(notificationsDb, "NOTIFICATIONS"); auto portStatusNotificatier = new Notifier(m_portStatusNotificationConsumer, this); Orch::addExecutor("PORT_STATUS_NOTIFICATIONS", portStatusNotificatier); - - // Try warm start - bake(); } void PortsOrch::removeDefaultVlanMembers() diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 2a73ccb6c1bc..fc1d2ae52b64 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -56,7 +56,7 @@ class PortsOrch : public Orch, public Subject bool isInitDone(); map& getAllPorts(); - bool bake(); + bool bake() override; void cleanPortTable(const vector& keys); bool getBridgePort(sai_object_id_t id, Port &port); bool getPort(string alias, Port &port);