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