Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[Bug Fix] Resolve compilation error introduced in 20984b0bb3a1e3e5e213963d9182b1c15ba...
[simgrid.git] / src / surf / surf_routing_cluster_fat_tree.cpp
1 #include "surf_routing_cluster_fat_tree.hpp"
2
3 #include <boost/algorithm/string/split.hpp>
4 #include <boost/algorithm/string/classification.hpp>
5
6 #include <iostream>
7 #include <fstream>
8
9
10 AsClusterFatTree::AsClusterFatTree() : levels(0) {}
11
12 AsClusterFatTree::~AsClusterFatTree() {
13   for (int i = 0 ; i < this->nodes.size() ; i++) {
14     delete this->nodes[i];
15   }
16 }
17
18 void AsClusterFatTree::getRouteAndLatency(RoutingEdgePtr src,
19                                           RoutingEdgePtr dst,
20                                           sg_platf_route_cbarg_t into,
21                                           double *latency) const{
22   // TODO
23 }
24
25 /* This function makes the assumption that parse_specific_arguments() and
26  * addNodes() have already been called
27  */
28 void AsClusterFatTree::create_links(sg_platf_cluster_cbarg_t cluster) {
29
30   if(this->levels == 0) {
31     return;
32   }
33   this->nodesByLevel.resize(this->levels, 0);
34   int nodesRequired = 0;
35
36
37     for (int i = 0 ; i < this->levels ; i++) {
38       int nodesInThisLevel = 1;
39       
40       for (int j = 0 ;  j < i ; j++) {
41         nodesInThisLevel *= this->upperLevelNodesNumber[j];
42       }
43       
44       for (int j = i+1 ; j < this->levels ; j++) {
45         nodesInThisLevel *= this->lowerLevelNodesNumber[j];
46       }
47
48       this->nodesByLevel[i] = nodesInThisLevel;
49       nodesRequired += nodesInThisLevel;
50     }
51    
52     if(nodesRequired > this->nodes.size()) {
53       surf_parse_error("There is not enough nodes to fit to the described topology."
54                        " Please check your platform description (We need %d nodes, we only got %lu)",
55                        nodesRequired, this->nodes.size());
56       return;
57     }
58
59     // Nodes are totally ordered, by level and then by position, in this->nodes
60     int k = 0;
61     for (int i = 0 ; i < this->levels ; i++) {
62       for (int j = 0 ; j < this->nodesByLevel[i] ; j++) {
63         this->nodes[k]->level = i;
64         this->nodes[k]->position = j;
65       }
66     }
67
68     
69 }
70
71 void AsClusterFatTree::getLevelPosition(const int level, int &position, int &size) {
72   if (level > this->levels - 1) {
73     position = -1;
74     size =  -1;
75     return;
76   }
77   int tempPosition = 0;
78
79   for (int i = 0 ; i < level ; i++) {
80     tempPosition += this->nodesByLevel[i];
81   }
82   position = tempPosition;
83   size = this->nodesByLevel[level];
84 }
85
86 void AsClusterFatTree::addNodes(std::vector<int> const& id) {
87   for (int i = 0 ; i < id.size() ; i++) {
88     this->nodes.push_back(new FatTreeNode(id[i]));
89   }
90 }
91
92 void AsClusterFatTree::addLink(FatTreeNode *parent, FatTreeNode *child) {
93   using std::make_pair;
94   if (parent->children.size() == this->nodesByLevel[parent->level] ||
95       child->parents.size()   == this->nodesByLevel[child->level]) {
96     /* NB : This case should never happen, if this private function is not misused,
97      * so should we keep this test, keep it only for debug, throw an exception
98      * or get rid of it ? In all cases, anytime we get in there, code should be
99      * fixed
100      */
101     xbt_die("I've been asked to create a link that could not possibly exist");
102     return;
103   }
104
105   parent->children.push_back(child);
106   child->parents.push_back(parent);
107
108   // FatTreeLink *newLink;
109
110   // newLink = new FatTreeLink(parent, child, this->lowerLevelPortsNumber[parent->level]);
111   // this->links.insert(make_pair(make_pair(parent->id, child->id), newLink));
112
113   
114
115 }
116
117 void AsClusterFatTree::parse_specific_arguments(sg_platf_cluster_cbarg_t 
118                                                 cluster) {
119   std::vector<string> parameters;
120   std::vector<string> tmp;
121   boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
122  
123
124   // TODO : we have to check for zeros and negative numbers, or it might crash
125   if (parameters.size() != 4){
126     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
127                      ", see the documentation for more informations");
128     // Well, there's no doc, yet
129   }
130
131   // The first parts of topo_parameters should be the levels number
132   this->levels = std::atoi(tmp[0].c_str()); // stoi() only in C++11...
133
134   // Then, a l-sized vector standing for the childs number by level
135   boost::split(tmp, parameters[1], boost::is_any_of(","));
136   if(tmp.size() != this->levels) {
137     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
138                      ", see the documentation for more informations"); 
139   }
140   for(unsigned int i = 0 ; i < tmp.size() ; i++){
141     this->lowerLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
142   }
143   
144   // Then, a l-sized vector standing for the parents number by level
145   boost::split(tmp, parameters[2], boost::is_any_of(","));
146   if(tmp.size() != this->levels) {
147     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
148                      ", see the documentation for more informations"); 
149   }
150   for(unsigned int i = 0 ; i < tmp.size() ; i++){
151     this->upperLevelNodesNumber.push_back(std::atoi(tmp[i].c_str())); 
152   }
153   
154   // Finally, a l-sized vector standing for the ports number with the lower level
155   boost::split(tmp, parameters[3], boost::is_any_of(","));
156   if(tmp.size() != this->levels) {
157     surf_parse_error("Fat trees are defined by the levels number and 3 vectors" 
158                      ", see the documentation for more informations"); 
159     
160   }
161   for(unsigned int i = 0 ; i < tmp.size() ; i++){
162     this->lowerLevelPortsNumber.push_back(std::atoi(tmp[i].c_str())); 
163   }
164 }
165
166
167 void AsClusterFatTree::generateDotFile(const string& filename) const {
168   ofstream file;
169   /* Maybe should we get directly a char*, as open takes strings only beginning
170    * with C++11...
171    */
172   file.open(filename.c_str(), ios::out | ios::trunc); 
173   
174   if(file.is_open()) {
175     // That could also be greatly clarified with C++11
176     // std::map<std::pair<int,int>,FatTreeLink*>::iterator iter;
177     // file << "graph AsClusterFatTree {\n";
178     // for (iter = this->links.begin() ; iter != this->links.end() ; iter++ ) {
179     //   for (int j = 0 ; j < iter->second->ports ; j++) {
180     //     file << iter->second->source->id 
181     //          << " -- " 
182     //          << iter->second->destination->id
183     //          << ";\n";
184     //   }
185     //}
186     file << "}";
187     file.close();
188   }
189   else {
190     std::cerr << "Unable to open file " << filename << std::endl;
191     return;
192   }
193 }
194
195 FatTreeNode::FatTreeNode(int id, int level, int position) : id(id),
196                                                             level(level),
197                                                             position(position){}
198
199 // FatTreeLink::FatTreeLink(FatTreeNode *source, FatTreeNode *destination,
200 //                          int ports) : source(source), destination(destination),
201 //                                       ports(ports) {
202   
203 // }