Logo AND Algorithmique Numérique Distribuée

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