Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[simgrid.git] / src / instr / jedule / jedule_platform.cpp
1 /* Copyright (c) 2010-2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "simgrid/jedule/jedule.hpp"
8 #include "simgrid/jedule/jedule_platform.hpp"
9 #include "simgrid/s4u/As.hpp"
10
11 #include "xbt/asserts.h"
12 #include "xbt/dynar.h"
13 #include <algorithm>
14
15 #if HAVE_JEDULE
16
17 namespace simgrid {
18 namespace jedule {
19 Subset::Subset(int start_idx, int end_idx, Container* parent)
20 : start_idx(start_idx), parent(parent)
21 {
22   nres=end_idx-start_idx+1;
23 }
24
25
26 Container::Container(std::string name): name(name)
27 {
28   container_name2container.insert({this->name, this});
29 }
30
31 Container::~Container()
32 {
33   if(!this->children.empty())
34     for (auto child: this->children)
35       delete child;
36 }
37
38 void Container::addChild(jed_container_t child)
39 {
40   xbt_assert(this != nullptr);
41   xbt_assert(child != nullptr);
42   this->children.push_back(child);
43   child->parent = this;
44 }
45
46 void Container::addResources(std::vector<sg_host_t> hosts)
47 {
48   this->is_lowest = 1;
49   this->children.clear();
50   this->last_id = 0;
51
52   //FIXME do we need to sort?: xbt_dynar_sort_strings(host_names);
53
54   for (auto host : hosts) {
55     const char *host_name = sg_host_get_name(host);
56     this->name2id.insert({host_name, this->last_id});
57     (this->last_id)++;
58     host2_simgrid_parent_container.insert({host_name, this});
59     this->resource_list.push_back(host);
60   }
61 }
62
63 void Container::createHierarchy(AS_t from_as)
64 {
65   xbt_dict_cursor_t cursor = nullptr;
66   char *key;
67   AS_t elem;
68   xbt_dict_t routing_sons = from_as->children();
69
70   if (xbt_dict_is_empty(routing_sons)) {
71     // I am no AS
72     // add hosts to jedule platform
73     xbt_dynar_t table = from_as->hosts();
74     unsigned int dynar_cursor;
75     sg_host_t host;
76
77     std::vector<sg_host_t> hosts;
78
79     xbt_dynar_foreach(table, dynar_cursor, host) {
80       hosts.push_back(host);
81     }
82     this->addResources(hosts);
83     xbt_dynar_free(&table);
84   } else {
85     xbt_dict_foreach(routing_sons, cursor, key, elem) {
86       jed_container_t child_container = new simgrid::jedule::Container(std::string(elem->name()));
87       this->addChild(child_container);
88       child_container->createHierarchy(elem);
89     }
90   }
91 }
92
93 std::vector<int> Container::getHierarchy()
94 {
95   xbt_assert( this!= nullptr );
96
97   if(this->parent != nullptr ) {
98
99     if(!this->parent->children.empty()) {
100       // we are in the last level
101       return this->parent->getHierarchy();
102     } else {
103       unsigned int i =0;
104       int child_nb = -1;
105
106       for (auto child : this->parent->children) {
107         if( child == this) {
108           child_nb = i;
109           break;
110         }
111         i++;
112       }
113
114       xbt_assert( child_nb > - 1);
115       std::vector<int> heir_list = this->parent->getHierarchy();
116       heir_list.insert(heir_list.begin(), child_nb);
117       return heir_list;
118     }
119   } else {
120     int top_level = 0;
121     std::vector<int> heir_list = {top_level};
122     return heir_list;
123   }
124 }
125
126 std::string Container::getHierarchyAsString()
127 {
128   std::string output("");
129
130   std::vector<int> heir_list = this->getHierarchy();
131
132   unsigned int length = heir_list.size();
133   unsigned int i = 0;
134   for (auto id : heir_list) {
135     output += std::to_string(id);
136     if( i != length-1 ) {
137       output += ".";
138     }
139   }
140
141   return output;
142 }
143
144 void Container::printResources(FILE * jed_file)
145 {
146   unsigned int i=0;
147   xbt_assert(!this->resource_list.empty());
148
149   unsigned int res_nb = this->resource_list.size();
150   std::string resid = this->getHierarchyAsString();
151
152   fprintf(jed_file, "      <rset id=\"%s\" nb=\"%u\" names=\"", resid.c_str(), res_nb);
153   for (auto res: this->resource_list) {
154     const char * res_name = sg_host_get_name(res);
155     fprintf(jed_file, "%s", res_name);
156     if( i != res_nb-1 ) {
157       fprintf(jed_file, "|");
158     }
159     i++;
160   }
161   fprintf(jed_file, "\" />\n");
162 }
163
164 void Container::print(FILE* jed_file)
165 {
166   xbt_assert( this != nullptr );
167   fprintf(jed_file, "    <res name=\"%s\">\n", this->name.c_str());
168   if( !this->children.empty()){
169     for (auto child: this->children) {
170       child->print(jed_file);
171     }
172   } else {
173     this->printResources(jed_file);
174   }
175   fprintf(jed_file, "    </res>\n");
176 }
177
178 }
179 }
180
181 static void add_subsets_to(std::vector<jed_subset_t> *subset_list, std::vector<const char*> hostgroup, jed_container_t parent)
182 {
183   // get ids for each host
184   // sort ids
185   // compact ids
186   // create subset for each id group
187
188   xbt_assert( parent != nullptr );
189
190   std::vector<unsigned int> id_list;
191
192   for (auto host_name : hostgroup) {
193     xbt_assert( host_name != nullptr );
194     jed_container_t parent = host2_simgrid_parent_container.at(host_name);
195     unsigned int id = parent->name2id.at(host_name);
196     id_list.push_back(id);
197   }
198   unsigned int nb_ids = id_list.size();
199   std::sort(id_list.begin(), id_list.end());
200
201   if( nb_ids > 0 ) {
202     int start = 0;
203     int pos = start;
204     for(unsigned int i=0; i<nb_ids; i++) {
205       if( id_list[i] - id_list[pos] > 1 ) {
206         subset_list->push_back(new simgrid::jedule::Subset(id_list[start], id_list[pos], parent));
207         start = i;
208
209         if( i == nb_ids-1 ) {
210          subset_list->push_back(new simgrid::jedule::Subset(id_list[i], id_list[i], parent));
211         }
212       } else {
213         if( i == nb_ids-1 ) {
214           subset_list->push_back(new simgrid::jedule::Subset(id_list[start], id_list[i], parent));
215         }
216       }
217       pos = i;
218     }
219   }
220
221 }
222
223 void get_resource_selection_by_hosts(std::vector<jed_subset_t> *subset_list, std::vector<sg_host_t> *host_list)
224 {
225   xbt_assert( host_list != nullptr );
226   // for each host name
227   //  find parent container
228   //  group by parent container
229   std::unordered_map<const char*, std::vector<const char*>> parent2hostgroup;
230   for (auto host: *host_list) {
231     const char *host_name = sg_host_get_name(host);
232     jed_container_t parent = host2_simgrid_parent_container.at(host_name);
233     xbt_assert( parent != nullptr );
234
235     auto host_group = parent2hostgroup.find(parent->name.c_str());
236     if (host_group == parent2hostgroup.end())
237       parent2hostgroup.insert({parent->name.c_str(), std::vector<const char*>(1,host_name)});
238     else
239       host_group->second.push_back(host_name);
240   }
241
242   for (auto elm: parent2hostgroup) {
243     jed_container_t parent = container_name2container.at(elm.first);
244     add_subsets_to(subset_list, elm.second, parent);
245   }
246 }
247
248 #endif