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