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