00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ordertree.h"
00015
00016 #include <boost/interprocess/managed_shared_memory.hpp>
00017 #include <boost/interprocess/containers/string.hpp>
00018
00019 #include <log4cpp/Category.hh>
00020 #include <algorithm>
00021 #include <string>
00022
00023
00024
00025
00026
00027 class OrderTree::DFSVotingVisitor : public boost::default_dfs_visitor {
00028 public:
00029
00030
00031
00032
00033
00034 explicit DFSVotingVisitor(OrderGraphType *tree): tree_(tree) {}
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 template < typename Vertex, typename Graph >
00046 void finish_vertex(Vertex u, const Graph & g) {
00047
00048
00049 int attackVotes = 0;
00050 int retreatVotes = 0;
00051
00052 OrderVertex* order_vertex = &((*tree_)[u]);
00053
00054
00055
00056
00057 OrderNodeIteratorType vi, vend;
00058 tie(vi, vend) = adjacent_vertices(u, g);
00059
00060 if (vi == vend) {
00061
00062
00063 const LocalOrder local_order = order_vertex->local_order;
00064
00065 const MarchingOrders::type leaf_orders =
00066 (*local_order).marching_orders;
00067
00068 assert(leaf_orders == MarchingOrders::kAttack ||
00069 leaf_orders == MarchingOrders::kRetreat);
00070
00071
00072 leaf_orders == MarchingOrders::kAttack ?
00073 ++attackVotes :
00074 ++retreatVotes;
00075 } else {
00076
00077
00078
00079 for (; vi != vend; ++vi) {
00080 OrderVertex child_order_vertex = g[*vi];
00081
00082 const MarchingOrders::type child_orders =
00083 child_order_vertex.child_majority_marching_orders;
00084
00085 assert(child_orders == MarchingOrders::kAttack ||
00086 child_orders == MarchingOrders::kRetreat);
00087
00088 child_orders == MarchingOrders::kAttack ?
00089 ++attackVotes :
00090 ++retreatVotes;
00091 }
00092 }
00093
00094 if (attackVotes < retreatVotes) {
00095 order_vertex->child_majority_marching_orders =
00096 MarchingOrders::kRetreat;
00097 } else {
00098
00099
00100
00101
00102
00103 order_vertex->child_majority_marching_orders =
00104 MarchingOrders::kAttack;
00105 }
00106 }
00107
00108 private:
00109
00110
00111
00112 OrderGraphType *tree_;
00113 };
00114
00115
00116
00117
00118
00119 class OrderTree::OrderVertexWriter {
00120 public:
00121
00122
00123
00124
00125
00126 explicit OrderVertexWriter(const OrderGraphType &g)
00127 : writer_order_tree(g) {}
00128
00129
00130
00131
00132 ~OrderVertexWriter() {}
00133
00134
00135
00136
00137
00138
00139
00140
00141 template <class Vertex>
00142 void operator() (std::ostream &out, Vertex u) {
00143 namespace bi = boost::interprocess;
00144
00145 const OrderVertex* order_vertex = &(writer_order_tree[u]);
00146
00147 const LocalOrder local_order = order_vertex->local_order;
00148
00149 const MarchingOrders::type marching_orders =
00150 (*local_order).marching_orders;
00151
00152 const bi::string kCommunicationPath =
00153 (*local_order).CommunicationPathToString();
00154
00155 const bi::string kMarchingOrder =
00156 Order::MarchingOrderTypeToString(marching_orders);
00157
00158 const bi::string kChildMarchingOrder =
00159 Order::MarchingOrderTypeToString(
00160 order_vertex->child_majority_marching_orders);
00161
00162 const bool kTraitorInPath =
00163 order_vertex->comm_path_contains_traitor;
00164
00165
00166
00167
00168 const bi::string fillcolor =
00169 kTraitorInPath ? "pink" : "white";
00170
00171 out << "[label=\"" << kCommunicationPath << "\\n"
00172 << "Rx: " << kMarchingOrder << "\\n"
00173 << "Vote: " << kChildMarchingOrder << "\" "
00174 << "fillcolor=\"" << fillcolor << "\" "
00175 << "style=filled"
00176 << "]";
00177 }
00178
00179
00180 private:
00181
00182
00183
00184 const OrderGraphType &writer_order_tree;
00185 };
00186
00187 OrderTree::OrderTree(const char* kLogCategoryName,
00188 const char* kSharedMemName,
00189 const char* kTraitorSetName)
00190 : log_(log4cpp::Category::getInstance(kLogCategoryName)) {
00191 namespace bi = boost::interprocess;
00192
00193 root_node_id_ = boost::graph_traits<OrderGraphType>::null_vertex();
00194
00195
00196
00197 order_tree_ = new OrderGraphType();
00198 assert(order_tree_ != NULL);
00199
00200 bi::managed_shared_memory segment(bi::open_only, kSharedMemName);
00201
00202 traitor_set_ = segment.find<SharedMemoryUIntSet>(kTraitorSetName).first;
00203 assert(traitor_set_ != NULL);
00204 }
00205
00206 OrderTree::~OrderTree() {
00207 if (order_tree_ != NULL) {
00208 delete order_tree_;
00209 order_tree_ = NULL;
00210 }
00211 }
00212
00213 MarchingOrders::type OrderTree::FinalizeOrders() {
00214 assert(root_node_id_ != boost::graph_traits<OrderGraphType>::null_vertex());
00215
00216
00217 DFSVotingVisitor vis(order_tree_);
00218 depth_first_search(*order_tree_, visitor(vis));
00219
00220
00221
00222 const OrderVertex* root_order_vertex = &((*order_tree_)[root_node_id_]);
00223 const LocalOrder root_local_order = root_order_vertex->local_order;
00224
00225 return root_order_vertex->child_majority_marching_orders;
00226 }
00227
00228 void OrderTree::PrintTree(const char* outfile) const {
00229 log_.infoStream() << "Writing " << std::string(outfile);
00230
00231 std::ofstream ofs(outfile);
00232 write_graphviz(ofs, *order_tree_, OrderVertexWriter(*order_tree_));
00233 }
00234
00235 unsigned int OrderTree::EdgeCount() const {
00236 return num_edges(*order_tree_);
00237 }
00238
00239 unsigned int OrderTree::NodeCount() const {
00240 return num_vertices(*order_tree_);
00241 }
00242
00243 OrderTree::OrderNodeIDType OrderTree::AddVertex(
00244 const OrderNodeIDType parent_node_id,
00245 const LocalOrder kChildOrder,
00246 const MarchingOrders::type kMarchingOrders,
00247 const bool kCommPathContainsTraitor) {
00248
00249 assert(order_tree_ != NULL);
00250
00251
00252 const OrderNodeIDType child_node_id = add_vertex(*order_tree_);
00253 assert(child_node_id != boost::graph_traits<OrderGraphType>::null_vertex());
00254
00255
00256 OrderVertex* child_vertex = &((*order_tree_)[child_node_id]);
00257
00258
00259 child_vertex->local_order = kChildOrder;
00260 child_vertex->child_majority_marching_orders = kMarchingOrders;
00261 child_vertex->comm_path_contains_traitor = kCommPathContainsTraitor;
00262
00263 if (parent_node_id != boost::graph_traits<OrderGraphType>::null_vertex()) {
00264
00265 add_edge(parent_node_id, child_node_id, *order_tree_);
00266 }
00267
00268
00269 return child_node_id;
00270 }
00271
00272 int OrderTree::Add(const LocalOrder kOrderToAdd) {
00273
00274 assert(order_tree_ != NULL);
00275
00276 if (NodeCount() > 0) {
00277
00278
00279
00280 assert((*kOrderToAdd).communication_path.size() > 1);
00281 assert(root_node_id_ !=
00282 boost::graph_traits<OrderGraphType>::null_vertex());
00283
00284 return Add(root_node_id_,
00285 kOrderToAdd,
00286 ((*order_tree_)[root_node_id_]).comm_path_contains_traitor);
00287 }
00288
00289
00290
00291
00292 assert((*kOrderToAdd).communication_path.size() == 1);
00293
00294 const unsigned int kLastGeneral = (*kOrderToAdd).communication_path.back();
00295 bool comm_path_contains_traitor = TraitorSetContains(kLastGeneral);
00296
00297
00298 assert(root_node_id_ == boost::graph_traits<OrderGraphType>::null_vertex());
00299
00300 root_node_id_ =
00301 AddVertex(boost::graph_traits<OrderGraphType>::null_vertex(),
00302 kOrderToAdd,
00303 MarchingOrders::kInvalid,
00304 comm_path_contains_traitor);
00305
00306 return 0;
00307 }
00308
00309 bool OrderTree::TraitorSetContains(const unsigned int kGeneralID) const {
00310 bool contains_traitor = false;
00311
00312
00313 assert(traitor_set_ != NULL);
00314
00315
00316 if (traitor_set_->find(kGeneralID) != traitor_set_->end()) {
00317 contains_traitor = true;
00318 }
00319
00320 return contains_traitor;
00321 }
00322
00323 bool OrderTree::PrefixMatches(const LocalOrder left_order,
00324 const LocalOrder right_order) const {
00325
00326
00327
00328
00329
00330
00331
00332
00333 SharedMemoryUIntList::const_iterator first1 =
00334 (*left_order).communication_path.begin();
00335
00336 SharedMemoryUIntList::const_iterator last1 =
00337 (*left_order).communication_path.end();
00338
00339 SharedMemoryUIntList::const_iterator first2 =
00340 (*right_order).communication_path.begin();
00341
00342 return equal(first1, last1, first2);
00343 }
00344
00345 int OrderTree::Add(const OrderNodeIDType kParentNodeID,
00346 const LocalOrder kOrderToAdd,
00347 bool traitor_in_path) {
00348 const LocalOrder kParentOrder = (*order_tree_)[kParentNodeID].local_order;
00349
00350 if (PrefixMatches(kParentOrder, kOrderToAdd) == true &&
00351 ((*kOrderToAdd).communication_path.size() - 1) ==
00352 ((*kParentOrder).communication_path.size())) {
00353
00354
00355
00356 if (traitor_in_path == false) {
00357
00358
00359 const unsigned int kLastGeneral =
00360 (*kOrderToAdd).communication_path.back();
00361 traitor_in_path = TraitorSetContains(kLastGeneral);
00362 }
00363
00364 AddVertex(kParentNodeID,
00365 kOrderToAdd,
00366 MarchingOrders::kInvalid,
00367 traitor_in_path);
00368
00369
00370 return 1;
00371 } else {
00372
00373
00374
00375
00376
00377
00378
00379
00380 OrderNodeIteratorType vi, vend;
00381
00382 for (tie(vi, vend) = adjacent_vertices(kParentNodeID, *order_tree_);
00383 vi != vend;
00384 ++vi) {
00385 const LocalOrder child_node_order = (*order_tree_)[*vi].local_order;
00386
00387 if (PrefixMatches(child_node_order, kOrderToAdd) == true) {
00388
00389
00390
00391 if (traitor_in_path == false) {
00392
00393
00394
00395 const unsigned int kLastGeneral =
00396 (*child_node_order).communication_path.back();
00397 traitor_in_path = TraitorSetContains(kLastGeneral);
00398 }
00399
00400
00401 return Add(*vi, kOrderToAdd, traitor_in_path) + 1;
00402 }
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411 log_.errorStream()
00412 << "Unable to find where to insert: '"
00413 << (*kOrderToAdd).CommunicationPathToString()
00414 << "' creating error.dot.";
00415 PrintTree("error.dot");
00416 assert(false);
00417
00418
00419 return -1;
00420 }
00421