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 "base/regex.h"
10 : #include "base/logging.h"
11 : #include "db/db.h"
12 : #include "db/db_graph.h"
13 : #include "db/db_graph_vertex.h"
14 : #include "db/db_table_partition.h"
15 : #include "base/bitset.h"
16 :
17 : #include "config_client_manager.h"
18 : #include "config_db_client.h"
19 : #include "config_client_show_types.h"
20 :
21 : #include "ifmap/ifmap_client.h"
22 : #include "ifmap/ifmap_exporter.h"
23 : #include "ifmap/ifmap_link.h"
24 : #include "ifmap/ifmap_link_table.h"
25 : #include "ifmap/ifmap_log.h"
26 : #include "ifmap/ifmap_node.h"
27 : #include "ifmap/ifmap_object.h"
28 : #include "ifmap/ifmap_origin.h"
29 : #include "ifmap/ifmap_sandesh_context.h"
30 : #include "ifmap/ifmap_server.h"
31 : #include "ifmap/ifmap_server_show_types.h"
32 : #include "ifmap/ifmap_server_show_internal_types.h"
33 : #include "ifmap/ifmap_log_types.h"
34 : #include "ifmap/ifmap_table.h"
35 : #include "ifmap/ifmap_update.h"
36 : #include "ifmap/ifmap_uuid_mapper.h"
37 :
38 : #include <pugixml/pugixml.hpp>
39 :
40 : using namespace boost::assign;
41 : using namespace std;
42 : using namespace pugi;
43 : using namespace boost::placeholders;
44 :
45 : using contrail::regex;
46 : using contrail::regex_match;
47 : using contrail::regex_search;
48 :
49 : class IFMapNodeCopier {
50 : public:
51 0 : IFMapNodeCopier(IFMapNodeShowInfo *dest, DBEntryBase *src,
52 : IFMapServer *server) {
53 : // Get the name of the node
54 0 : IFMapNode *src_node = static_cast<IFMapNode *>(src);
55 0 : dest->node_name = src_node->ToString();
56 :
57 0 : IFMapNodeState *state = server->exporter()->NodeStateLookup(src_node);
58 :
59 0 : if (state) {
60 : // Get the interests and advertised from state
61 0 : dest->interests = state->interest().ToNumberedString();
62 0 : dest->advertised = state->advertised().ToNumberedString();
63 : } else {
64 0 : dest->dbentryflags.append("No state, ");
65 : }
66 :
67 0 : if (src_node->IsDeleted()) {
68 0 : dest->dbentryflags.append("Deleted, ");
69 : }
70 0 : if (src_node->is_onlist()) {
71 0 : dest->dbentryflags.append("OnList, ");
72 : }
73 0 : if (src_node->IsOnRemoveQ()) {
74 0 : dest->dbentryflags.append("OnRemoveQ");
75 : }
76 :
77 0 : dest->obj_info.reserve(src_node->list_.size());
78 0 : for (IFMapNode::ObjectList::const_iterator iter =
79 0 : src_node->list_.begin(); iter != src_node->list_.end(); ++iter) {
80 0 : const IFMapObject *src_obj = iter.operator->();
81 :
82 0 : IFMapObjectShowInfo dest_obj;
83 0 : dest_obj.sequence_number = src_obj->sequence_number();
84 0 : dest_obj.origin = src_obj->origin().ToString();
85 0 : dest_obj.data = GetIFMapObjectData(src_obj);
86 :
87 0 : dest->obj_info.push_back(dest_obj);
88 0 : }
89 0 : if (src_node->IsVertexValid()) {
90 0 : DBGraph *graph = server->graph();
91 0 : int neighbor_count = 0;
92 0 : for (DBGraphVertex::adjacency_iterator iter =
93 0 : src_node->begin(graph); iter != src_node->end(graph); ++iter) {
94 0 : ++neighbor_count;
95 : }
96 0 : dest->neighbors.reserve(neighbor_count);
97 0 : for (DBGraphVertex::adjacency_iterator iter =
98 0 : src_node->begin(graph); iter != src_node->end(graph); ++iter) {
99 0 : IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
100 0 : dest->neighbors.push_back(adj->ToString());
101 : }
102 : }
103 0 : dest->last_modified = src_node->last_change_at_str();
104 0 : }
105 :
106 0 : string GetIFMapObjectData(const IFMapObject *src_obj) {
107 0 : pugi::xml_document xdoc;
108 0 : pugi::xml_node xnode = xdoc.append_child("iq");
109 0 : src_obj->EncodeUpdate(&xnode);
110 :
111 0 : ostringstream oss;
112 0 : xnode.print(oss);
113 0 : string objdata = oss.str();
114 0 : return objdata;
115 0 : }
116 : };
117 :
118 : const string kShowIterSeparator = "||";
119 :
120 : // almost everything in this class is static since we dont really want to
121 : // intantiate this class
122 : class ShowIFMapTable {
123 : public:
124 : static const uint32_t kMaxElementsPerRound = 50;
125 :
126 0 : static int GetPageLimit(IFMapSandeshContext *sctx) {
127 0 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
128 : }
129 :
130 : struct ShowData : public RequestPipeline::InstData {
131 : vector<IFMapNodeShowInfo> send_buffer;
132 : string next_table_name;
133 : string last_node_name;
134 : };
135 :
136 0 : static RequestPipeline::InstData* AllocBuffer(int stage) {
137 0 : return static_cast<RequestPipeline::InstData *>(new ShowData);
138 : }
139 :
140 : static bool BufferStageCommon(const IFMapTableShowReq *request,
141 : RequestPipeline::InstData *data,
142 : const string &next_table_name,
143 : const string &last_node_name);
144 : static bool BufferStage(const Sandesh *sr,
145 : const RequestPipeline::PipeSpec ps, int stage,
146 : int instNum, RequestPipeline::InstData *data);
147 : static bool BufferStageIterate(const Sandesh *sr,
148 : const RequestPipeline::PipeSpec ps, int stage,
149 : int instNum, RequestPipeline::InstData *data);
150 : static void SendStageCommon(const IFMapTableShowReq *request,
151 : const RequestPipeline::PipeSpec ps,
152 : IFMapTableShowResp *response);
153 : static bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
154 : int stage, int instNum,
155 : RequestPipeline::InstData *data);
156 : static bool SendStageIterate(const Sandesh *sr,
157 : const RequestPipeline::PipeSpec ps, int stage,
158 : int instNum, RequestPipeline::InstData *data);
159 : static bool TableToBuffer(const IFMapTableShowReq *request,
160 : IFMapTable *table, IFMapServer *server,
161 : const string &last_node_name,
162 : ShowData *show_data, uint32_t page_limit);
163 : static bool BufferAllTables(const IFMapTableShowReq *req,
164 : RequestPipeline::InstData *data,
165 : const string &next_table_name,
166 : const string &last_node_name);
167 : static bool BufferOneTable(const IFMapTableShowReq *request,
168 : RequestPipeline::InstData *data,
169 : const string &last_node_name);
170 : static bool ConvertReqIterateToReq(
171 : const IFMapTableShowReqIterate *req_iterate,
172 : IFMapTableShowReq *req, string *next_table_name,
173 : string *last_node_name);
174 : };
175 :
176 : // Return true if the buffer is full.
177 0 : bool ShowIFMapTable::TableToBuffer(const IFMapTableShowReq *request,
178 : IFMapTable *table, IFMapServer *server,
179 : const string &last_node_name,
180 : ShowData *show_data, uint32_t page_limit) {
181 0 : DBEntryBase *src = NULL;
182 0 : if (last_node_name.length()) {
183 : // If the last_node_name is set, it was the last node printed in the
184 : // previous round. Search for the node 'after' last_node_name and start
185 : // this round with it. If there is no next node, we are done with this
186 : // table.
187 0 : IFMapNode *last_node = table->FindNextNode(last_node_name);
188 0 : if (last_node) {
189 0 : src = last_node;
190 : } else {
191 0 : return false;
192 : }
193 : }
194 :
195 0 : bool buffer_full = false;
196 0 : regex search_expr(request->get_search_string());
197 0 : DBTablePartBase *partition = table->GetTablePartition(0);
198 0 : if (!src) {
199 0 : src = partition->GetFirst();
200 : }
201 0 : for (; src != NULL; src = partition->GetNext(src)) {
202 0 : IFMapNode *src_node = static_cast<IFMapNode *>(src);
203 0 : if (!regex_search(src_node->ToString(), search_expr)) {
204 0 : continue;
205 : }
206 0 : IFMapNodeShowInfo dest;
207 0 : IFMapNodeCopier copyNode(&dest, src, server);
208 0 : show_data->send_buffer.push_back(dest);
209 :
210 : // If we have picked up enough nodes for this round...
211 0 : if (show_data->send_buffer.size() == page_limit) {
212 : // Save the values needed for the next round. When we come
213 : // back, we will use the 'names' to lookup the elements since
214 : // the 'names' are the keys in the respective tables.
215 0 : show_data->next_table_name = table->name();
216 0 : show_data->last_node_name = src_node->name();
217 0 : buffer_full = true;
218 0 : break;
219 : }
220 0 : }
221 :
222 0 : return buffer_full;
223 0 : }
224 :
225 0 : bool ShowIFMapTable::BufferOneTable(const IFMapTableShowReq *request,
226 : RequestPipeline::InstData *data,
227 : const string &last_node_name) {
228 : IFMapSandeshContext *sctx =
229 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
230 :
231 0 : IFMapTable *table = IFMapTable::FindTable(sctx->ifmap_server()->database(),
232 : request->get_table_name());
233 0 : if (table) {
234 0 : ShowData *show_data = static_cast<ShowData *>(data);
235 0 : uint32_t page_limit = GetPageLimit(sctx);
236 0 : show_data->send_buffer.reserve(page_limit);
237 0 : TableToBuffer(request, table, sctx->ifmap_server(), last_node_name,
238 : show_data, page_limit);
239 : } else {
240 0 : IFMAP_WARN(IFMapTblNotFound, "Cant show/find table ",
241 : request->get_table_name());
242 : }
243 :
244 0 : return true;
245 : }
246 :
247 0 : bool ShowIFMapTable::BufferAllTables(const IFMapTableShowReq *request,
248 : RequestPipeline::InstData *data,
249 : const string &next_table_name,
250 : const string &last_node_name) {
251 : IFMapSandeshContext *sctx =
252 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
253 0 : string last_name = last_node_name;
254 :
255 0 : DB *db = sctx->ifmap_server()->database();
256 0 : DB::iterator iter;
257 0 : if (next_table_name.empty()) {
258 0 : iter = db->lower_bound("__ifmap__.");
259 : } else {
260 0 : iter = db->FindTableIter(next_table_name);
261 : }
262 :
263 0 : ShowData *show_data = static_cast<ShowData *>(data);
264 0 : uint32_t page_limit = GetPageLimit(sctx);
265 0 : show_data->send_buffer.reserve(page_limit);
266 0 : for (; iter != db->end(); ++iter) {
267 0 : if (iter->first.find("__ifmap__.") != 0) {
268 0 : break;
269 : }
270 0 : IFMapTable *table = static_cast<IFMapTable *>(iter->second);
271 0 : bool buffer_full = TableToBuffer(request, table, sctx->ifmap_server(),
272 : last_name, show_data, page_limit);
273 0 : if (buffer_full) {
274 0 : break;
275 : }
276 : // last_node_name is only relevant for the first iteration.
277 0 : last_name.clear();
278 : }
279 :
280 0 : return true;
281 0 : }
282 :
283 : // Format of node_info string:
284 : // table_name||search_string||next_table_name||last_node_name
285 : // table_name/search_string: original input. Could be empty.
286 : // next_table_name: next table to lookup in
287 : // last_node_name: name of last node that was printed in the previous round
288 0 : bool ShowIFMapTable::ConvertReqIterateToReq(
289 : const IFMapTableShowReqIterate *req_iterate,
290 : IFMapTableShowReq *req, string *next_table_name,
291 : string *last_node_name) {
292 : // First, set the context from the original request since we might return
293 : // due to parsing errors.
294 0 : req->set_context(req_iterate->context());
295 :
296 0 : string node_info = req_iterate->get_node_info();
297 0 : size_t sep_size = kShowIterSeparator.size();
298 :
299 : // table_name
300 0 : size_t pos1 = node_info.find(kShowIterSeparator);
301 0 : if (pos1 == string::npos) {
302 0 : return false;
303 : }
304 0 : string table_name = node_info.substr(0, pos1);
305 :
306 : // search_string
307 0 : size_t pos2 = node_info.find(kShowIterSeparator, (pos1 + sep_size));
308 0 : if (pos2 == string::npos) {
309 0 : return false;
310 : }
311 : string search_string = node_info.substr((pos1 + sep_size),
312 0 : pos2 - (pos1 + sep_size));
313 :
314 : // next_table_name
315 0 : size_t pos3 = node_info.find(kShowIterSeparator, (pos2 + sep_size));
316 0 : if (pos3 == string::npos) {
317 0 : return false;
318 : }
319 0 : *next_table_name = node_info.substr((pos2 + sep_size),
320 0 : pos3 - (pos2 + sep_size));
321 :
322 : // last_node_name
323 0 : *last_node_name = node_info.substr(pos3 + sep_size);
324 :
325 : // Fill up the fields of IFMapTableShowReq appropriately.
326 0 : req->set_table_name(table_name);
327 0 : req->set_search_string(search_string);
328 0 : return true;
329 0 : }
330 :
331 0 : bool ShowIFMapTable::BufferStageCommon(const IFMapTableShowReq *request,
332 : RequestPipeline::InstData *data,
333 : const string &next_table_name,
334 : const string &last_node_name) {
335 : // If table name has not been passed, print all tables
336 0 : if (request->get_table_name().length()) {
337 0 : return BufferOneTable(request, data, last_node_name);
338 : } else {
339 0 : return BufferAllTables(request, data, next_table_name, last_node_name);
340 : }
341 : }
342 :
343 0 : bool ShowIFMapTable::BufferStage(const Sandesh *sr,
344 : const RequestPipeline::PipeSpec ps,
345 : int stage, int instNum,
346 : RequestPipeline::InstData *data) {
347 : const IFMapTableShowReq *request =
348 0 : static_cast<const IFMapTableShowReq *>(ps.snhRequest_.get());
349 0 : string next_table_name;
350 0 : string last_node_name;
351 0 : return BufferStageCommon(request, data, next_table_name, last_node_name);
352 0 : }
353 :
354 0 : bool ShowIFMapTable::BufferStageIterate(const Sandesh *sr,
355 : const RequestPipeline::PipeSpec ps,
356 : int stage, int instNum,
357 : RequestPipeline::InstData *data) {
358 : const IFMapTableShowReqIterate *request_iterate =
359 0 : static_cast<const IFMapTableShowReqIterate *>(ps.snhRequest_.get());
360 :
361 0 : string next_table_name;
362 0 : string last_node_name;
363 0 : IFMapTableShowReq *request = new IFMapTableShowReq;
364 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
365 : &next_table_name, &last_node_name);
366 0 : if (success) {
367 0 : BufferStageCommon(request, data, next_table_name, last_node_name);
368 : }
369 0 : request->Release();
370 0 : return true;
371 0 : }
372 :
373 0 : void ShowIFMapTable::SendStageCommon(const IFMapTableShowReq *request,
374 : const RequestPipeline::PipeSpec ps,
375 : IFMapTableShowResp *response) {
376 0 : const RequestPipeline::StageData *prev_stage_data = ps.GetStageData(0);
377 : const ShowIFMapTable::ShowData &show_data =
378 0 : static_cast<const ShowIFMapTable::ShowData&>(prev_stage_data->at(0));
379 : IFMapSandeshContext *sctx =
380 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
381 :
382 0 : vector<IFMapNodeShowInfo> dest_buffer;
383 0 : dest_buffer = show_data.send_buffer;
384 :
385 : // If we have filled the buffer, set next_batch with all the values we will
386 : // need in the next round.
387 0 : string next_batch;
388 0 : uint32_t page_limit = GetPageLimit(sctx);
389 0 : if (dest_buffer.size() == page_limit) {
390 0 : next_batch = request->get_table_name() + kShowIterSeparator +
391 0 : request->get_search_string() + kShowIterSeparator +
392 0 : show_data.next_table_name + kShowIterSeparator +
393 0 : show_data.last_node_name;
394 : }
395 :
396 0 : response->set_ifmap_db(dest_buffer);
397 0 : response->set_next_batch(next_batch);
398 0 : }
399 :
400 0 : bool ShowIFMapTable::SendStage(const Sandesh *sr,
401 : const RequestPipeline::PipeSpec ps,
402 : int stage, int instNum,
403 : RequestPipeline::InstData *data) {
404 : const IFMapTableShowReq *request =
405 0 : static_cast<const IFMapTableShowReq *>(ps.snhRequest_.get());
406 0 : IFMapTableShowResp *response = new IFMapTableShowResp;
407 0 : SendStageCommon(request, ps, response);
408 :
409 0 : response->set_context(request->context());
410 0 : response->set_more(false);
411 0 : response->Response();
412 0 : return true;
413 : }
414 :
415 0 : bool ShowIFMapTable::SendStageIterate(const Sandesh *sr,
416 : const RequestPipeline::PipeSpec ps,
417 : int stage, int instNum,
418 : RequestPipeline::InstData *data) {
419 : const IFMapTableShowReqIterate *request_iterate =
420 0 : static_cast<const IFMapTableShowReqIterate *>(ps.snhRequest_.get());
421 :
422 0 : string next_table_name;
423 0 : string last_node_name;
424 :
425 0 : IFMapTableShowResp *response = new IFMapTableShowResp;
426 0 : IFMapTableShowReq *request = new IFMapTableShowReq;
427 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
428 : &next_table_name, &last_node_name);
429 0 : if (success) {
430 0 : SendStageCommon(request, ps, response);
431 : }
432 :
433 0 : response->set_context(request->context());
434 0 : response->set_more(false);
435 0 : response->Response();
436 :
437 0 : request->Release();
438 0 : return true;
439 0 : }
440 :
441 0 : void IFMapTableShowReq::HandleRequest() const {
442 :
443 0 : RequestPipeline::StageSpec s0, s1;
444 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
445 :
446 : // 2 stages - first: gather/read, second: send
447 :
448 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
449 0 : s0.allocFn_ = ShowIFMapTable::AllocBuffer;
450 0 : s0.cbFn_ = ShowIFMapTable::BufferStage;
451 0 : s0.instances_.push_back(0);
452 :
453 : // control-node ifmap show command task
454 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
455 0 : s1.cbFn_ = ShowIFMapTable::SendStage;
456 0 : s1.instances_.push_back(0);
457 :
458 0 : RequestPipeline::PipeSpec ps(this);
459 0 : ps.stages_ = list_of(s0)(s1)
460 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
461 0 : RequestPipeline rp(ps);
462 0 : }
463 :
464 0 : void IFMapTableShowReqIterate::HandleRequest() const {
465 :
466 0 : RequestPipeline::StageSpec s0, s1;
467 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
468 :
469 : // 2 stages - first: gather/read, second: send
470 :
471 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
472 0 : s0.allocFn_ = ShowIFMapTable::AllocBuffer;
473 0 : s0.cbFn_ = ShowIFMapTable::BufferStageIterate;
474 0 : s0.instances_.push_back(0);
475 :
476 : // control-node ifmap show command task
477 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
478 0 : s1.cbFn_ = ShowIFMapTable::SendStageIterate;
479 0 : s1.instances_.push_back(0);
480 :
481 0 : RequestPipeline::PipeSpec ps(this);
482 0 : ps.stages_ = list_of(s0)(s1)
483 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
484 0 : RequestPipeline rp(ps);
485 0 : }
486 :
487 : // Code to display link-table entries
488 :
489 : class ShowIFMapLinkTable {
490 : public:
491 : static const uint32_t kMaxElementsPerRound = 50;
492 :
493 0 : static int GetPageLimit(IFMapSandeshContext *sctx) {
494 0 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
495 : }
496 :
497 : struct ShowData : public RequestPipeline::InstData {
498 : vector<IFMapLinkShowInfo> send_buffer;
499 : uint32_t table_size;
500 : string last_link_name;
501 : };
502 :
503 0 : static RequestPipeline::InstData* AllocBuffer(int stage) {
504 0 : return static_cast<RequestPipeline::InstData *>(new ShowData);
505 : }
506 :
507 : static bool IncludeLink(DBEntryBase *src, const string &search_string,
508 : const regex &search_expr, const string &metadata,
509 : const regex &metadata_expr);
510 : static void CopyNode(IFMapLinkShowInfo *dest, DBEntryBase *src,
511 : IFMapServer *server);
512 : static bool BufferStageCommon(const IFMapLinkTableShowReq *request,
513 : RequestPipeline::InstData *data,
514 : const string &last_link_name);
515 : static bool BufferStage(const Sandesh *sr,
516 : const RequestPipeline::PipeSpec ps, int stage,
517 : int instNum, RequestPipeline::InstData *data);
518 : static bool BufferStageIterate(const Sandesh *sr,
519 : const RequestPipeline::PipeSpec ps,
520 : int stage, int instNum,
521 : RequestPipeline::InstData *data);
522 : static void SendStageCommon(const IFMapLinkTableShowReq *request,
523 : const RequestPipeline::PipeSpec ps,
524 : IFMapLinkTableShowResp *response);
525 : static bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
526 : int stage, int instNum,
527 : RequestPipeline::InstData *data);
528 : static bool SendStageIterate(const Sandesh *sr,
529 : const RequestPipeline::PipeSpec ps, int stage,
530 : int instNum, RequestPipeline::InstData *data);
531 : static bool ConvertReqIterateToReq(
532 : const IFMapLinkTableShowReqIterate *req_iterate,
533 : IFMapLinkTableShowReq *req, string *last_link_name);
534 : };
535 :
536 0 : bool ShowIFMapLinkTable::IncludeLink(DBEntryBase *src,
537 : const string &search_string,
538 : const regex &search_expr,
539 : const string &metadata,
540 : const regex &metadata_expr) {
541 0 : IFMapLink *link = static_cast<IFMapLink *>(src);
542 0 : IFMapNode *left = link->left();
543 0 : IFMapNode *right = link->right();
544 :
545 : // If we do not find the search string in the names of either of the
546 : // two ends, do not include the link.
547 0 : if (!search_string.empty() &&
548 0 : (!left || !regex_search(left->ToString(), search_expr)) &&
549 0 : (!right || !regex_search(right->ToString(), search_expr))) {
550 0 : return false;
551 : }
552 :
553 : // If the metadata does not match, do not include the link.
554 0 : if (!metadata.empty() && !regex_search(link->metadata(), metadata_expr)) {
555 0 : return false;
556 : }
557 :
558 0 : return true;
559 : }
560 :
561 0 : void ShowIFMapLinkTable::CopyNode(IFMapLinkShowInfo *dest, DBEntryBase *src,
562 : IFMapServer *server) {
563 0 : IFMapLink *src_link = static_cast<IFMapLink *>(src);
564 :
565 0 : dest->metadata = src_link->metadata();
566 0 : if (src_link->left()) {
567 0 : dest->left = src_link->left()->ToString();
568 : }
569 0 : if (src_link->right()) {
570 0 : dest->right = src_link->right()->ToString();
571 : }
572 :
573 : // Get the interests and advertised from state
574 0 : IFMapLinkState *state = server->exporter()->LinkStateLookup(src_link);
575 0 : if (state) {
576 0 : dest->interests = state->interest().ToNumberedString();
577 0 : dest->advertised = state->advertised().ToNumberedString();
578 : } else {
579 0 : dest->dbentryflags.append("No state, ");
580 : }
581 :
582 0 : if (src_link->IsDeleted()) {
583 0 : dest->dbentryflags.append("Deleted, ");
584 : }
585 0 : if (src_link->is_onlist()) {
586 0 : dest->dbentryflags.append("OnList");
587 : }
588 0 : if (src_link->IsOnRemoveQ()) {
589 0 : dest->dbentryflags.append("OnRemoveQ");
590 : }
591 0 : dest->last_modified = src_link->last_change_at_str();
592 :
593 0 : for (std::vector<IFMapLink::LinkOriginInfo>::const_iterator iter =
594 0 : src_link->origin_info_.begin(); iter != src_link->origin_info_.end();
595 0 : ++iter) {
596 0 : const IFMapLink::LinkOriginInfo *origin_info = iter.operator->();
597 0 : IFMapLinkOriginShowInfo dest_origin;
598 0 : dest_origin.sequence_number = origin_info->sequence_number;
599 0 : dest_origin.origin = origin_info->origin.ToString();
600 0 : dest->origins.push_back(dest_origin);
601 0 : }
602 0 : }
603 :
604 : // Format of link_info string:
605 : // search_string||metadata||last_link_name
606 : // search_string: original input. Could be empty.
607 : // metadata: original input. Could be empty.
608 : // last_link_name: name of last link that was printed in the previous round
609 0 : bool ShowIFMapLinkTable::ConvertReqIterateToReq(
610 : const IFMapLinkTableShowReqIterate *req_iterate,
611 : IFMapLinkTableShowReq *req, string *last_link_name) {
612 : // First, set the context from the original request since we might return
613 : // due to parsing errors.
614 0 : req->set_context(req_iterate->context());
615 :
616 0 : string link_info = req_iterate->get_link_info();
617 0 : size_t sep_size = kShowIterSeparator.size();
618 :
619 : // search_string
620 0 : size_t pos1 = link_info.find(kShowIterSeparator);
621 0 : if (pos1 == string::npos) {
622 0 : return false;
623 : }
624 0 : string search_string = link_info.substr(0, pos1);
625 :
626 : // metadata
627 0 : size_t pos2 = link_info.find(kShowIterSeparator, (pos1 + sep_size));
628 0 : if (pos2 == string::npos) {
629 0 : return false;
630 : }
631 : string metadata = link_info.substr((pos1 + sep_size),
632 0 : pos2 - (pos1 + sep_size));
633 :
634 : // last_link_name
635 0 : *last_link_name = link_info.substr(pos2 + sep_size);
636 :
637 : // Fill up the fields of IFMapLinkTableShowReq appropriately.
638 0 : req->set_search_string(search_string);
639 0 : req->set_metadata(metadata);
640 0 : return true;
641 0 : }
642 :
643 0 : bool ShowIFMapLinkTable::BufferStageCommon(const IFMapLinkTableShowReq *request,
644 : RequestPipeline::InstData *data,
645 : const string &last_link_name) {
646 0 : bool buffer_full = false;
647 : IFMapSandeshContext *sctx =
648 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
649 :
650 : IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
651 0 : sctx->ifmap_server()->database()->FindTable("__ifmap_metadata__.0"));
652 0 : if (table) {
653 0 : regex search_expr(request->get_search_string());
654 0 : regex metadata_expr(request->get_metadata());
655 0 : ShowData *show_data = static_cast<ShowData *>(data);
656 0 : uint32_t page_limit = GetPageLimit(sctx);
657 0 : show_data->send_buffer.reserve(page_limit);
658 0 : show_data->table_size = table->Size();
659 :
660 0 : DBEntryBase *src = NULL;
661 0 : DBTablePartBase *partition = table->GetTablePartition(0);
662 0 : if (last_link_name.length()) {
663 0 : src = table->FindNextLink(last_link_name);
664 : } else {
665 0 : src = partition->GetFirst();
666 : }
667 0 : for (; src != NULL; src = partition->GetNext(src)) {
668 0 : if (IncludeLink(src, request->get_search_string(), search_expr,
669 : request->get_metadata(), metadata_expr)) {
670 0 : IFMapLinkShowInfo dest;
671 0 : CopyNode(&dest, src, sctx->ifmap_server());
672 0 : show_data->send_buffer.push_back(dest);
673 : // If we have picked up enough links for this round...
674 0 : uint32_t page_limit = GetPageLimit(sctx);
675 0 : if (show_data->send_buffer.size() == page_limit) {
676 0 : IFMapLink *src_link = static_cast<IFMapLink *>(src);
677 0 : show_data->last_link_name = src_link->link_name();
678 0 : buffer_full = true;
679 0 : break;
680 : }
681 0 : }
682 : }
683 0 : } else {
684 0 : IFMAP_WARN(IFMapTblNotFound, "Cant show/find ", "link table");
685 : }
686 :
687 0 : return buffer_full;
688 : }
689 :
690 0 : bool ShowIFMapLinkTable::BufferStage(const Sandesh *sr,
691 : const RequestPipeline::PipeSpec ps,
692 : int stage, int instNum,
693 : RequestPipeline::InstData *data) {
694 : const IFMapLinkTableShowReq *request =
695 0 : static_cast<const IFMapLinkTableShowReq *>(ps.snhRequest_.get());
696 0 : string last_link_name;
697 0 : BufferStageCommon(request, data, last_link_name);
698 0 : return true;
699 0 : }
700 :
701 0 : bool ShowIFMapLinkTable::BufferStageIterate(const Sandesh *sr,
702 : const RequestPipeline::PipeSpec ps,
703 : int stage, int instNum,
704 : RequestPipeline::InstData *data) {
705 : const IFMapLinkTableShowReqIterate *request_iterate =
706 0 : static_cast<const IFMapLinkTableShowReqIterate *>(ps.snhRequest_.get());
707 :
708 0 : IFMapLinkTableShowReq *request = new IFMapLinkTableShowReq;
709 0 : string last_link_name;
710 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
711 : &last_link_name);
712 0 : if (success) {
713 0 : BufferStageCommon(request, data, last_link_name);
714 : }
715 0 : request->Release();
716 0 : return true;
717 0 : }
718 :
719 0 : void ShowIFMapLinkTable::SendStageCommon(const IFMapLinkTableShowReq *request,
720 : const RequestPipeline::PipeSpec ps,
721 : IFMapLinkTableShowResp *response) {
722 0 : const RequestPipeline::StageData *prev_stage_data = ps.GetStageData(0);
723 : const ShowIFMapLinkTable::ShowData &show_data =
724 : static_cast<const ShowIFMapLinkTable::ShowData&>
725 0 : (prev_stage_data->at(0));
726 :
727 0 : vector<IFMapLinkShowInfo> dest_buffer;
728 0 : dest_buffer = show_data.send_buffer;
729 :
730 : // If we have filled the buffer, set next_batch with all the values we will
731 : // need in the next round.
732 0 : string next_batch;
733 : IFMapSandeshContext *sctx =
734 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
735 0 : uint32_t page_limit = GetPageLimit(sctx);
736 0 : if (dest_buffer.size() == page_limit) {
737 0 : next_batch = request->get_search_string() + kShowIterSeparator +
738 0 : request->get_metadata() + kShowIterSeparator +
739 0 : show_data.last_link_name;
740 : }
741 :
742 0 : response->set_table_size(show_data.table_size);
743 0 : response->set_ifmap_db(dest_buffer);
744 0 : response->set_next_batch(next_batch);
745 0 : }
746 :
747 0 : bool ShowIFMapLinkTable::SendStage(const Sandesh *sr,
748 : const RequestPipeline::PipeSpec ps,
749 : int stage, int instNum,
750 : RequestPipeline::InstData *data) {
751 : const IFMapLinkTableShowReq *request =
752 0 : static_cast<const IFMapLinkTableShowReq *>(ps.snhRequest_.get());
753 0 : IFMapLinkTableShowResp *response = new IFMapLinkTableShowResp;
754 0 : SendStageCommon(request, ps, response);
755 :
756 0 : response->set_context(request->context());
757 0 : response->set_more(false);
758 0 : response->Response();
759 0 : return true;
760 : }
761 :
762 0 : bool ShowIFMapLinkTable::SendStageIterate(const Sandesh *sr,
763 : const RequestPipeline::PipeSpec ps,
764 : int stage, int instNum,
765 : RequestPipeline::InstData *data) {
766 : const IFMapLinkTableShowReqIterate *request_iterate =
767 0 : static_cast<const IFMapLinkTableShowReqIterate *>(ps.snhRequest_.get());
768 :
769 0 : IFMapLinkTableShowResp *response = new IFMapLinkTableShowResp;
770 0 : IFMapLinkTableShowReq *request = new IFMapLinkTableShowReq;
771 0 : string last_link_name;
772 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
773 : &last_link_name);
774 0 : if (success) {
775 0 : SendStageCommon(request, ps, response);
776 : }
777 :
778 0 : response->set_context(request->context());
779 0 : response->set_more(false);
780 0 : response->Response();
781 :
782 0 : request->Release();
783 0 : return true;
784 0 : }
785 :
786 0 : void IFMapLinkTableShowReq::HandleRequest() const {
787 :
788 0 : RequestPipeline::StageSpec s0, s1;
789 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
790 :
791 : // 2 stages - first: gather/read, second: send
792 :
793 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
794 0 : s0.allocFn_ = ShowIFMapLinkTable::AllocBuffer;
795 0 : s0.cbFn_ = ShowIFMapLinkTable::BufferStage;
796 0 : s0.instances_.push_back(0);
797 :
798 : // control-node ifmap show command task
799 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
800 0 : s1.cbFn_ = ShowIFMapLinkTable::SendStage;
801 0 : s1.instances_.push_back(0);
802 :
803 0 : RequestPipeline::PipeSpec ps(this);
804 0 : ps.stages_ = list_of(s0)(s1)
805 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
806 0 : RequestPipeline rp(ps);
807 0 : }
808 :
809 0 : void IFMapLinkTableShowReqIterate::HandleRequest() const {
810 :
811 0 : RequestPipeline::StageSpec s0, s1;
812 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
813 :
814 : // 2 stages - first: gather/read, second: send
815 :
816 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
817 0 : s0.allocFn_ = ShowIFMapLinkTable::AllocBuffer;
818 0 : s0.cbFn_ = ShowIFMapLinkTable::BufferStageIterate;
819 0 : s0.instances_.push_back(0);
820 :
821 : // control-node ifmap show command task
822 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
823 0 : s1.cbFn_ = ShowIFMapLinkTable::SendStageIterate;
824 0 : s1.instances_.push_back(0);
825 :
826 0 : RequestPipeline::PipeSpec ps(this);
827 0 : ps.stages_ = list_of(s0)(s1)
828 : .convert_to_container\
829 0 : <vector<RequestPipeline::StageSpec> >();
830 0 : RequestPipeline rp(ps);
831 0 : }
832 :
833 0 : static bool IFMapNodeShowReqHandleRequest(const Sandesh *sr,
834 : const RequestPipeline::PipeSpec ps,
835 : int stage, int instNum,
836 : RequestPipeline::InstData *data) {
837 : const IFMapNodeShowReq *request =
838 0 : static_cast<const IFMapNodeShowReq *>(ps.snhRequest_.get());
839 : IFMapSandeshContext *sctx =
840 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
841 :
842 0 : IFMapNodeShowResp *response = new IFMapNodeShowResp();
843 :
844 0 : string fq_node_name = request->get_fq_node_name();
845 : // EG: "virtual-network:my:virtual:network" i.e. type:name
846 0 : size_t type_length = fq_node_name.find(":");
847 0 : if (type_length != string::npos) {
848 0 : string node_type = fq_node_name.substr(0, type_length);
849 : // +1 to go to the next character after ':'
850 0 : string node_name = fq_node_name.substr(type_length + 1);
851 :
852 0 : DB *db = sctx->ifmap_server()->database();
853 0 : IFMapTable *table = IFMapTable::FindTable(db, node_type);
854 0 : if (table) {
855 0 : IFMapNode *src = table->FindNode(node_name);
856 0 : if (src) {
857 0 : IFMapNodeShowInfo dest;
858 0 : IFMapNodeCopier copyNode(&dest, src, sctx->ifmap_server());
859 0 : response->set_node_info(dest);
860 0 : } else {
861 0 : IFMAP_WARN(IFMapIdentifierNotFound, "Cant find identifier",
862 : node_name);
863 : }
864 : } else {
865 0 : IFMAP_WARN(IFMapTblNotFound, "Cant show/find table with node-type",
866 : node_type);
867 : }
868 0 : }
869 :
870 0 : response->set_context(request->context());
871 0 : response->set_more(false);
872 0 : response->Response();
873 :
874 : // Return 'true' so that we are not called again
875 0 : return true;
876 0 : }
877 :
878 0 : void IFMapNodeShowReq::HandleRequest() const {
879 :
880 0 : RequestPipeline::StageSpec s0;
881 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
882 :
883 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
884 0 : s0.cbFn_ = IFMapNodeShowReqHandleRequest;
885 0 : s0.instances_.push_back(0);
886 :
887 0 : RequestPipeline::PipeSpec ps(this);
888 0 : ps.stages_ = list_of(s0)
889 : .convert_to_container\
890 0 : <vector<RequestPipeline::StageSpec> >();
891 0 : RequestPipeline rp(ps);
892 0 : }
893 :
894 : class ShowIFMapPerClientNodes {
895 : public:
896 : static const uint32_t kMaxElementsPerRound = 50;
897 :
898 0 : static int GetPageLimit(IFMapSandeshContext *sctx) {
899 0 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
900 : }
901 :
902 : struct ShowData : public RequestPipeline::InstData {
903 : vector<IFMapPerClientNodesShowInfo> send_buffer;
904 : string next_table_name;
905 : string last_node_name;
906 : };
907 :
908 0 : static RequestPipeline::InstData* AllocBuffer(int stage) {
909 0 : return static_cast<RequestPipeline::InstData *>(new ShowData);
910 : }
911 :
912 : static bool ConvertReqIterateToReq(
913 : const IFMapPerClientNodesShowReqIterate *req_iterate,
914 : IFMapPerClientNodesShowReq *req, string *next_table_name,
915 : string *last_node_name);
916 : static bool CopyNode(IFMapPerClientNodesShowInfo *dest, IFMapNode *src,
917 : IFMapServer *server, int client_index);
918 : static bool TableToBuffer(const IFMapPerClientNodesShowReq *request,
919 : IFMapTable *table, IFMapServer *server,
920 : const string &last_node_name, int client_index,
921 : ShowData *show_data);
922 : static bool BufferStageCommon(const IFMapPerClientNodesShowReq *request,
923 : RequestPipeline::InstData *data,
924 : const string &next_table_name,
925 : const string &last_node_name);
926 : static bool BufferStage(const Sandesh *sr,
927 : const RequestPipeline::PipeSpec ps, int stage,
928 : int instNum, RequestPipeline::InstData *data);
929 : static bool BufferStageIterate(const Sandesh *sr,
930 : const RequestPipeline::PipeSpec ps,
931 : int stage, int instNum,
932 : RequestPipeline::InstData *data);
933 : static void SendStageCommon(const IFMapPerClientNodesShowReq *request,
934 : const RequestPipeline::PipeSpec ps,
935 : IFMapPerClientNodesShowResp *response);
936 : static bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
937 : int stage, int instNum,
938 : RequestPipeline::InstData *data);
939 : static bool SendStageIterate(const Sandesh *sr,
940 : const RequestPipeline::PipeSpec ps, int stage,
941 : int instNum, RequestPipeline::InstData *data);
942 : };
943 :
944 : // Format of node_info string:
945 : // client_index_or_name||search_string||next_table_name||last_node_name
946 : // client_index_or_name: original input
947 : // search_string: original input; can be empty
948 : // next_table_name: next table to lookup in
949 : // last_node_name: name of last node that was printed in the previous round
950 0 : bool ShowIFMapPerClientNodes::ConvertReqIterateToReq(
951 : const IFMapPerClientNodesShowReqIterate *req_iterate,
952 : IFMapPerClientNodesShowReq *req, string *next_table_name,
953 : string *last_node_name) {
954 : // First, set the context from the original request since we might return
955 : // due to parsing errors.
956 0 : req->set_context(req_iterate->context());
957 :
958 0 : string node_info = req_iterate->get_node_info();
959 0 : size_t sep_size = kShowIterSeparator.size();
960 :
961 : // client_index_or_name
962 0 : size_t pos1 = node_info.find(kShowIterSeparator);
963 0 : if (pos1 == string::npos) {
964 0 : return false;
965 : }
966 0 : string client_index_or_name = node_info.substr(0, pos1);
967 :
968 : // search_string
969 0 : size_t pos2 = node_info.find(kShowIterSeparator, (pos1 + sep_size));
970 0 : if (pos2 == string::npos) {
971 0 : return false;
972 : }
973 : string search_string = node_info.substr((pos1 + sep_size),
974 0 : pos2 - (pos1 + sep_size));
975 :
976 : // next_table_name
977 0 : size_t pos3 = node_info.find(kShowIterSeparator, (pos2 + sep_size));
978 0 : if (pos3 == string::npos) {
979 0 : return false;
980 : }
981 0 : *next_table_name = node_info.substr((pos2 + sep_size),
982 0 : pos3 - (pos2 + sep_size));
983 :
984 : // last_node_name
985 0 : *last_node_name = node_info.substr(pos3 + sep_size);
986 :
987 : // Fill up the fields of IFMapTableShowReq appropriately.
988 0 : req->set_client_index_or_name(client_index_or_name);
989 0 : req->set_search_string(search_string);
990 0 : return true;
991 0 : }
992 :
993 0 : bool ShowIFMapPerClientNodes::CopyNode(IFMapPerClientNodesShowInfo *dest,
994 : IFMapNode *src, IFMapServer *server,
995 : int client_index) {
996 0 : IFMapNodeState *state = server->exporter()->NodeStateLookup(src);
997 :
998 0 : if (state && state->interest().test(client_index)) {
999 0 : dest->node_name = src->ToString();
1000 0 : if (state->advertised().test(client_index)) {
1001 0 : dest->sent = "Yes";
1002 : } else {
1003 0 : dest->sent = "No";
1004 : }
1005 0 : if (server->exporter()->ClientHasConfigTracker(
1006 : IFMapExporter::INTEREST, client_index)) {
1007 0 : if (server->exporter()->ClientConfigTrackerHasState(
1008 : IFMapExporter::INTEREST, client_index, state)) {
1009 0 : dest->interest_tracked = "Yes";
1010 : } else {
1011 0 : dest->interest_tracked = "No";
1012 : }
1013 : } else {
1014 0 : dest->interest_tracked = "No tracker";
1015 : }
1016 0 : if (server->exporter()->ClientHasConfigTracker(
1017 : IFMapExporter::ADVERTISED, client_index)) {
1018 0 : if (server->exporter()->ClientConfigTrackerHasState(
1019 : IFMapExporter::ADVERTISED, client_index, state)) {
1020 0 : dest->advertised_tracked = "Yes";
1021 : } else {
1022 0 : dest->advertised_tracked = "No";
1023 : }
1024 : } else {
1025 0 : dest->advertised_tracked = "No tracker";
1026 : }
1027 0 : return true;
1028 : } else {
1029 0 : return false;
1030 : }
1031 : }
1032 :
1033 0 : bool ShowIFMapPerClientNodes::TableToBuffer(
1034 : const IFMapPerClientNodesShowReq *request, IFMapTable *table,
1035 : IFMapServer *ifmap_server, const string &last_node_name,
1036 : int client_index, ShowData *show_data) {
1037 :
1038 0 : DBEntryBase *src = NULL;
1039 0 : if (last_node_name.length()) {
1040 : // If the last_node_name is set, it was the last node printed in the
1041 : // previous round. Search for the node 'after' last_node_name and start
1042 : // this round with it. If there is no next node, we are done with this
1043 : // table.
1044 0 : IFMapNode *last_node = table->FindNextNode(last_node_name);
1045 0 : if (last_node) {
1046 0 : src = last_node;
1047 : } else {
1048 0 : return false;
1049 : }
1050 : }
1051 :
1052 0 : bool buffer_full = false;
1053 0 : string search_string = request->get_search_string();
1054 0 : DBTablePartBase *partition = table->GetTablePartition(0);
1055 0 : if (!src) {
1056 0 : src = partition->GetFirst();
1057 : }
1058 0 : for (; src != NULL; src = partition->GetNext(src)) {
1059 0 : IFMapNode *src_node = static_cast<IFMapNode *>(src);
1060 0 : if (!search_string.empty() &&
1061 0 : (src_node->ToString().find(search_string) == string::npos)) {
1062 0 : continue;
1063 : }
1064 0 : IFMapPerClientNodesShowInfo dest;
1065 0 : bool send = CopyNode(&dest, src_node, ifmap_server, client_index);
1066 0 : if (send) {
1067 0 : show_data->send_buffer.push_back(dest);
1068 :
1069 : IFMapSandeshContext *sctx =
1070 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1071 0 : uint32_t page_limit = sctx->page_limit() ?
1072 0 : sctx->page_limit() : kMaxElementsPerRound;
1073 : // If we have picked up enough nodes for this round...
1074 0 : if (show_data->send_buffer.size() == page_limit) {
1075 : // Save the values needed for the next round. When we come
1076 : // back, we will use the 'names' to lookup the elements since
1077 : // the 'names' are the keys in the respective tables.
1078 0 : show_data->next_table_name = table->name();
1079 0 : show_data->last_node_name = src_node->name();
1080 0 : buffer_full = true;
1081 0 : break;
1082 : }
1083 : }
1084 0 : }
1085 :
1086 0 : return buffer_full;
1087 0 : }
1088 :
1089 0 : bool ShowIFMapPerClientNodes::BufferStageCommon(
1090 : const IFMapPerClientNodesShowReq *request,
1091 : RequestPipeline::InstData *data, const string &next_table_name,
1092 : const string &last_node_name) {
1093 : IFMapSandeshContext *sctx =
1094 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1095 0 : IFMapServer *ifmap_server = sctx->ifmap_server();
1096 :
1097 : // The user gives us either a name or an index. If the input is not a
1098 : // number, find the client's index using its name. If we cant find it,
1099 : // we cant process this request. If we have the index, continue processing.
1100 0 : string client_index_or_name = request->get_client_index_or_name();
1101 : int client_index;
1102 0 : if (!stringToInteger(client_index_or_name, client_index)) {
1103 0 : if (!ifmap_server->ClientNameToIndex(client_index_or_name,
1104 : &client_index)) {
1105 0 : return true;
1106 : }
1107 : }
1108 :
1109 0 : string last_name = last_node_name;
1110 0 : string search_string = request->get_search_string();
1111 0 : DB *db = ifmap_server->database();
1112 :
1113 0 : DB::iterator iter;
1114 0 : if (next_table_name.empty()) {
1115 0 : iter = db->lower_bound("__ifmap__.");
1116 : } else {
1117 0 : iter = db->FindTableIter(next_table_name);
1118 : }
1119 :
1120 0 : uint32_t page_limit = GetPageLimit(sctx);
1121 0 : ShowData *show_data = static_cast<ShowData *>(data);
1122 0 : show_data->send_buffer.reserve(page_limit);
1123 0 : for (; iter != db->end(); ++iter) {
1124 0 : if (iter->first.find("__ifmap__.") != 0) {
1125 0 : break;
1126 : }
1127 0 : IFMapTable *table = static_cast<IFMapTable *>(iter->second);
1128 0 : bool buffer_full = TableToBuffer(request, table, ifmap_server,
1129 : last_name, client_index, show_data);
1130 0 : if (buffer_full) {
1131 0 : break;
1132 : }
1133 : // last_node_name is only relevant for the first iteration.
1134 0 : last_name.clear();
1135 : }
1136 :
1137 0 : return true;
1138 0 : }
1139 :
1140 0 : bool ShowIFMapPerClientNodes::BufferStage(const Sandesh *sr,
1141 : const RequestPipeline::PipeSpec ps,
1142 : int stage, int instNum,
1143 : RequestPipeline::InstData *data) {
1144 : const IFMapPerClientNodesShowReq *request =
1145 0 : static_cast<const IFMapPerClientNodesShowReq *>(ps.snhRequest_.get());
1146 :
1147 : // If neither the client index nor the name has been provided, we are done.
1148 0 : if (request->get_client_index_or_name().empty()) {
1149 0 : return true;
1150 : }
1151 :
1152 0 : string next_table_name;
1153 0 : string last_node_name;
1154 0 : return BufferStageCommon(request, data, next_table_name, last_node_name);
1155 0 : }
1156 :
1157 0 : bool ShowIFMapPerClientNodes::BufferStageIterate(
1158 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1159 : int instNum, RequestPipeline::InstData *data) {
1160 : const IFMapPerClientNodesShowReqIterate *request_iterate =
1161 : static_cast<const IFMapPerClientNodesShowReqIterate *>
1162 0 : (ps.snhRequest_.get());
1163 :
1164 0 : string next_table_name;
1165 0 : string last_node_name;
1166 0 : IFMapPerClientNodesShowReq *request = new IFMapPerClientNodesShowReq;
1167 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
1168 : &next_table_name, &last_node_name);
1169 0 : if (success) {
1170 0 : BufferStageCommon(request, data, next_table_name, last_node_name);
1171 : }
1172 0 : request->Release();
1173 0 : return true;
1174 0 : }
1175 :
1176 0 : void ShowIFMapPerClientNodes::SendStageCommon(
1177 : const IFMapPerClientNodesShowReq *request,
1178 : const RequestPipeline::PipeSpec ps,
1179 : IFMapPerClientNodesShowResp *response) {
1180 0 : const RequestPipeline::StageData *prev_stage_data = ps.GetStageData(0);
1181 : const ShowIFMapPerClientNodes::ShowData &show_data =
1182 : static_cast<const ShowIFMapPerClientNodes::ShowData&>
1183 0 : (prev_stage_data->at(0));
1184 :
1185 0 : vector<IFMapPerClientNodesShowInfo> dest_buffer;
1186 0 : dest_buffer = show_data.send_buffer;
1187 :
1188 : // If we have filled the buffer, set next_batch with all the values we will
1189 : // need in the next round.
1190 0 : string next_batch;
1191 : IFMapSandeshContext *sctx =
1192 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1193 0 : uint32_t page_limit = GetPageLimit(sctx);
1194 0 : if (dest_buffer.size() == page_limit) {
1195 0 : next_batch = request->get_client_index_or_name() + kShowIterSeparator +
1196 0 : request->get_search_string() + kShowIterSeparator +
1197 0 : show_data.next_table_name + kShowIterSeparator +
1198 0 : show_data.last_node_name;
1199 : }
1200 :
1201 0 : response->set_node_db(dest_buffer);
1202 0 : response->set_next_batch(next_batch);
1203 0 : }
1204 :
1205 0 : bool ShowIFMapPerClientNodes::SendStage(const Sandesh *sr,
1206 : const RequestPipeline::PipeSpec ps,
1207 : int stage, int instNum,
1208 : RequestPipeline::InstData *data) {
1209 : const IFMapPerClientNodesShowReq *request =
1210 0 : static_cast<const IFMapPerClientNodesShowReq *>(ps.snhRequest_.get());
1211 0 : IFMapPerClientNodesShowResp *response = new IFMapPerClientNodesShowResp;
1212 0 : SendStageCommon(request, ps, response);
1213 :
1214 0 : response->set_context(request->context());
1215 0 : response->set_more(false);
1216 0 : response->Response();
1217 0 : return true;
1218 : }
1219 :
1220 0 : bool ShowIFMapPerClientNodes::SendStageIterate(
1221 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1222 : int instNum, RequestPipeline::InstData *data) {
1223 : const IFMapPerClientNodesShowReqIterate *request_iterate =
1224 : static_cast<const IFMapPerClientNodesShowReqIterate *>
1225 0 : (ps.snhRequest_.get());
1226 :
1227 0 : string next_table_name;
1228 0 : string last_node_name;
1229 :
1230 0 : IFMapPerClientNodesShowResp *response = new IFMapPerClientNodesShowResp;
1231 0 : IFMapPerClientNodesShowReq *request = new IFMapPerClientNodesShowReq;
1232 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
1233 : &next_table_name, &last_node_name);
1234 0 : if (success) {
1235 0 : SendStageCommon(request, ps, response);
1236 : }
1237 :
1238 0 : response->set_context(request->context());
1239 0 : response->set_more(false);
1240 0 : response->Response();
1241 :
1242 0 : request->Release();
1243 0 : return true;
1244 0 : }
1245 :
1246 0 : void IFMapPerClientNodesShowReq::HandleRequest() const {
1247 :
1248 0 : RequestPipeline::StageSpec s0, s1;
1249 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1250 :
1251 : // 2 stages - first: gather/read, second: send
1252 :
1253 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1254 0 : s0.allocFn_ = ShowIFMapPerClientNodes::AllocBuffer;
1255 0 : s0.cbFn_ = ShowIFMapPerClientNodes::BufferStage;
1256 0 : s0.instances_.push_back(0);
1257 :
1258 : // control-node ifmap show command task
1259 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
1260 0 : s1.cbFn_ = ShowIFMapPerClientNodes::SendStage;
1261 0 : s1.instances_.push_back(0);
1262 :
1263 0 : RequestPipeline::PipeSpec ps(this);
1264 0 : ps.stages_ = list_of(s0)(s1)
1265 : .convert_to_container\
1266 0 : <vector<RequestPipeline::StageSpec> >();
1267 0 : RequestPipeline rp(ps);
1268 0 : }
1269 :
1270 0 : void IFMapPerClientNodesShowReqIterate::HandleRequest() const {
1271 :
1272 0 : RequestPipeline::StageSpec s0, s1;
1273 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1274 :
1275 : // 2 stages - first: gather/read, second: send
1276 :
1277 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1278 0 : s0.allocFn_ = ShowIFMapPerClientNodes::AllocBuffer;
1279 0 : s0.cbFn_ = ShowIFMapPerClientNodes::BufferStageIterate;
1280 0 : s0.instances_.push_back(0);
1281 :
1282 : // control-node ifmap show command task
1283 0 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
1284 0 : s1.cbFn_ = ShowIFMapPerClientNodes::SendStageIterate;
1285 0 : s1.instances_.push_back(0);
1286 :
1287 0 : RequestPipeline::PipeSpec ps(this);
1288 0 : ps.stages_ = list_of(s0)(s1)
1289 : .convert_to_container\
1290 0 : <vector<RequestPipeline::StageSpec> >();
1291 0 : RequestPipeline rp(ps);
1292 0 : }
1293 :
1294 : class ShowIFMapPerClientLinkTable {
1295 : public:
1296 : static const uint32_t kMaxElementsPerRound = 50;
1297 :
1298 0 : static int GetPageLimit(IFMapSandeshContext *sctx) {
1299 0 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
1300 : }
1301 :
1302 : static bool HandleRequest(const Sandesh *sr,
1303 : const RequestPipeline::PipeSpec ps,
1304 : int stage, int instNum,
1305 : RequestPipeline::InstData *data);
1306 : static bool HandleRequestIterate(const Sandesh *sr,
1307 : const RequestPipeline::PipeSpec ps,
1308 : int stage, int instNum,
1309 : RequestPipeline::InstData *data);
1310 : static bool ConvertReqIterateToReq(
1311 : const IFMapPerClientLinksShowReqIterate *req_iterate,
1312 : IFMapPerClientLinksShowReq *req, string *last_node_name);
1313 : static bool SkipLink(IFMapLink *src, const string &search_string);
1314 : static bool CopyNode(IFMapPerClientLinksShowInfo *dest, IFMapLink *src,
1315 : IFMapServer *server, int client_index);
1316 : static void BufferTable(const IFMapPerClientLinksShowReq *request,
1317 : const string &last_link_name,
1318 : IFMapPerClientLinksShowResp *response);
1319 : };
1320 :
1321 0 : bool ShowIFMapPerClientLinkTable::CopyNode(IFMapPerClientLinksShowInfo *dest,
1322 : IFMapLink *src, IFMapServer *server,
1323 : int client_index) {
1324 0 : IFMapLinkState *state = server->exporter()->LinkStateLookup(src);
1325 :
1326 0 : if (state && state->interest().test(client_index)) {
1327 0 : dest->metadata = src->metadata();
1328 0 : dest->left = src->left()->ToString();
1329 0 : dest->right = src->right()->ToString();
1330 0 : if (state->advertised().test(client_index)) {
1331 0 : dest->sent = "Yes";
1332 : } else {
1333 0 : dest->sent = "No";
1334 : }
1335 0 : if (server->exporter()->ClientHasConfigTracker(
1336 : IFMapExporter::INTEREST, client_index)) {
1337 0 : if (server->exporter()->ClientConfigTrackerHasState(
1338 : IFMapExporter::INTEREST, client_index, state)) {
1339 0 : dest->interest_tracked = "Yes";
1340 : } else {
1341 0 : dest->interest_tracked = "No";
1342 : }
1343 : } else {
1344 0 : dest->interest_tracked = "No tracker";
1345 : }
1346 0 : if (server->exporter()->ClientHasConfigTracker(
1347 : IFMapExporter::ADVERTISED, client_index)) {
1348 0 : if (server->exporter()->ClientConfigTrackerHasState(
1349 : IFMapExporter::ADVERTISED, client_index, state)) {
1350 0 : dest->advertised_tracked = "Yes";
1351 : } else {
1352 0 : dest->advertised_tracked = "No";
1353 : }
1354 : } else {
1355 0 : dest->advertised_tracked = "No tracker";
1356 : }
1357 0 : return true;
1358 : } else {
1359 0 : return false;
1360 : }
1361 : }
1362 :
1363 0 : bool ShowIFMapPerClientLinkTable::SkipLink(IFMapLink *src_link,
1364 : const string &search_string) {
1365 0 : if (search_string.empty()) {
1366 0 : return false;
1367 : }
1368 0 : IFMapNode *left = src_link->left();
1369 0 : IFMapNode *right = src_link->right();
1370 : // If we do not find the search string in the metadata or the names of
1371 : // either of the 2 ends, skip the src_link.
1372 0 : if ((src_link->metadata().find(search_string) == string::npos) &&
1373 0 : (!left || (left->ToString().find(search_string) == string::npos)) &&
1374 0 : (!right || (right->ToString().find(search_string) == string::npos))) {
1375 0 : return true;
1376 : }
1377 0 : return false;
1378 : }
1379 :
1380 : // Format of node_info string:
1381 : // client_index_or_name||search_string||last_node_name
1382 : // client_index_or_name: original input
1383 : // search_string: original input; can be empty
1384 : // last_node_name: name of last node that was printed in the previous round
1385 0 : bool ShowIFMapPerClientLinkTable::ConvertReqIterateToReq(
1386 : const IFMapPerClientLinksShowReqIterate *req_iterate,
1387 : IFMapPerClientLinksShowReq *req, string *last_node_name) {
1388 : // First, set the context from the original request since we might return
1389 : // due to parsing errors.
1390 0 : req->set_context(req_iterate->context());
1391 :
1392 0 : string node_info = req_iterate->get_link_info();
1393 0 : size_t sep_size = kShowIterSeparator.size();
1394 :
1395 : // client_index_or_name
1396 0 : size_t pos1 = node_info.find(kShowIterSeparator);
1397 0 : if (pos1 == string::npos) {
1398 0 : return false;
1399 : }
1400 0 : string client_index_or_name = node_info.substr(0, pos1);
1401 :
1402 : // search_string
1403 0 : size_t pos2 = node_info.find(kShowIterSeparator, (pos1 + sep_size));
1404 0 : if (pos2 == string::npos) {
1405 0 : return false;
1406 : }
1407 : string search_string = node_info.substr((pos1 + sep_size),
1408 0 : pos2 - (pos1 + sep_size));
1409 :
1410 : // last_node_name
1411 0 : *last_node_name = node_info.substr(pos2 + sep_size);
1412 :
1413 : // Fill up the fields of IFMapTableShowReq appropriately.
1414 0 : req->set_client_index_or_name(client_index_or_name);
1415 0 : req->set_search_string(search_string);
1416 0 : return true;
1417 0 : }
1418 :
1419 0 : void ShowIFMapPerClientLinkTable::BufferTable(
1420 : const IFMapPerClientLinksShowReq *request, const string &last_link_name,
1421 : IFMapPerClientLinksShowResp *response) {
1422 : IFMapSandeshContext *sctx =
1423 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1424 :
1425 0 : string client_index_or_name = request->get_client_index_or_name();
1426 0 : if (client_index_or_name.empty()) {
1427 0 : return;
1428 : }
1429 : // The user gives us either a name or an index. If the input is not a
1430 : // number, find the client's index using its name. If we cant find it,
1431 : // we cant process this request. If we have the index, continue processing.
1432 : int client_index;
1433 0 : if (!stringToInteger(client_index_or_name, client_index)) {
1434 0 : if (!sctx->ifmap_server()->ClientNameToIndex(client_index_or_name,
1435 : &client_index)) {
1436 0 : return;
1437 : }
1438 : }
1439 :
1440 : IFMapLinkTable *table = static_cast<IFMapLinkTable *>(
1441 0 : sctx->ifmap_server()->database()->FindTable("__ifmap_metadata__.0"));
1442 :
1443 0 : uint32_t page_limit = GetPageLimit(sctx);
1444 0 : if (table) {
1445 0 : vector<IFMapPerClientLinksShowInfo> dest_buffer;
1446 0 : dest_buffer.reserve(page_limit);
1447 :
1448 0 : DBEntryBase *src = NULL;
1449 0 : DBTablePartBase *partition = table->GetTablePartition(0);
1450 0 : if (last_link_name.length()) {
1451 0 : src = table->FindNextLink(last_link_name);
1452 : } else {
1453 0 : src = partition->GetFirst();
1454 : }
1455 0 : for (; src != NULL; src = partition->GetNext(src)) {
1456 0 : IFMapLink *src_link = static_cast<IFMapLink *>(src);
1457 0 : if (SkipLink(src_link, request->get_search_string())) {
1458 0 : continue;
1459 : }
1460 0 : IFMapPerClientLinksShowInfo dest;
1461 0 : bool send = CopyNode(&dest, src_link, sctx->ifmap_server(),
1462 : client_index);
1463 0 : if (send) {
1464 0 : dest_buffer.push_back(dest);
1465 0 : if (dest_buffer.size() == page_limit) {
1466 0 : string next_batch = request->get_client_index_or_name() +
1467 0 : kShowIterSeparator + request->get_search_string() +
1468 0 : kShowIterSeparator + src_link->link_name();
1469 0 : response->set_next_batch(next_batch);
1470 0 : break;
1471 0 : }
1472 : }
1473 0 : }
1474 0 : response->set_link_db(dest_buffer);
1475 0 : } else {
1476 0 : IFMAP_WARN(IFMapTblNotFound, "Cant show/find ", "link table");
1477 : }
1478 0 : }
1479 :
1480 0 : bool ShowIFMapPerClientLinkTable::HandleRequest(
1481 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1482 : int instNum, RequestPipeline::InstData *data) {
1483 : const IFMapPerClientLinksShowReq *request =
1484 0 : static_cast<const IFMapPerClientLinksShowReq *>(ps.snhRequest_.get());
1485 :
1486 0 : string last_link_name;
1487 0 : IFMapPerClientLinksShowResp *response = new IFMapPerClientLinksShowResp();
1488 0 : BufferTable(request, last_link_name, response);
1489 :
1490 0 : response->set_context(request->context());
1491 0 : response->set_more(false);
1492 0 : response->Response();
1493 :
1494 : // Return 'true' so that we are not called again
1495 0 : return true;
1496 0 : }
1497 :
1498 0 : bool ShowIFMapPerClientLinkTable::HandleRequestIterate(
1499 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1500 : int instNum, RequestPipeline::InstData *data) {
1501 : const IFMapPerClientLinksShowReqIterate *request_iterate =
1502 : static_cast<const IFMapPerClientLinksShowReqIterate *>
1503 0 : (ps.snhRequest_.get());
1504 :
1505 0 : string last_link_name;
1506 0 : IFMapPerClientLinksShowReq *request = new IFMapPerClientLinksShowReq();
1507 0 : IFMapPerClientLinksShowResp *response = new IFMapPerClientLinksShowResp();
1508 0 : bool success = ConvertReqIterateToReq(request_iterate, request,
1509 : &last_link_name);
1510 0 : if (success) {
1511 0 : BufferTable(request, last_link_name, response);
1512 : }
1513 :
1514 0 : response->set_context(request->context());
1515 0 : response->set_more(false);
1516 0 : response->Response();
1517 :
1518 0 : request->Release();
1519 : // Return 'true' so that we are not called again
1520 0 : return true;
1521 0 : }
1522 :
1523 0 : void IFMapPerClientLinksShowReq::HandleRequest() const {
1524 0 : RequestPipeline::StageSpec s0;
1525 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1526 :
1527 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1528 0 : s0.cbFn_ = ShowIFMapPerClientLinkTable::HandleRequest;
1529 0 : s0.instances_.push_back(0);
1530 :
1531 0 : RequestPipeline::PipeSpec ps(this);
1532 0 : ps.stages_ = list_of(s0)
1533 : .convert_to_container\
1534 0 : <vector<RequestPipeline::StageSpec> >();
1535 0 : RequestPipeline rp(ps);
1536 0 : }
1537 :
1538 0 : void IFMapPerClientLinksShowReqIterate::HandleRequest() const {
1539 0 : RequestPipeline::StageSpec s0;
1540 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1541 :
1542 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1543 0 : s0.cbFn_ = ShowIFMapPerClientLinkTable::HandleRequestIterate;
1544 0 : s0.instances_.push_back(0);
1545 :
1546 0 : RequestPipeline::PipeSpec ps(this);
1547 0 : ps.stages_ = list_of(s0)
1548 : .convert_to_container\
1549 0 : <vector<RequestPipeline::StageSpec> >();
1550 0 : RequestPipeline rp(ps);
1551 0 : }
1552 :
1553 : class ShowIFMapUuidToNodeMapping {
1554 : public:
1555 : static const int kMaxElementsPerRound = 50;
1556 :
1557 4 : static int GetPageLimit(IFMapSandeshContext *sctx) {
1558 4 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
1559 : }
1560 :
1561 : static bool ProcessRequestCommon(const IFMapUuidToNodeMappingReq *req,
1562 : const string &last_uuid);
1563 :
1564 : static bool ProcessRequest(
1565 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1566 : int instNum, RequestPipeline::InstData *data);
1567 :
1568 : static bool ProcessRequestIterate(
1569 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1570 : int instNum, RequestPipeline::InstData *data);
1571 : };
1572 :
1573 4 : bool ShowIFMapUuidToNodeMapping::ProcessRequestCommon(
1574 : const IFMapUuidToNodeMappingReq *req, const string &last_uuid) {
1575 : IFMapSandeshContext *sctx =
1576 4 : static_cast<IFMapSandeshContext *>(req->module_context("IFMap"));
1577 4 : uint32_t page_limit = GetPageLimit(sctx);
1578 4 : IFMapVmUuidMapper *mapper = sctx->ifmap_server()->vm_uuid_mapper();
1579 4 : IFMapUuidMapper &uuid_mapper = mapper->uuid_mapper_;
1580 :
1581 4 : vector<IFMapUuidToNodeMappingEntry> dest_buffer;
1582 4 : IFMapUuidMapper::UuidNodeMap::const_iterator iter;
1583 4 : if (last_uuid.size()) {
1584 2 : iter = uuid_mapper.uuid_node_map_.upper_bound(last_uuid);
1585 : } else {
1586 2 : iter = uuid_mapper.uuid_node_map_.begin();
1587 : }
1588 20 : for (uint32_t iter_count = 0; (iter_count != page_limit) &&
1589 28 : (iter != uuid_mapper.uuid_node_map_.end()); iter++, iter_count++) {
1590 8 : IFMapUuidToNodeMappingEntry dest;
1591 8 : dest.set_uuid(iter->first);
1592 8 : IFMapNode *node = static_cast<IFMapNode *>(iter->second);
1593 8 : dest.set_node_name(node->ToString());
1594 8 : dest_buffer.push_back(dest);
1595 8 : }
1596 :
1597 4 : IFMapUuidToNodeMappingResp *response = new IFMapUuidToNodeMappingResp();
1598 4 : response->set_map_count(dest_buffer.size());
1599 4 : response->set_uuid_to_node_map(dest_buffer);
1600 4 : if (iter++ != uuid_mapper.uuid_node_map_.end()) {
1601 2 : response->set_next_batch(dest_buffer.back().get_uuid());
1602 : }
1603 4 : response->set_context(req->context());
1604 4 : response->set_more(false);
1605 4 : response->Response();
1606 4 : return true;
1607 4 : }
1608 :
1609 2 : bool ShowIFMapUuidToNodeMapping::ProcessRequestIterate(
1610 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1611 : int instNum, RequestPipeline::InstData *data) {
1612 : const IFMapUuidToNodeMappingReqIterate *request_iterate =
1613 : static_cast<const IFMapUuidToNodeMappingReqIterate *>
1614 2 : (ps.snhRequest_.get());
1615 2 : IFMapUuidToNodeMappingReq *request = new IFMapUuidToNodeMappingReq;
1616 2 : request->set_context(request_iterate->context());
1617 2 : string last_uuid = request_iterate->get_uuid_info();
1618 2 : ProcessRequestCommon(request, last_uuid);
1619 2 : request->Release();
1620 2 : return true;
1621 2 : }
1622 :
1623 2 : bool ShowIFMapUuidToNodeMapping::ProcessRequest(
1624 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1625 : int instNum, RequestPipeline::InstData *data) {
1626 : const IFMapUuidToNodeMappingReq *request =
1627 2 : static_cast<const IFMapUuidToNodeMappingReq *>(ps.snhRequest_.get());
1628 2 : string last_uuid;
1629 2 : ProcessRequestCommon(request, last_uuid);
1630 2 : return true;
1631 2 : }
1632 :
1633 :
1634 2 : void IFMapUuidToNodeMappingReq::HandleRequest() const {
1635 :
1636 2 : RequestPipeline::StageSpec s0;
1637 2 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1638 :
1639 2 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1640 2 : s0.cbFn_ = ShowIFMapUuidToNodeMapping::ProcessRequest;
1641 2 : s0.instances_.push_back(0);
1642 :
1643 2 : RequestPipeline::PipeSpec ps(this);
1644 2 : ps.stages_ = boost::assign::list_of(s0)
1645 2 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1646 2 : RequestPipeline rp(ps);
1647 2 : }
1648 :
1649 2 : void IFMapUuidToNodeMappingReqIterate::HandleRequest() const {
1650 :
1651 2 : RequestPipeline::StageSpec s0;
1652 2 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1653 :
1654 2 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1655 2 : s0.cbFn_ = ShowIFMapUuidToNodeMapping::ProcessRequestIterate;
1656 2 : s0.instances_.push_back(0);
1657 :
1658 2 : RequestPipeline::PipeSpec ps(this);
1659 2 : ps.stages_ = boost::assign::list_of(s0)
1660 2 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1661 2 : RequestPipeline rp(ps);
1662 2 : }
1663 :
1664 : class ShowIFMapNodeToUuidMapping {
1665 : public:
1666 : static const int kMaxElementsPerRound = 50;
1667 :
1668 4 : static int GetPageLimit(IFMapSandeshContext *sctx) {
1669 4 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
1670 : }
1671 :
1672 : static bool ProcessRequestCommon(const IFMapNodeToUuidMappingReq *req,
1673 : const string &last_uuid);
1674 :
1675 : static bool ProcessRequest(
1676 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1677 : int instNum, RequestPipeline::InstData *data);
1678 :
1679 : static bool ProcessRequestIterate(
1680 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1681 : int instNum, RequestPipeline::InstData *data);
1682 : };
1683 :
1684 4 : bool ShowIFMapNodeToUuidMapping::ProcessRequestCommon(
1685 : const IFMapNodeToUuidMappingReq *req, const string &last_uuid) {
1686 : IFMapSandeshContext *sctx =
1687 4 : static_cast<IFMapSandeshContext *>(req->module_context("IFMap"));
1688 4 : uint32_t page_limit = GetPageLimit(sctx);
1689 :
1690 4 : IFMapVmUuidMapper *mapper = sctx->ifmap_server()->vm_uuid_mapper();
1691 :
1692 4 : vector<IFMapNodeToUuidMappingEntry> dest_buffer;
1693 4 : IFMapVmUuidMapper::NodeUuidMap::const_iterator iter;
1694 4 : if (last_uuid.size()) {
1695 2 : IFMapNode *vm = mapper->GetVmNodeByUuid(last_uuid);
1696 2 : iter = mapper->node_uuid_map_.upper_bound(vm);
1697 : } else {
1698 2 : iter = mapper->node_uuid_map_.begin();
1699 : }
1700 : IFMapNode *node;
1701 20 : for (uint32_t iter_count = 0; (iter_count != page_limit) &&
1702 28 : (iter != mapper->node_uuid_map_.end()); iter++, iter_count++) {
1703 8 : IFMapNodeToUuidMappingEntry dest;
1704 8 : node = static_cast<IFMapNode *>(iter->first);
1705 8 : dest.set_node_name(node->ToString());
1706 8 : dest.set_uuid(iter->second);
1707 8 : dest_buffer.push_back(dest);
1708 8 : }
1709 4 : IFMapNodeToUuidMappingResp *response = new IFMapNodeToUuidMappingResp();
1710 4 : response->set_map_count(dest_buffer.size());
1711 4 : response->set_node_to_uuid_map(dest_buffer);
1712 4 : if (iter != mapper->node_uuid_map_.end()) {
1713 2 : string next_batch = iter->second;
1714 2 : response->set_next_batch(next_batch);
1715 2 : }
1716 4 : response->set_context(req->context());
1717 4 : response->set_more(false);
1718 4 : response->Response();
1719 4 : return true;
1720 4 : }
1721 :
1722 2 : bool ShowIFMapNodeToUuidMapping::ProcessRequestIterate(
1723 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1724 : int instNum, RequestPipeline::InstData *data) {
1725 : const IFMapNodeToUuidMappingReqIterate *request_iterate =
1726 : static_cast<const IFMapNodeToUuidMappingReqIterate
1727 2 : *>(ps.snhRequest_.get());
1728 2 : IFMapNodeToUuidMappingReq *request = new IFMapNodeToUuidMappingReq;
1729 2 : request->set_context(request_iterate->context());
1730 2 : string last_uuid = request_iterate->get_uuid_info();
1731 2 : ProcessRequestCommon(request, last_uuid);
1732 2 : request->Release();
1733 2 : return true;
1734 2 : }
1735 :
1736 2 : bool ShowIFMapNodeToUuidMapping::ProcessRequest(
1737 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1738 : int instNum, RequestPipeline::InstData *data) {
1739 : const IFMapNodeToUuidMappingReq *request =
1740 2 : static_cast<const IFMapNodeToUuidMappingReq *>(ps.snhRequest_.get());
1741 2 : string last_uuid;
1742 2 : ProcessRequestCommon(request, last_uuid);
1743 2 : return true;
1744 2 : }
1745 :
1746 2 : void IFMapNodeToUuidMappingReq::HandleRequest() const {
1747 :
1748 2 : RequestPipeline::StageSpec s0;
1749 2 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1750 :
1751 2 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1752 2 : s0.cbFn_ = ShowIFMapNodeToUuidMapping::ProcessRequest;
1753 2 : s0.instances_.push_back(0);
1754 :
1755 2 : RequestPipeline::PipeSpec ps(this);
1756 2 : ps.stages_ = boost::assign::list_of(s0)
1757 2 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1758 2 : RequestPipeline rp(ps);
1759 2 : }
1760 :
1761 2 : void IFMapNodeToUuidMappingReqIterate::HandleRequest() const {
1762 :
1763 2 : RequestPipeline::StageSpec s0;
1764 2 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1765 :
1766 2 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1767 2 : s0.cbFn_ = ShowIFMapNodeToUuidMapping::ProcessRequestIterate;
1768 2 : s0.instances_.push_back(0);
1769 :
1770 2 : RequestPipeline::PipeSpec ps(this);
1771 2 : ps.stages_ = boost::assign::list_of(s0)
1772 2 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1773 2 : RequestPipeline rp(ps);
1774 2 : }
1775 :
1776 : class ShowIFMapPendingVmReg {
1777 : public:
1778 : static const int kMaxElementsPerRound = 50;
1779 :
1780 6 : static int GetPageLimit(IFMapSandeshContext *sctx) {
1781 6 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
1782 : }
1783 :
1784 : struct ShowData : public RequestPipeline::InstData {
1785 : vector<IFMapPendingVmRegEntry> send_buffer;
1786 : };
1787 :
1788 4 : static RequestPipeline::InstData* AllocBuffer(int stage) {
1789 4 : return static_cast<RequestPipeline::InstData *>(new ShowData);
1790 : }
1791 :
1792 : struct TrackerData : public RequestPipeline::InstData {
1793 : // init as 1 indicates we need to init 'first' to begin() since there is
1794 : // no way to initialize an iterator here.
1795 4 : TrackerData() : init(1) { }
1796 : int init;
1797 : vector<IFMapPendingVmRegEntry>::const_iterator first;
1798 : };
1799 :
1800 4 : static RequestPipeline::InstData* AllocTracker(int stage) {
1801 4 : return static_cast<RequestPipeline::InstData *>(new TrackerData);
1802 : }
1803 :
1804 : static bool BufferStage(const Sandesh *sr,
1805 : const RequestPipeline::PipeSpec ps, int stage,
1806 : int instNum, RequestPipeline::InstData *data);
1807 : static bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
1808 : int stage, int instNum,
1809 : RequestPipeline::InstData *data);
1810 : };
1811 :
1812 4 : bool ShowIFMapPendingVmReg::BufferStage(const Sandesh *sr,
1813 : const RequestPipeline::PipeSpec ps,
1814 : int stage, int instNum,
1815 : RequestPipeline::InstData *data) {
1816 : const IFMapPendingVmRegReq *request =
1817 4 : static_cast<const IFMapPendingVmRegReq *>(ps.snhRequest_.get());
1818 : IFMapSandeshContext *sctx =
1819 4 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1820 4 : ShowData *show_data = static_cast<ShowData *>(data);
1821 :
1822 4 : IFMapVmUuidMapper *mapper = sctx->ifmap_server()->vm_uuid_mapper();
1823 :
1824 4 : show_data->send_buffer.reserve(mapper->PendingVmRegCount());
1825 4 : for (IFMapVmUuidMapper::PendingVmRegMap::const_iterator iter =
1826 4 : mapper->pending_vmreg_map_.begin();
1827 16 : iter != mapper->pending_vmreg_map_.end(); ++iter) {
1828 12 : IFMapPendingVmRegEntry dest;
1829 12 : dest.set_vm_uuid(iter->first);
1830 12 : dest.set_vr_name(iter->second);
1831 12 : show_data->send_buffer.push_back(dest);
1832 12 : }
1833 :
1834 4 : return true;
1835 : }
1836 :
1837 : // Can be called multiple times i.e. approx total/kMaxElementsPerRound
1838 6 : bool ShowIFMapPendingVmReg::SendStage(const Sandesh *sr,
1839 : const RequestPipeline::PipeSpec ps,
1840 : int stage, int instNum,
1841 : RequestPipeline::InstData *data) {
1842 6 : const RequestPipeline::StageData *prev_stage_data = ps.GetStageData(0);
1843 : const ShowIFMapPendingVmReg::ShowData &show_data =
1844 : static_cast<const ShowIFMapPendingVmReg::ShowData&>
1845 6 : (prev_stage_data->at(0));
1846 : // Data for this stage
1847 6 : TrackerData *tracker_data = static_cast<TrackerData *>(data);
1848 :
1849 6 : vector<IFMapPendingVmRegEntry> dest_buffer;
1850 6 : vector<IFMapPendingVmRegEntry>::const_iterator first, last;
1851 6 : bool more = false;
1852 :
1853 6 : if (tracker_data->init) {
1854 4 : first = show_data.send_buffer.begin();
1855 4 : tracker_data->init = 0;
1856 : } else {
1857 2 : first = tracker_data->first;
1858 : }
1859 6 : int rem_num = show_data.send_buffer.end() - first;
1860 : const IFMapPendingVmRegReq *request =
1861 6 : static_cast<const IFMapPendingVmRegReq *>(ps.snhRequest_.get());
1862 : IFMapSandeshContext *sctx =
1863 6 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1864 6 : uint32_t page_limit = GetPageLimit(sctx);
1865 6 : int send_num = (rem_num < (int)page_limit) ? rem_num : (int)page_limit;
1866 6 : last = first + send_num;
1867 6 : copy(first, last, back_inserter(dest_buffer));
1868 : // Decide if we want to be called again.
1869 6 : if ((rem_num - send_num) > 0) {
1870 2 : more = true;
1871 : } else {
1872 4 : more = false;
1873 : }
1874 6 : IFMapPendingVmRegResp *response = new IFMapPendingVmRegResp();
1875 6 : response->set_map_count(dest_buffer.size());
1876 6 : response->set_vm_reg_map(dest_buffer);
1877 6 : response->set_context(request->context());
1878 6 : response->set_more(more);
1879 6 : response->Response();
1880 6 : tracker_data->first = first + send_num;
1881 :
1882 : // Return 'false' to be called again
1883 6 : return (!more);
1884 6 : }
1885 :
1886 4 : void IFMapPendingVmRegReq::HandleRequest() const {
1887 :
1888 4 : RequestPipeline::StageSpec s0, s1;
1889 4 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1890 :
1891 : // 2 stages - first: gather/read, second: send
1892 :
1893 4 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1894 4 : s0.allocFn_ = ShowIFMapPendingVmReg::AllocBuffer;
1895 4 : s0.cbFn_ = ShowIFMapPendingVmReg::BufferStage;
1896 4 : s0.instances_.push_back(0);
1897 :
1898 : // control-node ifmap show command task
1899 4 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
1900 4 : s1.allocFn_ = ShowIFMapPendingVmReg::AllocTracker;
1901 4 : s1.cbFn_ = ShowIFMapPendingVmReg::SendStage;
1902 4 : s1.instances_.push_back(0);
1903 :
1904 4 : RequestPipeline::PipeSpec ps(this);
1905 4 : ps.stages_ = list_of(s0)(s1)
1906 4 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1907 4 : RequestPipeline rp(ps);
1908 4 : }
1909 :
1910 0 : static bool IFMapServerClientShowReqHandleRequest(
1911 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1912 : int instNum, RequestPipeline::InstData *data) {
1913 : const IFMapServerClientShowReq *request =
1914 0 : static_cast<const IFMapServerClientShowReq *>(ps.snhRequest_.get());
1915 : IFMapSandeshContext *sctx =
1916 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1917 :
1918 0 : IFMapServerClientShowResp *response = new IFMapServerClientShowResp();
1919 0 : string search_string = request->get_search_string();
1920 :
1921 0 : IFMapServerShowClientMap name_list;
1922 0 : sctx->ifmap_server()->FillClientMap(&name_list, search_string);
1923 0 : IFMapServerShowIndexMap index_list;
1924 0 : sctx->ifmap_server()->FillIndexMap(&index_list, search_string);
1925 0 : IFMapServerClientHistoryList history_list;
1926 0 : sctx->ifmap_server()->FillClientHistory(&history_list, search_string);
1927 :
1928 0 : response->set_name_list(name_list);
1929 0 : response->set_index_list(index_list);
1930 0 : response->set_history_list(history_list);
1931 0 : response->set_context(request->context());
1932 0 : response->set_more(false);
1933 0 : response->Response();
1934 :
1935 : // Return 'true' so that we are not called again
1936 0 : return true;
1937 0 : }
1938 :
1939 0 : void IFMapServerClientShowReq::HandleRequest() const {
1940 :
1941 0 : RequestPipeline::StageSpec s0;
1942 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1943 :
1944 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1945 0 : s0.cbFn_ = IFMapServerClientShowReqHandleRequest;
1946 0 : s0.instances_.push_back(0);
1947 :
1948 0 : RequestPipeline::PipeSpec ps(this);
1949 0 : ps.stages_ = boost::assign::list_of(s0)
1950 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1951 0 : RequestPipeline rp(ps);
1952 0 : }
1953 :
1954 0 : static bool IFMapNodeTableListShowReqHandleRequest(
1955 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
1956 : int instNum, RequestPipeline::InstData *data) {
1957 : const IFMapNodeTableListShowReq *request =
1958 0 : static_cast<const IFMapNodeTableListShowReq *>(ps.snhRequest_.get());
1959 : IFMapSandeshContext *sctx =
1960 0 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
1961 :
1962 0 : vector<IFMapNodeTableListShowEntry> dest_buffer;
1963 0 : IFMapTable::FillNodeTableList(sctx->ifmap_server()->database(),
1964 : &dest_buffer);
1965 :
1966 0 : IFMapNodeTableListShowResp *response = new IFMapNodeTableListShowResp();
1967 0 : response->set_table_list(dest_buffer);
1968 0 : response->set_context(request->context());
1969 0 : response->set_more(false);
1970 0 : response->Response();
1971 :
1972 : // Return 'true' so that we are not called again
1973 0 : return true;
1974 0 : }
1975 :
1976 0 : void IFMapNodeTableListShowReq::HandleRequest() const {
1977 :
1978 0 : RequestPipeline::StageSpec s0;
1979 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
1980 :
1981 0 : s0.taskId_ = scheduler->GetTaskId("db::IFMapTable");
1982 0 : s0.cbFn_ = IFMapNodeTableListShowReqHandleRequest;
1983 0 : s0.instances_.push_back(0);
1984 :
1985 0 : RequestPipeline::PipeSpec ps(this);
1986 0 : ps.stages_ = boost::assign::list_of(s0)
1987 0 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
1988 0 : RequestPipeline rp(ps);
1989 0 : }
1990 :
1991 : class ShowConfigDBUUIDCache {
1992 : public:
1993 : static const uint32_t kMaxElementsPerRound = 50;
1994 :
1995 234 : static int GetPageLimit(IFMapSandeshContext *sctx) {
1996 234 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
1997 : }
1998 :
1999 : struct ShowData : public RequestPipeline::InstData {
2000 : vector<ConfigDBUUIDCacheEntry> send_buffer;
2001 : };
2002 :
2003 208 : static RequestPipeline::InstData* AllocBuffer(int stage) {
2004 208 : return static_cast<RequestPipeline::InstData *>(new ShowData);
2005 : }
2006 :
2007 : static bool BufferStageCommon(const ConfigDBUUIDCacheReq *request,
2008 : int instNum, RequestPipeline::InstData *data,
2009 : const string &last_uuid);
2010 : static bool BufferStage(const Sandesh *sr,
2011 : const RequestPipeline::PipeSpec ps, int stage,
2012 : int instNum, RequestPipeline::InstData *data);
2013 : static bool BufferStageIterate(const Sandesh *sr,
2014 : const RequestPipeline::PipeSpec ps, int stage,
2015 : int instNum, RequestPipeline::InstData *data);
2016 : static void SendStageCommon(const ConfigDBUUIDCacheReq *request,
2017 : const RequestPipeline::PipeSpec ps,
2018 : ConfigDBUUIDCacheResp *response);
2019 : static bool SendStage(const Sandesh *sr, const RequestPipeline::PipeSpec ps,
2020 : int stage, int instNum,
2021 : RequestPipeline::InstData *data);
2022 : static bool SendStageIterate(const Sandesh *sr,
2023 : const RequestPipeline::PipeSpec ps, int stage,
2024 : int instNum, RequestPipeline::InstData *data);
2025 : static bool SortList(const ConfigDBUUIDCacheEntry &lhs,
2026 : const ConfigDBUUIDCacheEntry &rhs);
2027 : static bool ConvertReqIterateToReq(
2028 : const ConfigDBUUIDCacheReqIterate *req_iterate,
2029 : ConfigDBUUIDCacheReq *req, string *last_uuid);
2030 : };
2031 :
2032 14 : bool ShowConfigDBUUIDCache::SortList(
2033 : const ConfigDBUUIDCacheEntry &lhs,
2034 : const ConfigDBUUIDCacheEntry &rhs) {
2035 14 : BOOL_KEY_COMPARE(lhs.uuid, rhs.uuid);
2036 0 : return false;
2037 : }
2038 :
2039 : // Format of uuid_info string:
2040 : // search_string||last_uuid
2041 : // search_string: original input. Could be empty.
2042 : // last_uuid : uuid of last UUIDToFQName entry that was printed in the
2043 : // previous round
2044 72 : bool ShowConfigDBUUIDCache::ConvertReqIterateToReq(
2045 : const ConfigDBUUIDCacheReqIterate *req_iterate,
2046 : ConfigDBUUIDCacheReq *req, string *last_uuid) {
2047 : // First, set the context from the original request since we might return
2048 : // due to parsing errors.
2049 72 : req->set_context(req_iterate->context());
2050 :
2051 72 : string uuid_info = req_iterate->get_uuid_info();
2052 72 : size_t sep_size = kShowIterSeparator.size();
2053 :
2054 : // search_string
2055 72 : size_t pos1 = uuid_info.find(kShowIterSeparator);
2056 72 : if (pos1 == string::npos) {
2057 0 : return false;
2058 : }
2059 72 : string search_string = uuid_info.substr(0, pos1);
2060 :
2061 : // last_uuid
2062 72 : *last_uuid = uuid_info.substr((pos1 + sep_size));
2063 :
2064 : // Fill up the fields of ConfigDBUUIDCacheReq appropriately.
2065 72 : req->set_search_string(search_string);
2066 72 : return true;
2067 72 : }
2068 :
2069 :
2070 208 : bool ShowConfigDBUUIDCache::BufferStageCommon(
2071 : const ConfigDBUUIDCacheReq *req, int instNum,
2072 : RequestPipeline::InstData *data, const string &last_uuid) {
2073 : IFMapSandeshContext *sctx =
2074 208 : static_cast<IFMapSandeshContext *>(req->module_context("IFMap"));
2075 208 : ConfigClientManager *ccmgr = sctx->ifmap_server()->get_config_manager();
2076 208 : ShowData *show_data = static_cast<ShowData *>(data);
2077 208 : uint32_t page_limit = GetPageLimit(sctx);
2078 208 : show_data->send_buffer.reserve(page_limit);
2079 208 : ccmgr->config_db_client()->UUIDToObjCacheShow(req->get_search_string(),
2080 : instNum,
2081 : last_uuid, page_limit,
2082 : &show_data->send_buffer);
2083 208 : return true;
2084 : }
2085 :
2086 144 : bool ShowConfigDBUUIDCache::BufferStage(const Sandesh *sr,
2087 : const RequestPipeline::PipeSpec ps,
2088 : int stage, int instNum,
2089 : RequestPipeline::InstData *data) {
2090 : const ConfigDBUUIDCacheReq *request =
2091 144 : static_cast<const ConfigDBUUIDCacheReq *>(ps.snhRequest_.get());
2092 144 : string last_uuid;
2093 288 : return BufferStageCommon(request, instNum, data, last_uuid);
2094 144 : }
2095 :
2096 64 : bool ShowConfigDBUUIDCache::BufferStageIterate(
2097 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
2098 : int instNum, RequestPipeline::InstData *data) {
2099 : const ConfigDBUUIDCacheReqIterate *request_iterate =
2100 64 : static_cast<const ConfigDBUUIDCacheReqIterate *>(ps.snhRequest_.get());
2101 :
2102 64 : ConfigDBUUIDCacheReq *request = new ConfigDBUUIDCacheReq;
2103 64 : string last_uuid;
2104 64 : bool success = ConvertReqIterateToReq(request_iterate, request,
2105 : &last_uuid);
2106 64 : if (success) {
2107 64 : BufferStageCommon(request, instNum, data, last_uuid);
2108 : }
2109 64 : request->Release();
2110 64 : return true;
2111 64 : }
2112 :
2113 26 : void ShowConfigDBUUIDCache::SendStageCommon(const ConfigDBUUIDCacheReq *request,
2114 : const RequestPipeline::PipeSpec ps,
2115 : ConfigDBUUIDCacheResp *response) {
2116 26 : const RequestPipeline::StageData *prev_stage_data = ps.GetStageData(0);
2117 :
2118 26 : vector<ConfigDBUUIDCacheEntry> uuid_cache_list;
2119 234 : for (size_t i = 0; i < prev_stage_data->size(); ++i) {
2120 : const ShowConfigDBUUIDCache::ShowData &show_data = static_cast
2121 208 : <const ShowConfigDBUUIDCache::ShowData&>(prev_stage_data->at(i));
2122 208 : if (show_data.send_buffer.size()) {
2123 36 : size_t list_size = uuid_cache_list.size();
2124 36 : uuid_cache_list.reserve(list_size + show_data.send_buffer.size());
2125 36 : copy(show_data.send_buffer.begin(),
2126 : show_data.send_buffer.end(),
2127 : std::back_inserter(uuid_cache_list));
2128 36 : if (list_size) {
2129 28 : std::inplace_merge(uuid_cache_list.begin(),
2130 28 : uuid_cache_list.begin() + list_size,
2131 : uuid_cache_list.end(),
2132 : ShowConfigDBUUIDCache::SortList);
2133 : }
2134 : }
2135 : }
2136 :
2137 : // If we have filled the buffer, set next_batch with all the values we will
2138 : // need in the next round.
2139 26 : string next_batch;
2140 : IFMapSandeshContext *sctx =
2141 26 : static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
2142 26 : uint32_t page_limit = GetPageLimit(sctx);
2143 26 : if (uuid_cache_list.size() > page_limit) {
2144 : vector<ConfigDBUUIDCacheEntry> ouput_list(uuid_cache_list.begin(),
2145 2 : uuid_cache_list.begin()
2146 2 : + page_limit);
2147 2 : response->set_uuid_cache(ouput_list);
2148 2 : next_batch = request->get_search_string() + kShowIterSeparator
2149 4 : + ouput_list.back().uuid;
2150 2 : } else {
2151 24 : response->set_uuid_cache(uuid_cache_list);
2152 : }
2153 :
2154 26 : response->set_next_batch(next_batch);
2155 26 : }
2156 :
2157 18 : bool ShowConfigDBUUIDCache::SendStage(const Sandesh *sr,
2158 : const RequestPipeline::PipeSpec ps,
2159 : int stage, int instNum,
2160 : RequestPipeline::InstData *data) {
2161 : const ConfigDBUUIDCacheReq *request =
2162 18 : static_cast<const ConfigDBUUIDCacheReq *>(ps.snhRequest_.get());
2163 18 : ConfigDBUUIDCacheResp *response = new ConfigDBUUIDCacheResp;
2164 18 : SendStageCommon(request, ps, response);
2165 18 : response->set_context(request->context());
2166 18 : response->set_more(false);
2167 18 : response->Response();
2168 18 : return true;
2169 : }
2170 :
2171 8 : bool ShowConfigDBUUIDCache::SendStageIterate(const Sandesh *sr,
2172 : const RequestPipeline::PipeSpec ps,
2173 : int stage, int instNum,
2174 : RequestPipeline::InstData *data) {
2175 : const ConfigDBUUIDCacheReqIterate *request_iterate =
2176 8 : static_cast<const ConfigDBUUIDCacheReqIterate *>(ps.snhRequest_.get());
2177 :
2178 8 : ConfigDBUUIDCacheResp *response = new ConfigDBUUIDCacheResp;
2179 8 : ConfigDBUUIDCacheReq *request = new ConfigDBUUIDCacheReq;
2180 8 : string last_uuid;
2181 8 : bool success = ConvertReqIterateToReq(request_iterate, request,
2182 : &last_uuid);
2183 8 : if (success) {
2184 8 : SendStageCommon(request, ps, response);
2185 : }
2186 :
2187 8 : response->set_context(request->context());
2188 8 : response->set_more(false);
2189 8 : response->Response();
2190 :
2191 8 : request->Release();
2192 8 : return true;
2193 8 : }
2194 :
2195 18 : void ConfigDBUUIDCacheReq::HandleRequest() const {
2196 :
2197 18 : RequestPipeline::StageSpec s0, s1;
2198 18 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
2199 :
2200 : // 2 stages - first: gather/read, second: send
2201 :
2202 18 : s0.taskId_ = scheduler->GetTaskId("config_client::Reader");
2203 18 : s0.allocFn_ = ShowConfigDBUUIDCache::AllocBuffer;
2204 18 : s0.cbFn_ = ShowConfigDBUUIDCache::BufferStage;
2205 162 : for (int i = 0; i < ConfigClientManager::GetNumConfigReader(); ++i) {
2206 144 : s0.instances_.push_back(i);
2207 : }
2208 :
2209 : // control-node ifmap show command task
2210 18 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
2211 18 : s1.cbFn_ = ShowConfigDBUUIDCache::SendStage;
2212 18 : s1.instances_.push_back(0);
2213 :
2214 18 : RequestPipeline::PipeSpec ps(this);
2215 18 : ps.stages_ = list_of(s0)(s1)
2216 18 : .convert_to_container<vector<RequestPipeline::StageSpec> >();
2217 18 : RequestPipeline rp(ps);
2218 18 : }
2219 :
2220 8 : void ConfigDBUUIDCacheReqIterate::HandleRequest() const {
2221 :
2222 8 : RequestPipeline::StageSpec s0, s1;
2223 8 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
2224 :
2225 : // 2 stages - first: gather/read, second: send
2226 :
2227 8 : s0.taskId_ = scheduler->GetTaskId("config_client::Reader");
2228 8 : s0.allocFn_ = ShowConfigDBUUIDCache::AllocBuffer;
2229 8 : s0.cbFn_ = ShowConfigDBUUIDCache::BufferStageIterate;
2230 72 : for (int i = 0; i < ConfigClientManager::GetNumConfigReader(); ++i) {
2231 64 : s0.instances_.push_back(i);
2232 : }
2233 :
2234 : // control-node ifmap show command task
2235 8 : s1.taskId_ = scheduler->GetTaskId("ifmap::ShowCommandSendStage");
2236 8 : s1.cbFn_ = ShowConfigDBUUIDCache::SendStageIterate;
2237 8 : s1.instances_.push_back(0);
2238 :
2239 8 : RequestPipeline::PipeSpec ps(this);
2240 8 : ps.stages_ = list_of(s0)(s1)
2241 : .convert_to_container\
2242 8 : <vector<RequestPipeline::StageSpec> >();
2243 8 : RequestPipeline rp(ps);
2244 8 : }
2245 :
2246 : class ShowConfigDBUUIDToFQName {
2247 : public:
2248 : static const int kMaxElementsPerRound = 50;
2249 :
2250 18 : static int GetPageLimit(IFMapSandeshContext *sctx) {
2251 18 : return (sctx->page_limit() ? sctx->page_limit() : kMaxElementsPerRound);
2252 : }
2253 :
2254 : static bool ProcessRequestCommon(const ConfigDBUUIDToFQNameReq *req,
2255 : const string &last_uuid);
2256 :
2257 : static bool ProcessRequest(
2258 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
2259 : int instNum, RequestPipeline::InstData *data);
2260 :
2261 : static bool ProcessRequestIterate(
2262 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
2263 : int instNum, RequestPipeline::InstData *data);
2264 :
2265 : static bool ConvertReqIterateToReq(
2266 : const ConfigDBUUIDToFQNameReqIterate *req_iterate,
2267 : ConfigDBUUIDToFQNameReq *req, string *last_uuid);
2268 : };
2269 :
2270 : // Format of uuid_info string:
2271 : // search_string||last_uuid
2272 : // search_string: original input. Could be empty.
2273 : // last_uuid : uuid of last UUIDToFQName entry that was printed in the
2274 : // previous round
2275 8 : bool ShowConfigDBUUIDToFQName::ConvertReqIterateToReq(
2276 : const ConfigDBUUIDToFQNameReqIterate *req_iterate,
2277 : ConfigDBUUIDToFQNameReq *req, string *last_uuid) {
2278 : // First, set the context from the original request since we might return
2279 : // due to parsing errors.
2280 8 : req->set_context(req_iterate->context());
2281 :
2282 8 : string uuid_info = req_iterate->get_uuid_info();
2283 8 : size_t sep_size = kShowIterSeparator.size();
2284 :
2285 : // search_string
2286 8 : size_t pos1 = uuid_info.find(kShowIterSeparator);
2287 8 : if (pos1 == string::npos) {
2288 0 : return false;
2289 : }
2290 8 : string search_string = uuid_info.substr(0, pos1);
2291 :
2292 : // last_uuid
2293 8 : *last_uuid = uuid_info.substr((pos1 + sep_size));
2294 :
2295 : // Fill up the fields of ConfigDBUUIDToFQNameReq appropriately.
2296 8 : req->set_search_string(search_string);
2297 8 : return true;
2298 8 : }
2299 :
2300 18 : bool ShowConfigDBUUIDToFQName::ProcessRequestCommon(
2301 : const ConfigDBUUIDToFQNameReq *req, const string &last_uuid) {
2302 : IFMapSandeshContext *sctx =
2303 18 : static_cast<IFMapSandeshContext *>(req->module_context("IFMap"));
2304 18 : uint32_t page_limit = GetPageLimit(sctx);
2305 18 : ConfigClientManager *ccmgr = sctx->ifmap_server()->get_config_manager();
2306 18 : vector<ConfigDBFQNameCacheEntry> dest_buffer;
2307 18 : bool more = ccmgr->config_db_client()->UUIDToFQNameShow(
2308 : req->get_search_string(), last_uuid, page_limit, &dest_buffer);
2309 18 : string next_batch;
2310 18 : ConfigDBUUIDToFQNameResp *response = new ConfigDBUUIDToFQNameResp();
2311 18 : if (more) {
2312 2 : next_batch = req->get_search_string()
2313 4 : + kShowIterSeparator + dest_buffer.back().get_uuid();
2314 : }
2315 18 : response->set_fqname_cache(dest_buffer);
2316 18 : response->set_next_batch(next_batch);
2317 18 : response->set_context(req->context());
2318 18 : response->set_more(false);
2319 18 : response->Response();
2320 18 : return true;
2321 18 : }
2322 :
2323 8 : bool ShowConfigDBUUIDToFQName::ProcessRequestIterate(
2324 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
2325 : int instNum, RequestPipeline::InstData *data) {
2326 : const ConfigDBUUIDToFQNameReqIterate *request_iterate =
2327 : static_cast<const ConfigDBUUIDToFQNameReqIterate
2328 8 : *>(ps.snhRequest_.get());
2329 8 : ConfigDBUUIDToFQNameReq *request = new ConfigDBUUIDToFQNameReq;
2330 8 : string last_uuid;
2331 8 : bool success = ConvertReqIterateToReq(request_iterate, request,
2332 : &last_uuid);
2333 8 : if (success) {
2334 8 : ProcessRequestCommon(request, last_uuid);
2335 : }
2336 8 : request->Release();
2337 8 : return true;
2338 8 : }
2339 :
2340 10 : bool ShowConfigDBUUIDToFQName::ProcessRequest(
2341 : const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage,
2342 : int instNum, RequestPipeline::InstData *data) {
2343 : const ConfigDBUUIDToFQNameReq *request =
2344 10 : static_cast<const ConfigDBUUIDToFQNameReq*>(ps.snhRequest_.get());
2345 10 : string last_uuid;
2346 10 : ProcessRequestCommon(request, last_uuid);
2347 10 : return true;
2348 10 : }
2349 :
2350 10 : void ConfigDBUUIDToFQNameReq::HandleRequest() const {
2351 :
2352 10 : RequestPipeline::StageSpec s0;
2353 10 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
2354 :
2355 10 : s0.taskId_ = scheduler->GetTaskId("config_client::Reader");
2356 10 : s0.cbFn_ = ShowConfigDBUUIDToFQName::ProcessRequest;
2357 10 : s0.instances_.push_back(0);
2358 :
2359 10 : RequestPipeline::PipeSpec ps(this);
2360 10 : ps.stages_ = boost::assign::list_of(s0)
2361 : .convert_to_container\
2362 10 : <vector<RequestPipeline::StageSpec> >();
2363 10 : RequestPipeline rp(ps);
2364 10 : }
2365 :
2366 8 : void ConfigDBUUIDToFQNameReqIterate::HandleRequest() const {
2367 :
2368 8 : RequestPipeline::StageSpec s0;
2369 8 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
2370 :
2371 8 : s0.taskId_ = scheduler->GetTaskId("config_client::Reader");
2372 8 : s0.cbFn_ = ShowConfigDBUUIDToFQName::ProcessRequestIterate;
2373 8 : s0.instances_.push_back(0);
2374 :
2375 8 : RequestPipeline::PipeSpec ps(this);
2376 8 : ps.stages_ = boost::assign::list_of(s0)
2377 : .convert_to_container
2378 8 : <vector<RequestPipeline::StageSpec> >();
2379 8 : RequestPipeline rp(ps);
2380 8 : }
|