OpenSDN source code
ifmap_agent_sandesh.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sandesh/request_pipeline.h>
6 
7 #include <boost/bind/bind.hpp>
8 #include <boost/assign/list_of.hpp>
9 #include <boost/uuid/uuid_io.hpp>
10 #include <boost/algorithm/string/trim.hpp>
11 
12 #include "base/logging.h"
13 #include "db/db.h"
14 #include "db/db_table_partition.h"
15 #include "base/bitset.h"
16 
17 #include <ifmap/ifmap_update.h>
18 #include <ifmap/ifmap_table.h>
20 #include <ifmap/ifmap_node.h>
21 #include <ifmap/ifmap_agent_types.h>
23 #include <pugixml/pugixml.hpp>
24 
25 using namespace boost::assign;
26 using namespace std;
27 using namespace boost::placeholders;
28 
30 public:
31  static DB *db_;
34  vector<string> send_buffer;
35  };
36 
38  return static_cast<RequestPipeline::InstData *>(new ShowData);
39  }
40 
41  void MakeNode(const string &name_sub_string,
42  const string &link_type_sub_string,
43  const string &link_node_sub_string,
44  string &dst, DBEntryBase *src);
45 
46  bool BufferStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
47  int stage, int instNum, RequestPipeline::InstData *data);
48  bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
49  int stage, int instNum, RequestPipeline::InstData *data);
50  void TableToBuffer(const ShowIFMapAgentReq *request, IFMapTable *table,
51  ShowData *show_data);
52 
53  bool BufferAllTables(const RequestPipeline::PipeSpec ps,
55  bool BufferSomeTables(const RequestPipeline::PipeSpec ps,
57 };
58 
61 
62 static inline void to_uuid(uint64_t ms_long, uint64_t ls_long,
63  boost::uuids::uuid &u) {
64  for (int i = 0; i < 8; i++) {
65  u.data[7 - i] = ms_long & 0xFF;
66  ms_long = ms_long >> 8;
67  }
68 
69  for (int i = 0; i < 8; i++) {
70  u.data[15 - i] = ls_long & 0xFF;
71  ls_long = ls_long >> 8;
72  }
73 }
74 
75 
76 void xml_parse(pugi::xml_node &node, string &s, int n) {
77  int child;
78  pugi::xml_node chld;
79  pugi::xml_node fchld;
80  string t(n, '\t');
81  static uint64_t uuid_ms;
82  static uint64_t uuid_ls;
83  static int ls_set = 0;
84  static int ms_set = 0;
85 
86  switch(node.type()) {
87  case pugi::node_element:
88  child = 0;
89  for(chld = node.first_child(); chld; chld = chld.next_sibling()) {
90  child++;
91  fchld = chld;
92  }
93 
94  if (strlen(node.child_value()) == 0) {
95  if (!child) {
96  break;
97  }
98  if ((child == 1) && (fchld.type() == pugi::node_pcdata) && (strlen(fchld.child_value()) == 0)) {
99  break;
100  }
101  }
102 
103  if (strcmp(node.name(), "uuid-mslong") == 0) {
104  string value(node.child_value());
105  boost::trim(value);
106  uuid_ms = strtoull(value.c_str(), NULL, 10);
107  ms_set = 1;
108  }
109 
110  if (strcmp(node.name(), "uuid-lslong") == 0) {
111  string value(node.child_value());
112  boost::trim(value);
113  uuid_ls = strtoull(value.c_str(), NULL, 10);
114  ls_set = 1;
115  }
116 
117  if (strcmp(node.name(), "config") && strcmp(node.name(), "node")) {
118 
119  if (strlen(node.child_value())) {
120  s = s + t + node.name() + ":" + node.child_value() + "\n";
121  } else {
122  s = s + t + node.name() + "\n";
123  }
124  }
125 
126  if (ms_set && ls_set) {
128  to_uuid(uuid_ms, uuid_ls, u);
129  string tmp = UuidToString(u);
130  s = s + t + "Uuid : " + tmp + "\n";
131  ms_set = ls_set = 0;
132  }
133 
134  for (pugi::xml_attribute_iterator ait = node.attributes_begin(); ait != node.attributes_end(); ++ait) {
135  s = s + t + ait->name() + ":" + ait->value() + "\n";
136  }
137 
138  for(pugi::xml_node chld = node.first_child(); chld; chld = chld.next_sibling()) {
139  xml_parse(chld, s, n + 1);
140  }
141  break;
142 
143  case pugi::node_pcdata:
144  s = s + node.child_value() + "\n";
145  break;
146 
147  default:
148  break;
149  }
150 }
151 void ShowIFMapAgentTable::MakeNode(const string &name_sub_string,
152  const string &link_node_sub_string,
153  const string &link_type_sub_string,
154  string &dst, DBEntryBase *src) {
155  IFMapNode *node = static_cast<IFMapNode *>(src);
156  pugi::xml_document doc;
157  pugi::xml_node config;
158 
159  if (name_sub_string.empty() == false) {
160  if (node->name().find(name_sub_string) == string::npos)
161  return;
162  }
163 
164  dst += "\n";
165  if (!node->IsDeleted()) {
166  config = doc.append_child("config");
167  } else {
168  config = doc.append_child("Delete Marked config");
169  }
170 
171  node->EncodeNodeDetail(&config);
172  xml_parse(config, dst, 1);
173 
174  if (node->IsDeleted()) {
175  return;
176  }
177 
178  // Display its adjacencies
179  dst = dst + "Adjacencies:\n";
180  IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
182  iter = node->begin(table->GetGraph());
183  iter != node->end(table->GetGraph()); ++iter) {
184  IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
185 
186  if (link_type_sub_string.empty() == false) {
187  // Check if filter passes the table-name for the adjacency
188  if (strstr(adj_node->table()->Typename(),
189  link_type_sub_string.c_str()) == NULL)
190  continue;
191  }
192 
193  if (link_node_sub_string.empty() == false) {
194  // Check if filter passes the node-name for the adjacency
195  if (adj_node->name().find(link_node_sub_string) == string::npos)
196  continue;
197  }
198 
199  dst = dst + "\t" + adj_node->table()->Typename() + " " +
200  adj_node->name() +"\n";
201  }
202 }
203 
204 void ShowIFMapAgentTable::TableToBuffer(const ShowIFMapAgentReq *request,
205  IFMapTable *table,
206  ShowData *show_data) {
207  for (int i = 0; i < IFMapTable::kPartitionCount; i++) {
208  DBTablePartBase *partition = table->GetTablePartition(i);
209  DBEntryBase *src = partition->GetFirst();
210  while (src) {
211  string dst;
212  MakeNode(request->get_node_sub_string(),
213  request->get_link_node_sub_string(),
214  request->get_link_type_sub_string(),
215  dst, src);
216  if (dst.empty() == false)
217  show_data->send_buffer.push_back(dst);
218  src = partition->GetNext(src);
219  }
220  }
221 }
222 
225  const ShowIFMapAgentReq *request =
226  static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
227 
228  IFMapTable *table = IFMapTable::FindTable(db_, request->get_table_name());
229  if (table == NULL) {
230  LOG(DEBUG, "Invalid table name: " << request->get_table_name());
231  return true;
232  }
233 
234  if (table->name().find("__ifmap__.") != 0) {
235  LOG(DEBUG, "Invalid table name: " << request->get_table_name());
236  return true;
237  }
238 
239  ShowData *show_data = static_cast<ShowData *>(data);
240  TableToBuffer(request, table, show_data);
241  return true;
242 }
243 
246 
247  const ShowIFMapAgentReq *request =
248  static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
249  for (DB::iterator iter = db_->lower_bound("__ifmap__.");
250  iter != db_->end(); ++iter) {
251  if (iter->first.find("__ifmap__.") != 0) {
252  break;
253  }
254  IFMapTable *table = static_cast<IFMapTable *>(iter->second);
255  ShowData *show_data = static_cast<ShowData *>(data);
256  TableToBuffer(request, table, show_data);
257  }
258 
259  return true;
260 }
261 
263  const RequestPipeline::PipeSpec ps,
264  int stage, int instNum,
266 
267  const ShowIFMapAgentReq *request =
268  static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
269  // If table name has not been passed, print all tables
270  if (request->get_table_name().length()) {
271  return BufferSomeTables(ps, data);
272  } else {
273  return BufferAllTables(ps, data);
274  }
275 }
276 
278  const RequestPipeline::PipeSpec ps,
279  int stage, int instNum,
281  const RequestPipeline::StageData *stage_data = ps.GetStageData(0);
282  const ShowIFMapAgentTable::ShowData &show_data =
283  static_cast<const ShowIFMapAgentTable::ShowData &> (stage_data->at(0));
284  const ShowIFMapAgentReq *request =
285  static_cast<const ShowIFMapAgentReq *>(ps.snhRequest_.get());
286  ShowIFMapAgentResp *response = new ShowIFMapAgentResp();
287  response->set_table_data(show_data.send_buffer);
288  response->set_context(request->context());
289  response->set_more(false);
290  response->Response();
291  return true;
292 }
293 
294 void ShowIFMapAgentReq::HandleRequest() const {
295  ShowIFMapAgentTable show_table;
296 
299 
300  // 2 stages - first: gather/read, second: send
301 
302  s0.taskId_ = scheduler->GetTaskId("db::DBTable");
303  s0.allocFn_ = boost::bind(&ShowIFMapAgentTable::AllocData, &show_table, _1);
304  s0.cbFn_ = boost::bind(&ShowIFMapAgentTable::BufferStage, &show_table,
305  _1, _2, _3, _4, _5);
306  s0.instances_.push_back(0);
307 
308  // Agent ifmap show command task
309  s1.taskId_ = scheduler->GetTaskId("agent_ifmap::ShowCommand");
310  s1.allocFn_ = boost::bind(&ShowIFMapAgentTable::AllocData, &show_table, _1);
311  s1.cbFn_ = boost::bind(&ShowIFMapAgentTable::SendStage, &show_table,
312  _1, _2, _3, _4, _5);
313  s1.instances_.push_back(0);
314 
315  RequestPipeline::PipeSpec ps(this);
316  ps.stages_= list_of(s0)(s1)
317  .convert_to_container<vector<RequestPipeline::StageSpec> >();
318  RequestPipeline rp(ps);
319 }
320 
321 void ShowIFMapAgentDefLinkReq::HandleRequest() const {
322  ShowIFMapAgentDefLinkResp *resp;
323  resp = new ShowIFMapAgentDefLinkResp();
324 
325  //Get link table
326  IFMapAgentLinkTable *link_table = static_cast<IFMapAgentLinkTable *>(
328 
329  IFMapAgentLinkTable::LinkDefMap::const_iterator dlist_it;
330  std::list<IFMapAgentLinkTable::DeferredNode> *ent;
331  std::list<IFMapAgentLinkTable::DeferredNode>::iterator it;
332 
333  //Get linktables's deferred list
334  const IFMapAgentLinkTable::LinkDefMap &def_list = link_table->GetLinkDefMap();
335 
336  //Get Sandesh response's output list
337  std::vector<IFMapAgentDefLink> &list =
338  const_cast<std::vector<IFMapAgentDefLink>&>(resp->get_def_list());
339 
340  //Iterate left node list
341  for(dlist_it = def_list.begin(); dlist_it != def_list.end(); dlist_it++) {
342  const IFMapTable::RequestKey &temp = dlist_it->first;
343  ent = dlist_it->second;
344 
345  //Iterate the right nodes corresponding to above left node
346  for(it = ent->begin(); it != ent->end(); it++) {
347  IFMapAgentDefLink data;
348  data.set_seq_num((*it).node_key.id_seq_num);
349  data.set_left_node(temp.id_type + ":" +
350  temp.id_name);
351  data.set_metadata((*it).link_metadata);
352  data.set_right_node((*it).node_key.id_type + ":" +
353  (*it).node_key.id_name);
354  list.push_back(data);
355  }
356  }
357  resp->set_context(context());
358  resp->Response();
359  return;
360 }
361 
362 void ShowIFMapAgentStatsReq::HandleRequest() const {
363 
365 
366  if (!parser)
367  return;
368 
369  ShowIFMapAgentStatsResp *resp;
370  resp = new ShowIFMapAgentStatsResp();
371 
372  resp->set_node_updates_processed(parser->node_updates());
373  resp->set_node_deletes_processed(parser->node_deletes());
374  resp->set_link_updates_processed(parser->link_updates());
375  resp->set_link_deletes_processed(parser->link_deletes());
376  resp->set_node_update_parse_errors(parser->node_update_parse_errors());
377  resp->set_link_update_parse_errors(parser->link_update_parse_errors());
378  resp->set_node_delete_parse_errors(parser->node_delete_parse_errors());
379  resp->set_link_delete_parse_errors(parser->link_delete_parse_errors());
380 
381  resp->set_context(context());
382  resp->Response();
383  return;
384 }
385 
389 }
bool IsDeleted() const
Definition: db_entry.h:48
adjacency_iterator end(DBGraph *graph)
adjacency_iterator begin(DBGraph *graph)
const std::string & name() const
Definition: db_table.h:110
virtual DBEntryBase * GetNext(const DBEntryBase *)=0
virtual DBEntryBase * GetFirst()=0
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:462
Definition: db.h:24
TableMap::iterator iterator
Definition: db.h:29
DBTableBase * FindTable(const std::string &name)
Definition: db.cc:68
std::map< IFMapTable::RequestKey, std::list< DeferredNode > *, comp > LinkDefMap
const LinkDefMap & GetLinkDefMap() const
uint64_t node_delete_parse_errors()
uint64_t link_update_parse_errors()
uint64_t node_update_parse_errors()
uint64_t link_delete_parse_errors()
const DBGraph * GetGraph() const
IFMapTable * table()
Definition: ifmap_node.h:29
const std::string & name() const
Definition: ifmap_node.h:48
void EncodeNodeDetail(pugi::xml_node *parent) const
Definition: ifmap_node.cc:99
static IFMapTable * FindTable(DB *db, const std::string &element_type)
Definition: ifmap_table.cc:39
virtual const char * Typename() const =0
static const int kPartitionCount
Definition: ifmap_table.h:16
boost::ptr_vector< InstData > StageData
bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
bool BufferAllTables(const RequestPipeline::PipeSpec ps, RequestPipeline::InstData *data)
void MakeNode(const string &name_sub_string, const string &link_type_sub_string, const string &link_node_sub_string, string &dst, DBEntryBase *src)
RequestPipeline::InstData * AllocData(int stage)
bool BufferSomeTables(const RequestPipeline::PipeSpec ps, RequestPipeline::InstData *data)
static IFMapAgentParser * parser_
bool BufferStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
void TableToBuffer(const ShowIFMapAgentReq *request, IFMapTable *table, ShowData *show_data)
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:304
int GetTaskId(const std::string &name)
Definition: task.cc:861
static TaskScheduler * GetInstance()
Definition: task.cc:554
void IFMapAgentSandeshInit(DB *db, IFMapAgentParser *parser)
void xml_parse(pugi::xml_node &node, string &s, int n)
static void to_uuid(uint64_t ms_long, uint64_t ls_long, boost::uuids::uuid &u)
#define IFMAP_AGENT_LINK_DB_NAME
#define LOG(_Level, _Msg)
Definition: logging.h:34
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
boost::shared_ptr< const SandeshRequest > snhRequest_
const StageData * GetStageData(int stage) const
std::vector< int > instances_
boost::uuids::uuid uuid