8 #include <boost/assign/list_of.hpp>
9 #include <sandesh/request_pipeline.h>
12 #include "bgp/bgp_peer_internal_types.h"
18 using boost::assign::list_of;
19 using std::unique_ptr;
23 static bool IsLess(
const ShowRoute &lhs,
const ShowRoute &rhs,
30 unique_ptr<DBEntry> lhs_entry = table->
AllocEntryStr(lhs.get_prefix());
31 unique_ptr<DBEntry> rhs_entry = table->
AllocEntryStr(rhs.get_prefix());
33 Route *lhs_route =
static_cast<Route *
>(lhs_entry.get());
34 Route *rhs_route =
static_cast<Route *
>(rhs_entry.get());
36 return lhs_route->
IsLess(*rhs_route);
39 static bool IsLess(
const ShowRouteTable &lhs,
const ShowRouteTable &rhs,
41 if (lhs.get_routing_instance() < rhs.get_routing_instance()) {
44 if (lhs.get_routing_instance() == rhs.get_routing_instance()) {
45 return lhs.get_routing_table_name() < rhs.get_routing_table_name();
51 void MergeSort(vector<T> *result, vector<
const vector<T> *> *input,
int limit,
54 int MergeValues(ShowRoute *result, vector<const ShowRoute *> *input,
56 assert(input->size() == 1);
57 *result = *input->at(0);
61 int MergeValues(ShowRouteTable *result, vector<const ShowRouteTable *> *input,
63 vector<const vector<ShowRoute> *> list;
64 result->set_routing_instance(input->at(0)->get_routing_instance());
65 result->set_routing_table_name(input->at(0)->get_routing_table_name());
66 result->set_deleted(input->at(0)->get_deleted());
67 result->set_deleted_at(input->at(0)->get_deleted_at());
68 result->set_prefixes(input->at(0)->get_prefixes());
69 result->set_primary_paths(input->at(0)->get_primary_paths());
70 result->set_secondary_paths(input->at(0)->get_secondary_paths());
71 result->set_infeasible_paths(input->at(0)->get_infeasible_paths());
72 result->set_stale_paths(input->at(0)->get_stale_paths());
73 result->set_llgr_stale_paths(input->at(0)->get_llgr_stale_paths());
74 result->set_paths(input->at(0)->get_paths());
75 result->set_listeners(input->at(0)->get_listeners());
78 for (
size_t i = 0; i < input->size(); ++i) {
79 if (input->at(i)->get_routes().size())
80 list.push_back(&input->at(i)->get_routes());
82 MergeSort(
const_cast<vector<ShowRoute> *
>(&result->get_routes()), &list,
83 limit ? limit - count : 0, bsc,
84 input->at(0)->get_routing_table_name());
85 count += result->get_routes().size();
94 void MergeSort(vector<T> *result, vector<
const vector<T> *> *input,
int limit,
96 size_t size = input->size();
97 vector<size_t> index(size, 0);
99 while (limit == 0 || count < limit) {
100 size_t best_index = size;
101 const T *best = NULL;
102 for (
size_t i = 0; i < size; ++i) {
103 if (index[i] == input->at(i)->size())
106 IsLess(input->at(i)->at(index[i]), *best, bsc, table_name)) {
107 best = &input->at(i)->at(index[i]);
112 if (best_index >= size)
115 vector<const T *> list;
116 for (
size_t j = best_index; j < size; ++j) {
117 if (index[j] == input->at(j)->size())
119 if (
IsLess(input->at(j)->at(index[j]), *best, bsc, table_name) ||
120 IsLess(*best, input->at(j)->at(index[j]), bsc, table_name)) {
123 list.push_back(&input->at(j)->at(index[j]));
126 count +=
MergeValues(&table, &list, limit ? limit - count : 0, bsc);
127 result->push_back(table);
141 req_(req), inst_id_(inst_id), prefix_expr_(req->get_prefix()) {
146 vector<ShowRoute> *route_list,
int count) {
153 if (table->
name() ==
req_->get_start_routing_table()) {
154 unique_ptr<DBEntry> key =
160 for (
int i = 0; route && (!count || i < count);
163 req_->get_longer_match(),
164 req_->get_shorter_match()))
166 ShowRoute show_route;
168 req_->get_protocol());
169 if (!show_route.get_paths().empty())
170 route_list->push_back(show_route);
176 bool shorter_match) {
177 if (expected_prefix.empty())
179 if (!longer_match && !shorter_match)
196 return expected == actual;
209 uint32_t route_count = req->get_count() + 1;
210 if (!req->get_count() || (req->get_count() > max_count)) {
212 route_count = max_count + 1;
219 const ShowRouteReqIterate *req_iterate, ShowRouteReq *req) {
222 req->set_context(req_iterate->context());
230 string route_info = req_iterate->get_route_info();
234 if (pos1 == string::npos) {
237 string user_ri = route_info.substr(0, pos1);
240 if (pos2 == string::npos) {
243 string user_rt = route_info.substr((pos1 + sep_size),
244 pos2 - (pos1 + sep_size));
247 if (pos3 == string::npos) {
250 string user_prefix = route_info.substr((pos2 + sep_size),
251 pos3 - (pos2 + sep_size));
254 if (pos4 == string::npos) {
257 string next_ri = route_info.substr((pos3 + sep_size),
258 pos4 - (pos3 + sep_size));
261 if (pos5 == string::npos) {
264 string next_rt = route_info.substr((pos4 + sep_size),
265 pos5 - (pos4 + sep_size));
268 if (pos6 == string::npos) {
271 string next_prefix = route_info.substr((pos5 + sep_size),
272 pos6 - (pos5 + sep_size));
275 if (pos7 == string::npos) {
278 string count_str = route_info.substr((pos6 + sep_size),
279 pos7 - (pos6 + sep_size));
282 if (pos8 == string::npos) {
285 string user_source = route_info.substr((pos7 + sep_size),
286 pos8 - (pos7 + sep_size));
289 if (pos9 == string::npos) {
292 string user_protocol = route_info.substr((pos8 + sep_size),
293 pos9 - (pos8 + sep_size));
295 size_t pos10 = route_info.find(
kIterSeparator, (pos9 + sep_size));
296 if (pos10 == string::npos) {
299 string user_family = route_info.substr((pos9 + sep_size),
300 pos10 - (pos9 + sep_size));
302 size_t pos11 = route_info.find(
kIterSeparator, (pos10 + sep_size));
303 if (pos11 == string::npos) {
306 string longer_match = route_info.substr((pos10 + sep_size),
307 pos11 - (pos10 + sep_size));
309 string shorter_match = route_info.substr(pos11 + sep_size);
311 req->set_routing_instance(user_ri);
312 req->set_routing_table(user_rt);
313 req->set_prefix(user_prefix);
314 req->set_start_routing_instance(next_ri);
315 req->set_start_routing_table(next_rt);
316 req->set_start_prefix(next_prefix);
317 req->set_count(atoi(count_str.c_str()));
318 req->set_source(user_source);
319 req->set_protocol(user_protocol);
320 req->set_family(user_family);
336 string exact_routing_table = req->get_routing_table();
337 string exact_routing_instance;
338 string start_routing_instance;
339 if (exact_routing_table.empty()) {
340 exact_routing_instance = req->get_routing_instance();
342 exact_routing_instance =
345 if (exact_routing_instance.empty()) {
346 start_routing_instance = req->get_start_routing_instance();
348 start_routing_instance = exact_routing_instance;
355 if (!handler.
match(exact_routing_instance, i->first)) {
358 RoutingInstance::RouteTableList::const_iterator j;
359 if (req->get_start_routing_instance() == i->first) {
360 j = i->second->GetTables().
361 lower_bound(req->get_start_routing_table());
363 j = i->second->GetTables().begin();
365 for (; j != i->second->GetTables().end(); ++j) {
367 if (!req->get_family().empty() && req->get_family() !=
371 if (!handler.
match(req->get_routing_table(), table->
name())) {
376 srt.set_routing_table_name(table->
name());
382 srt.set_prefixes(table->
Size());
388 srt.set_paths(srt.get_primary_paths() + srt.get_secondary_paths());
390 vector<ShowTableListener> listeners;
392 srt.set_listeners(listeners);
394 vector<ShowRoute> route_list;
396 max_count ? max_count - count : 0);
397 if (route_list.size() || table->
IsDeleted()) {
398 srt.set_routes(route_list);
401 count += route_list.size();
402 if (count >= max_count) {
406 if (count >= max_count) {
420 int inst_id = ps.
stages_[stage].instances_[instNum];
421 const ShowRouteReq *req =
422 static_cast<const ShowRouteReq *
>(ps.
snhRequest_.get());
431 int inst_id = ps.
stages_[stage].instances_[instNum];
432 const ShowRouteReqIterate *req_iterate =
433 static_cast<const ShowRouteReqIterate *
>(ps.
snhRequest_.get());
435 ShowRouteReq *req =
new ShowRouteReq;
445 vector<ShowRouteTable> *route_table_list) {
449 if (route_table_list->empty()) {
455 uint32_t total_count = 0;
456 for (
size_t i = 0; i < route_table_list->size(); ++i) {
457 total_count += route_table_list->at(i).get_routes().size();
460 ShowRouteTable *last_route_table =
461 &route_table_list->at(route_table_list->size() - 1);
482 bool next_round =
true;
483 if (req->get_count()) {
487 new_count = req->get_count() - total_count + 1;
493 new_count = req->get_count();
497 ShowRoute last_route =
498 last_route_table->get_routes().at(
499 last_route_table->get_routes().size() - 1);
517 const_cast<vector<ShowRoute> *
>(
518 &last_route_table->get_routes())->pop_back();
519 if (last_route_table->get_routes().empty()) {
520 route_table_list->pop_back();
528 ShowRouteResp *resp) {
532 vector<ShowRouteTable> route_table_list;
533 vector<const vector<ShowRouteTable> *> table_lists;
534 for (
size_t i = 0; i < sd->size(); ++i) {
541 MergeSort(&route_table_list, &table_lists,
545 resp->set_next_batch(next_batch);
548 resp->set_tables(route_table_list);
554 const ShowRouteReq *req =
555 static_cast<const ShowRouteReq *
>(ps.
snhRequest_.get());
557 ShowRouteResp *resp =
new ShowRouteResp;
559 resp->set_context(req->context());
567 const ShowRouteReqIterate *req_iterate =
568 static_cast<const ShowRouteReqIterate *
>(ps.
snhRequest_.get());
570 ShowRouteResp *resp =
new ShowRouteResp;
571 ShowRouteReq *req =
new ShowRouteReq;
576 resp->set_context(req->context());
583 void ShowRouteReq::HandleRequest()
const {
606 ps.stages_= list_of(s1)(s2)
607 .convert_to_container<vector<RequestPipeline::StageSpec> >();
612 void ShowRouteReqIterate::HandleRequest()
const {
635 ps.stages_= list_of(s1)(s2)
636 .convert_to_container<vector<RequestPipeline::StageSpec> >();
RoutingInstanceList::iterator name_iterator
void FillRouteInfo(const BgpTable *table, ShowRouteBrief *show_route) const
std::vector< int > instances_
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
static const uint32_t kUnitTestMaxCount
boost::ptr_vector< InstData > StageData
static RequestPipeline::InstData * CreateData(int stage)
contrail::regex prefix_expr_
static const uint32_t kMaxCount
ShowRouteHandler(const ShowRouteReq *req, int inst_id)
virtual DBEntry * GetNext(const DBEntryBase *entry)
const uint64_t GetLlgrStalePathCount() const
virtual bool IsLessSpecific(const std::string &match) const
static void CallbackS2Common(const ShowRouteReq *req, const RequestPipeline::PipeSpec ps, ShowRouteResp *resp)
RoutingInstanceMgr * routing_instance_mgr()
const ShowRouteReq * req_
static bool CallbackS1(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
int MergeValues(ShowRoute *result, vector< const ShowRoute * > *input, int limit, const BgpSandeshContext *bsc)
static std::string FamilyToTableString(Family family)
static bool CallbackS1Iterate(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
bool match(const std::string &expected, const std::string &actual)
virtual Address::Family family() const =0
void FillListeners(std::vector< ShowTableListener > *listeners) const
int GetTaskId(const std::string &name)
static std::string SaveContextAndPopLast(const ShowRouteReq *req, std::vector< ShowRouteTable > *route_table_list)
virtual size_t Size() const
static uint32_t GetMaxCount(bool test_mode)
static const std::string integerToString(const NumberType &num)
const uint64_t GetInfeasiblePathCount() const
void MergeSort(vector< T > *result, vector< const vector< T > * > *input, int limit, const BgpSandeshContext *bsc, const string &table_name)
static TaskScheduler * GetInstance()
virtual std::string ToString() const =0
std::vector< StageSpec > stages_
static bool CallbackS2Iterate(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
virtual DBEntry * lower_bound(const DBEntryBase *entry)
const std::string & name() const
static bool CallbackS1Common(const ShowRouteReq *req, int inst_id, ShowRouteData *mydata)
static bool regex_search(const std::string &input, const regex ®ex)
static bool IsLess(const ShowRoute &lhs, const ShowRoute &rhs, const BgpSandeshContext *bsc, const string &table_name)
static bool ConvertReqIterateToReq(const ShowRouteReqIterate *req_iterate, ShowRouteReq *req)
bool MatchPrefix(const std::string &expected_prefix, BgpRoute *route, bool longer_match, bool shorter_match)
static std::string GetVrfFromTableName(const std::string table)
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
static bool CallbackS2(const Sandesh *sr, const RequestPipeline::PipeSpec &ps, int stage, int instNum, RequestPipeline::InstData *data)
const uint64_t GetPrimaryPathCount() const
virtual bool IsLess(const DBEntry &rhs) const =0
static uint32_t GetMaxRouteCount(const ShowRouteReq *req)
static char kIterSeparator[]
name_iterator name_lower_bound(const std::string &name)
LifetimeActor * deleter()
boost::shared_ptr< const SandeshRequest > snhRequest_
virtual void set_routing_instance(RoutingInstance *rtinstance)
static int PartitionCount()
virtual DBEntry * GetFirst()
virtual std::unique_ptr< DBEntry > AllocEntryStr(const std::string &key) const =0
const uint64_t delete_time_stamp_usecs() const
static bool StringToBool(const std::string &in_string)
std::vector< ShowRouteTable > route_table_list
const StageData * GetStageData(int stage) const
virtual int PartitionCount() const
virtual bool IsMoreSpecific(const std::string &match) const
const uint64_t GetStalePathCount() const
void BuildShowRouteTable(BgpTable *table, std::vector< ShowRoute > *route_list, int count)
DBTableBase * FindTable(const std::string &name)
static std::string BoolToString(const bool &val)
const uint64_t GetSecondaryPathCount() const
static std::string UTCUsecToString(uint64_t tstamp)