Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warm reboot for general Orch #572

Merged
merged 4 commits into from
Aug 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 50 additions & 17 deletions orchagent/orch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ vector<Selectable *> Orch::getSelectables()
return selectables;
}

void Consumer::addToSync(std::deque<KeyOpFieldsValuesTuple> &entries)
size_t Consumer::addToSync(std::deque<KeyOpFieldsValuesTuple> &entries)
{
SWSS_LOG_ENTER();

/* Nothing popped */
if (entries.empty())
{
return;
return 0;
}

for (auto& entry: entries)
Expand Down Expand Up @@ -120,10 +120,11 @@ void Consumer::addToSync(std::deque<KeyOpFieldsValuesTuple> &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<KeyOpFieldsValuesTuple> entries;
vector<string> keys;
Expand All @@ -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<SubscriberStateTable *>(consumerTable);
if (subTable != NULL)
{
std::deque<KeyOpFieldsValuesTuple> 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()
Expand All @@ -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<Consumer *>(getExecutor(tableName));
auto consumer = dynamic_cast<Consumer *>(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<Consumer *>(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<Consumer *>(executor.get());
if (consumer == NULL)
{
continue;
}

size_t refilled = consumer->refillToSync();
SWSS_LOG_NOTICE("Add warm input: %s, %zd", executorName.c_str(), refilled);
Copy link
Contributor

@lguohan lguohan Aug 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEBUG LEVEL IS better? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer NOTICE since it is important and one time thing. The total lines are about 35.


In reply to: 209397186 [](ancestors = 209397186)

}

consumer->refillToSync(table);
return true;
}

Expand Down
17 changes: 12 additions & 5 deletions orchagent/orch.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,18 @@ class Consumer : public Executor {
return getConsumerTable()->getTableName();
}

void addToSync(std::deque<KeyOpFieldsValuesTuple> &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<KeyOpFieldsValuesTuple> &entries);
};

typedef map<string, std::shared_ptr<Executor>> ConsumerMap;
Expand Down Expand Up @@ -153,9 +156,13 @@ class Orch
vector<Selectable*> 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();

Expand Down
6 changes: 6 additions & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
3 changes: 0 additions & 3 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,6 @@ PortsOrch::PortsOrch(DBConnector *db, vector<table_name_with_pri_t> &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()
Expand Down
2 changes: 1 addition & 1 deletion orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class PortsOrch : public Orch, public Subject
bool isInitDone();

map<string, Port>& getAllPorts();
bool bake();
bool bake() override;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why PortsOrch has its own bake() instead of using Orch::bake()?

void cleanPortTable(const vector<string>& keys);
bool getBridgePort(sai_object_id_t id, Port &port);
bool getPort(string alias, Port &port);
Expand Down