/
Node.hpp
executable file
·729 lines (499 loc) · 21.3 KB
/
Node.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
/* To do
attach_after seek new routers
check acceptability criteria to accept a node in router
Manage routing table size
bootstrap to more than one node
*/
//#include "Allheader.hpp"
#ifndef NODE_HPP
#define NODE_HPP
#include "ForwardDeclaration.hpp"
#include "Infrastructure.hpp"
//#include "Input.hpp"
/*
typedef std::map<Tag, std::list<ResourceNode*> > RoutingTable ;
typedef std::list<ResourceNode*> RoutingTableRow ;
typedef RoutingTable::iterator RoutingTableIterator ;
typedef RoutingTableRow::iterator RoutingTableRowIterator ;
*/
//*************These are for trimming routing table and known routers list *********************
inline bool greater_than(std::multiset< int > multiset1, std::multiset< int > multiset2){
std::multiset< int >::iterator multiset1_itr = multiset1.begin(), multiset2_itr = multiset2.begin();
int fi,fj;
for ( fi = multiset1.size(),fj = multiset2.size(); fi>0 && fj>0 ;fi--,fj--)
{
if (*multiset1_itr == *multiset2_itr)
{
multiset1_itr++ , multiset2_itr++;
}
else {
//return *multiset1_itr < *multiset2_itr ; //ascending
return *multiset1_itr > *multiset2_itr ;//descending
}
}
//Haven't returned yet and the foor loop exited, so that means the two input multiset have equal entries atleast the common portions
//return (fi<fj);//asecending
return (fi>fj);//descending
};
inline bool greater_than_strict(std::multiset< int > multiset1, std::multiset< int > multiset2, unsigned int id1, unsigned int id2){
std::multiset< int >::iterator multiset1_itr = multiset1.begin(), multiset2_itr = multiset2.begin();
int fi,fj;
for ( fi = multiset1.size(),fj = multiset2.size(); fi>0 && fj>0 ;fi--,fj--)
{
if (*multiset1_itr == *multiset2_itr)
{
multiset1_itr++ , multiset2_itr++;
}
else {
//return *multiset1_itr < *multiset2_itr ; //ascending
return *multiset1_itr > *multiset2_itr ;//descending
}
}
//Haven't returned yet and the foor loop exited, so that means the two input multiset have equal entries atleast the common portions
if (fi==fj)
{
//If they are equal, that means the relevance multiset is exactly the same, in that case we need to enforce stricter ordering based on node ids
return id1> id2; //Descending
}
//return (fi<fj);//asecending
return (fi>fj);//descending
};
//if return is 0 then neither greater or equal, if returned 1 then equal, if 2 then greater
inline int equal_and_greater(std::multiset< int > multiset1, std::multiset< int > multiset2){
std::multiset< int >::iterator multiset1_itr = multiset1.begin(), multiset2_itr = multiset2.begin();
int fi,fj;
for ( fi = multiset1.size(),fj = multiset2.size(); fi>0 && fj>0 ;fi--,fj--)
{
if (*multiset1_itr == *multiset2_itr)
{
multiset1_itr++ ; multiset2_itr++;
}
else {
return ((*multiset1_itr > *multiset2_itr) ? 2 : (*multiset1_itr == *multiset2_itr)? 1 : 0) ;
}
}
return (fi < fj) ? 0: (fi > fj) ? 2: 1;
};
//*************Above these are for trimming routing table and known routers list *********************
//class QueryHandler:public Handler {
class QueryHandler {
public:
#ifdef DEBUG
ResourceNode *parent_node_ptr; //Update this
//Infrastructure *If_ptr;
#endif
//int expired;
Response *response_to_send_ptr;
Query *query_to_send_ptr;
QueryHandler();
/*
#ifdef DEBUG
QueryHandler(Infrastructure *passed_If_ptr);
#endif
*/
//~QueryHandler();
void transmit_response();
void transmit_query();
};
class Node {
public:
unsigned int id;
QueryHandler *query_handler_ptr;
Listener *listener_ptr;
Event *handler_schedule_event_ptr;
Infrastructure *If_ptr;
NodeType node_type;
Node(Infrastructure* passed_If_ptr);
virtual void heartbeat(){};
virtual ~Node(){};
};
class ResourceNode:public Node {
public:
//unsigned int num_elements;
unsigned int num_elements1;
unsigned int num_queries_to_submit_per_period;
#ifdef DEBUG
unsigned int listener_seq_id; //For troubleshooting
#endif
std::vector< std::vector<int> > *all_distances_ptr;
unsigned int *num_vertices_at_onto_ptr ;
//int description_matched;
Query *query_ptr;
Response *response_ptr;
//std::list<Tag>* neighboring_tags_ptr;
BootstrapNodeList bootstrap_nodes;
Tag *tag_to_use_for_query_ptr;
//int *current_query_sequence_id_ptr;
SpecificFunctor<QueryHandler> *functor_handler_ptr;
SpecificFunctor<Listener> *functor_listener_ptr;
std::list<Query*> query_bag_for_advertising;
//bool query_with_tag_does_not_exist;
std::list<Query*>::iterator query_itr;
Description::iterator description_itr;
std::map<unsigned int, Listener*> listener_array;
std::map< unsigned int, RouterNode *> known_routers;
std::map<unsigned int,Listener*>::iterator listener_itr, listener_to_remove_itr;
std::map< unsigned int, RouterNode *>::iterator router_node_address_itr;
RouterNode *router_node_to_attach_to_ptr;
//std::list<QueryHandler*> query_handler_array;
//std::list<QueryHandler*>::iterator query_handler_itr, query_handler_to_remove_itr;
//void drop_expired_listeners();
void attach_listener(Listener &listener, unsigned int query_sequence_id);
//void attach_query_handler(QueryHandler *passed_query_handler_ptr);
//void drop_expired_query_handlers();
void seek_new_routers_to_attach_to();
//void update_query_bag_for_advertising();
void update_query_bag(Description &from_description, std::list<Query*> &to_query_bag);
int verify_against_description(Query &submitted_query);
void response_action(Query &query_to_handle);
virtual void handle_recvd_response(Response *curr_response_ptr);
virtual void update_routing_table_action(Response *curr_response_ptr){};//=0;
virtual int attach_request(ResourceNode* passed_node_ptr){};//=0;Added to avoid dynamic cast
void ResourceNode::send_queries_from(std::list<Query*> &query_bag , std::list<Query*>::iterator &curr_query_bag_itr, int num_queries_to_send );
virtual bool can_accept_message(Message &submitted_message);
unsigned int vitality;
unsigned int extroversion;
Tick delay;
Description description;
unsigned int message_time_to_live;
//unsigned int routing_table_capacity;
unsigned int current_query_sequence_id;
Tick response_timeout;
ResourceNode(unsigned int passed_message_time_to_live,
NodeType node_type_to_pass_on,
int known_routers_floor,
int known_routers_trim_threshold,
int known_routers_capacity,
int translation_radius,
int routing_table_length_floor,
int routing_table_length_trim_threshold,
int routing_table_max_length,
int routing_table_width_floor,
int routing_table_width_threshold,
int routing_table_min_num_resource_nodes,
int routing_table_max_width,
int passed_k, int passed_num_centroid_tags_to_explore_per_period,
int passed_num_queries_to_submit_per_period,
Description &passed_description, unsigned int passed_id, unsigned int passed_vitality, int passed_extroversion,
Tick passed_delay,
Tick passed_response_timeout, BootstrapNodeList &passed_bootstrap_nodes,
Infrastructure* passed_If_ptr );
void begin_life(/*BootstrapNodeList &bootstrap_nodes*/);
virtual void bootstrap_action();
void heartbeat();
void submit_response(Response &submitted_response);
virtual void submit_query(Query &submitted_query);
virtual void periodic_housekeeping();//{}; Activated housekeeping for resource node also
void cleanup();
#ifdef DEBUG
void print_query(Query &submitted_query);
void print_listener_status();
#endif
~ResourceNode();
//*************These are for trimming routing table and known routers list *********************
int known_routers_floor;
int known_routers_trim_threshold;
int known_routers_capacity;
int translation_radius;
ResourceNode *this_ptr;
RouterNode *curr_router_ptr;
KnownRoutersIndexEncapsulator *known_routers_index_ptr;
//void *known_routers_index_itr_ptr;
std::multiset< int > relevance( Tag tag1){
std::multiset< int > temp_multiset;
description_itr = description.begin();
for (int fi= description.size();fi>0 ;fi--, description_itr++ )
temp_multiset.insert( ((*all_distances_ptr)[*description_itr][tag1] ));
return temp_multiset;
};
std::multiset<int > relevance( Description description2){
std::multiset< int > temp_multiset;
Description::iterator description2_itr;
description_itr = description.begin();
for (int fi= description.size();fi>0 ;fi--, description_itr++ )
{
description2_itr = description2.begin();
for (int fj= description2.size();fj>0 ;fj--, description2_itr++ )
{
temp_multiset.insert( ((*all_distances_ptr)[*description_itr][*description2_itr] ));
}
}
return temp_multiset;
};
void trim_known_routers();
//*************Above these are for trimming routing table and known routers list *********************
};
//Copy from here
class routing_table_rows_greater_than {
public:
ResourceNode *parent_ptr;
routing_table_rows_greater_than(ResourceNode *passed_parent_ptr):parent_ptr(passed_parent_ptr){};//parent_ptr= passed_parent_ptr;};
bool operator()(Tag tag1, Tag tag2) //const
{
return greater_than((*parent_ptr).relevance( tag1), (*parent_ptr).relevance( tag2));
}
};
/*
class routing_table_cols_greater_than {
public:
ResourceNode *parent_ptr;
routing_table_cols_greater_than(ResourceNode *passed_parent_ptr):parent_ptr(passed_parent_ptr){};//{parent_ptr =passed_parent_ptr;};
bool operator()(ResourceNode* ResourceNode_ptr1, ResourceNode* ResourceNode_ptr2) //const
{
return greater_than((*parent_ptr).relevance( ResourceNode_ptr1->description ), (*parent_ptr).relevance( ResourceNode_ptr2->description ));
}
};
*/
class routing_table_cols_greater_than_strict {
public:
ResourceNode *parent_ptr;
routing_table_cols_greater_than_strict(ResourceNode *passed_parent_ptr):parent_ptr(passed_parent_ptr){};//{parent_ptr =passed_parent_ptr;};
bool operator()(ResourceNode* ResourceNode_ptr1, ResourceNode* ResourceNode_ptr2) //const
{
return greater_than_strict((*parent_ptr).relevance( ResourceNode_ptr1->description ), (*parent_ptr).relevance( ResourceNode_ptr2->description ),
ResourceNode_ptr1->id, ResourceNode_ptr2->id);
}
};
//Old ones from ver 1.15
/*
typedef std::multiset<ResourceNode* > Destinations;
typedef std::map<Tag, RoutingTableRow* > RoutingTable ;
//typedef RoutingTableRow::iterator RoutingTableRowIterator;
typedef RoutingTable::iterator RoutingTableIterator ;
typedef Destinations::iterator RoutingTableRowIterator;
*/
//*************These are for trimming routing table and known routers list *********************
//typedef std::multiset<ResourceNode* , routing_table_cols_greater_than > Destinations;
typedef std::set<ResourceNode* , routing_table_cols_greater_than_strict > Destinations;
class RoutingTableRow {
public:
Destinations destinations;
unsigned int num_resource_nodes;
RoutingTableRow(ResourceNode* this_ptr) : destinations( (routing_table_cols_greater_than_strict(this_ptr)) ) {num_resource_nodes = 0;};
void insert(ResourceNode* &res_ptr) { destinations.insert(res_ptr); }
};
typedef std::map<Tag, RoutingTableRow* > RoutingTable ; //New
typedef std::multiset<Tag , routing_table_rows_greater_than > RoutingTableIndex ; //new
typedef Destinations::iterator RoutingTableRowIterator;
typedef RoutingTable::iterator RoutingTableIterator ;
typedef RoutingTableIndex::iterator RoutingTableIndexIterator ; //New
//*************Above these are for trimming routing table and known routers list *********************
class UserNode:public ResourceNode {
std::set<unsigned int> index_of_nodes_to_bootstrap_to;
Tag generated_random_tag;
unsigned int generated_random_index;
//RouterNode *generated_random_bootstrap_node_ptr;
public:
UserNode(unsigned int passed_message_time_to_live,
NodeType node_type_to_pass_on,
int known_routers_floor,
int known_routers_trim_threshold,
int known_routers_capacity,
int translation_radius,
int routing_table_length_floor,
int routing_table_length_trim_threshold,
int routing_table_max_length,
int routing_table_width_floor,
int routing_table_width_threshold,
int routing_table_min_num_resource_nodes,
int routing_table_max_width,
int passed_k, int passed_num_centroid_tags_to_explore_per_period,
int passed_num_queries_to_submit_per_period,
Description &passed_description, unsigned int passed_id, unsigned int passed_vitality, int passed_extroversion,
Tick passed_delay,
Tick passed_response_timeout, BootstrapNodeList &passed_bootstrap_nodes,
Infrastructure* passed_If_ptr);
void bootstrap_action(){};
void generate_random_description(unsigned int num_description);
void generate_random_bootstrap_nodes(unsigned int num_bootstrap_nodes) ;
void heartbeat();
void handle_recvd_response(Response *curr_response_ptr);
~UserNode(){ index_of_nodes_to_bootstrap_to.clear();cleanup(); };
};
#ifdef DUPPACK_CACHE
class Message_key {
public:
//unsigned int id;
//unsigned int seq_num;
std::pair<unsigned int, unsigned int> key;
Tick time_to_expire;
Message_key(){key.first =0;key.second =0;time_to_expire=0; };
Message_key(const Message_key& passed_message_key){
key = passed_message_key.key;
//id = passed_message_key.id;
//seq_num = passed_message_key.seq_num;
time_to_expire = passed_message_key.time_to_expire;
};
Message_key(unsigned int passed_id,unsigned int passed_seq_num, Tick passed_time_to_expire){
//id = passed_id;
//seq_num = passed_seq_num;
key = make_pair( passed_id, passed_seq_num);
time_to_expire = passed_time_to_expire;
};
friend bool operator==(const Message_key& k1,const Message_key& k2){
//return k1.id==k2.id && k1.seq_num==k2.seq_num;
return k1.key == k2.key;
}
friend bool operator!=(const Message_key& k1,const Message_key& k2){
//return k1.id!=k2.id || k1.seq_num!=k2.seq_num;
return k1.key != k2.key;
}
friend bool operator>(const Message_key& k1,const Message_key& k2){
//return k1.id>k2.id ;
//return k1.seq_num>k2.seq_num ;
return k1.key>k2.key;
}
friend bool operator<(const Message_key& k1,const Message_key& k2){
// return k1.id<k2.id ;
// return k1.seq_num<k2.seq_num ;
return k1.key<k2.key;
}
};
#endif
class RouterNode:public ResourceNode {
private:
std::list<Tag> nearest_k;
std::list<Tag>::iterator nearest_k_itr;
unsigned int routing_table_size;
//std::list<ResourceNode*> *routing_table_row_obj_ptr;
//std::list<ResourceNode*> routing_table_row_obj;
RoutingTableRow *routing_table_row_obj_ptr;
std::map< unsigned int, RouterNode *> routers_attached;
std::map< unsigned int, ResourceNode *> resources_attached;
std::list<Query*> query_bag_for_exploring;
std::list<Query*>::iterator curr_query_bag_for_exploring_itr;
//std::list<Query*>::reverse_iterator query_rev_itr;
std::list<Query*> temp_query_bag_for_exploring;
std::vector<Tag> knowledge;
//std::list<ResourceNode*>::iterator routing_table_entry_itr; //From QueryHandler
RoutingTableRowIterator routing_table_entry_itr; //From QueryHandler
Description descriptions_to_explore;
Description temp_descriptions_to_explore;
unsigned int num_centroid_tags_to_explore_per_period;
Description::iterator description_budget_itr;//Has memory and tracks from which centroid topic to start again
unsigned int semantic_space_inner_radius;
//For duplicate message testing
#ifdef DUPPACK_SET
QueryAlreadyReceived query_already_received_set;
QueryAlreadyReceived::iterator query_already_received_set_itr;
NodeId_QuerySeqNum query_key;
#endif
#ifdef DUPPACK_CACHE
std::set<Message_key> message_key_cache;
std::set<Message_key>::iterator message_key_cache_itr;//, message_key_to_remove_itr ;
Message_key message_key;
#endif
void update_descriptions_to_explore();
void seek_new_resources_to_update_routing_table();
//void free_space_in_routing_table();
int can_accept(Node* passed_node_ptr);
void selective_multicast_action(Query &query_to_handle);
bool can_accept_message(Message &submitted_message);
//OntologyRepository services
void generate_nearest_neighbors(Tag focus_vertice /*, int k, const std::vector<Tag> &neighbors, std::list<Tag> &nearest_k*/);
void generate_neighbors_to_explore(Tag focus_vertice , int radius /*, std::list<Tag> &nearest_k*/);
void generate_new_neighbors_to_explore(Tag focus_vertice , int inner_radius, int radius_increment /*, std::list<Tag> &nearest_k */);//From Suneil
int distance(Tag vertice1, Tag vertice2);
public:
//RoutingTable routing_table;
RoutingTable routing_table;
unsigned int k;
//unsigned int routing_table_capacity; //Moved to ResourceNode
RouterNode(unsigned int passed_message_time_to_live,
NodeType node_type_to_pass_on,
int known_routers_floor,
int known_routers_trim_threshold,
int known_routers_capacity,
int translation_radius,
int routing_table_length_floor,
int routing_table_length_trim_threshold,
int routing_table_max_length,
int routing_table_width_floor,
int routing_table_width_threshold,
int routing_table_min_num_resource_nodes,
int routing_table_max_width,
int passed_k, int passed_num_centroid_tags_to_explore_per_period,
int passed_num_queries_to_submit_per_period,
Description &passed_description, unsigned int passed_id, unsigned int passed_vitality, int passed_extroversion,
Tick passed_delay,
Tick passed_response_timeout, BootstrapNodeList &passed_bootstrap_nodes,
Infrastructure* passed_If_ptr);
void heartbeat();
void submit_query(Query &submitted_query);
int attach_request(ResourceNode* passed_node_ptr);
bool routing_filter( ResourceNode *resource_node_entry_in_routing_table_ptr, Query &query_to_route );
void periodic_housekeeping();
void update_routing_table_action(Response *curr_response_ptr);
~RouterNode();
#ifdef DEBUG_L2
void print_routing_table();
void print_nearest_k();
void RouterNode::print_routing_table_index();
void print_destinations(Destinations &destinations);
#endif
//*************These are for trimming routing table and known routers list *********************
std::vector<Tag>::iterator knowledge_itr;
int routing_table_length_floor;
int routing_table_length_trim_threshold;
int routing_table_max_length;
int routing_table_width_floor;
int routing_table_width_threshold;
int routing_table_min_num_resource_nodes;
int routing_table_max_width;
RoutingTableIndex routing_table_index;
RoutingTableIterator routing_table_itr ;
RoutingTableIndexIterator routing_table_index_itr ;//New
//RoutingTableRowIterator routing_table_entry_to_remove_itr;
RouterNode(Infrastructure *passed_If_ptr);
void trim_routing_table_length();
//void trim_routing_table_specific_width(Destinations &destinations_to_trim);
void trim_routing_table_specific_width(RoutingTableRow* row_to_trim_ptr);
void trim_routing_table_all_widths();
};
class KnownRouterIndexElement {
public:
RouterNode *RouterNode_ptr;
unsigned int id;
unsigned int performance;
//Ticks birth_ticks;
unsigned int birth_ticks;
KnownRouterIndexElement(RouterNode *passed_RouterNode_ptr );
};
class known_routers_index_less_than {
public:
ResourceNode *parent_ptr;
known_routers_index_less_than (ResourceNode *passed_parent_ptr):parent_ptr(passed_parent_ptr){};//parent_ptr= passed_parent_ptr;};
bool operator()(KnownRouterIndexElement* element_ptr1, KnownRouterIndexElement* element_ptr2){
switch (equal_and_greater( (*(element_ptr1->RouterNode_ptr)).relevance( (*parent_ptr).description ), (*(element_ptr2->RouterNode_ptr)).relevance( (*parent_ptr).description ) ) )
{
case 0:
return 0;
break;
case 1:
return (element_ptr1->birth_ticks < element_ptr2->birth_ticks) ? 1 : 0;
break;
case 2:
return 1;
}
}
};
typedef std::multiset< KnownRouterIndexElement*, known_routers_index_less_than > KnownRoutersIndex;
typedef KnownRoutersIndex::iterator KnownRoutersIndexIterator;
//class KnownRoutersIndexIterator: public KnownRoutersIndex::iterator;
class KnownRoutersIndexEncapsulator {
KnownRouterIndexElement* index_element_ptr;
public:
KnownRoutersIndex index;
KnownRoutersIndexEncapsulator(ResourceNode* passed_ResourceNode_ptr):index(( known_routers_index_less_than(passed_ResourceNode_ptr) )){};
void insert(RouterNode* RouterNode_ptr){
index_element_ptr = new KnownRouterIndexElement(RouterNode_ptr /*,RouterNode_ptr->If_ptr->scheduler_ptr->now()*/);
index.insert(index_element_ptr);
}
int size(){ int temp; temp = index.size(); return temp; }
//KnownRoutersIndex::iterator begin(){return index.begin();}
KnownRoutersIndexIterator begin(){return index.begin();}
void erase(KnownRoutersIndexIterator &start_itr, KnownRoutersIndexIterator &end_itr){
index.erase(start_itr, end_itr);
}
};
#endif