LCOV - code coverage report
Current view: top level - ifmap - ifmap_server_show.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 392 1207 32.5 %
Date: 2026-11-09 02:10:49 Functions: 38 95 40.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14