Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ef3da4eef7bfb6176d57962d67ed4e804d01c8c7
[simgrid.git] / src / surf / sg_platf.cpp
1 /* Copyright (c) 2006-2014. 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 "xbt/misc.h"
8 #include "xbt/log.h"
9 #include "xbt/str.h"
10 #include "xbt/dict.h"
11 #include "xbt/RngStream.h"
12 #include "simgrid/platf_interface.h"
13 #include "surf/surf_routing.h"
14 #include "surf/surf.h"
15
16 #include "src/simix/smx_private.h"
17
18 #include "cpu_interface.hpp"
19 #include "host_interface.hpp"
20
21 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_parse);
22 xbt_dynar_t sg_platf_link_cb_list = NULL;   // of sg_platf_link_cb_t
23 xbt_dynar_t sg_platf_cluster_cb_list = NULL; // of sg_platf_cluster_cb_t
24 xbt_dynar_t sg_platf_postparse_cb_list = NULL; // of void_f_void_t
25
26 xbt_dynar_t sg_platf_ASroute_cb_list = NULL; // of sg_platf_ASroute_cb_t
27
28 /* ***************************************** */
29 /* TUTORIAL: New TAG                         */
30
31 xbt_dynar_t sg_platf_gpu_cb_list = NULL;
32 /* ***************************************** */
33
34
35 static int surf_parse_models_setup_already_called = 0;
36
37 /* one RngStream for the platform, to respect some statistic rules */
38 static RngStream sg_platf_rng_stream = NULL;
39
40 /** Module management function: creates all internal data structures */
41 void sg_platf_init(void) {
42
43   //FIXME : Ugly, but useful...
44   if (sg_platf_gpu_cb_list)
45     return; //Already initialized, so do nothing...
46
47   sg_platf_link_cb_list = xbt_dynar_new(sizeof(sg_platf_link_cb_t), NULL);
48   sg_platf_cluster_cb_list = xbt_dynar_new(sizeof(sg_platf_cluster_cb_t), NULL);
49   sg_platf_postparse_cb_list = xbt_dynar_new(sizeof(sg_platf_link_cb_t),NULL);
50
51   sg_platf_ASroute_cb_list = xbt_dynar_new(sizeof(sg_platf_route_cb_t), NULL);
52
53   /* ***************************************** */
54   /* TUTORIAL: New TAG                         */
55
56   sg_platf_gpu_cb_list = xbt_dynar_new(sizeof(sg_platf_gpu_cb_t), NULL);
57   /* ***************************************** */
58 }
59 /** Module management function: frees all internal data structures */
60 void sg_platf_exit(void) {
61   xbt_dynar_free(&sg_platf_link_cb_list);
62   xbt_dynar_free(&sg_platf_postparse_cb_list);
63   xbt_dynar_free(&sg_platf_cluster_cb_list);
64
65   xbt_dynar_free(&sg_platf_ASroute_cb_list);
66
67   /* ***************************************** */
68   /* TUTORIAL: New TAG                         */
69
70   xbt_dynar_free(&sg_platf_gpu_cb_list);
71
72   /* ***************************************** */
73
74   /* make sure that we will reinit the models while loading the platf once reinited */
75   surf_parse_models_setup_already_called = 0;
76 }
77
78 void sg_platf_new_host(sg_platf_host_cbarg_t host)
79 {
80   xbt_assert(! sg_host_by_name(host->id),
81                      "Refusing to create a second host named '%s'.", host->id);
82
83   RoutingEdge *net = NULL;
84   As* current_routing = routing_get_current();
85   if (current_routing)
86     net = routing_add_host(current_routing, host);
87
88   Cpu *cpu = surf_cpu_model_pm->createCpu(
89         host->id,
90         host->power_peak,
91         host->pstate,
92         host->power_scale,
93         host->power_trace,
94         host->core_amount,
95         host->initial_state,
96         host->state_trace,
97         host->properties);
98   surf_host_model->createHost(host->id, net, cpu);
99
100   if (TRACE_is_enabled() && TRACE_needs_platform())
101     sg_instr_new_host(host);
102 }
103
104 /**
105  * \brief Add a "router" to the network element list
106  */
107 void sg_platf_new_router(sg_platf_router_cbarg_t router)
108 {
109   As* current_routing = routing_get_current();
110
111   if (current_routing->p_hierarchy == SURF_ROUTING_NULL)
112     current_routing->p_hierarchy = SURF_ROUTING_BASE;
113   xbt_assert(!xbt_lib_get_or_null(as_router_lib, router->id, ROUTING_ASR_LEVEL),
114              "Reading a router, processing unit \"%s\" already exists",
115              router->id);
116
117   RoutingEdge *info = new RoutingEdgeImpl(xbt_strdup(router->id),
118                                             -1,
119                                             SURF_NETWORK_ELEMENT_ROUTER,
120                                             current_routing);
121   info->setId(current_routing->parsePU(info));
122   xbt_lib_set(as_router_lib, router->id, ROUTING_ASR_LEVEL, (void *) info);
123   XBT_DEBUG("Having set name '%s' id '%d'", router->id, info->getId());
124   routingEdgeCreatedCallbacks(info);
125
126   if (router->coord && strcmp(router->coord, "")) {
127     unsigned int cursor;
128     char*str;
129
130     if (!COORD_ASR_LEVEL)
131       xbt_die ("To use host coordinates, please add --cfg=network/coordinates:yes to your command line");
132     /* Pre-parse the host coordinates */
133     xbt_dynar_t ctn_str = xbt_str_split_str(router->coord, " ");
134     xbt_dynar_t ctn = xbt_dynar_new(sizeof(double),NULL);
135     xbt_dynar_foreach(ctn_str,cursor, str) {
136       double val = atof(str);
137       xbt_dynar_push(ctn,&val);
138     }
139     xbt_dynar_shrink(ctn, 0);
140     xbt_dynar_free(&ctn_str);
141     xbt_lib_set(as_router_lib, router->id, COORD_ASR_LEVEL, (void *) ctn);
142     XBT_DEBUG("Having set router coordinates for '%s'",router->id);
143   }
144
145   if (TRACE_is_enabled())
146     sg_instr_new_router(router);
147 }
148
149 void sg_platf_new_link(sg_platf_link_cbarg_t link){
150   unsigned int iterator;
151   sg_platf_link_cb_t fun;
152   xbt_dynar_foreach(sg_platf_link_cb_list, iterator, fun) {
153     fun(link);
154   }
155 }
156
157 void sg_platf_new_cluster(sg_platf_cluster_cbarg_t cluster){
158   unsigned int iterator;
159   sg_platf_cluster_cb_t fun;
160   xbt_dynar_foreach(sg_platf_cluster_cb_list, iterator, fun) {
161     fun(cluster);
162   }
163 }
164
165 void sg_platf_new_storage(sg_platf_storage_cbarg_t storage)
166 {
167   xbt_assert(!xbt_lib_get_or_null(storage_lib, storage->id,ROUTING_STORAGE_LEVEL),
168                "Reading a storage, processing unit \"%s\" already exists", storage->id);
169
170   // Verification of an existing type_id
171 #ifndef NDEBUG
172   void* storage_type = xbt_lib_get_or_null(storage_type_lib, storage->type_id,ROUTING_STORAGE_TYPE_LEVEL);
173 #endif
174   xbt_assert(storage_type,"Reading a storage, type id \"%s\" does not exists", storage->type_id);
175
176   XBT_DEBUG("ROUTING Create a storage name '%s' with type_id '%s' and content '%s'",
177       storage->id,
178       storage->type_id,
179       storage->content);
180
181   xbt_lib_set(storage_lib,
182       storage->id,
183       ROUTING_STORAGE_LEVEL,
184       (void *) xbt_strdup(storage->type_id));
185
186   void* stype = xbt_lib_get_or_null(storage_type_lib,
187                                     storage->type_id,
188                                     ROUTING_STORAGE_TYPE_LEVEL);
189   if(!stype) xbt_die("No storage type '%s'",storage->type_id);
190
191   // if storage content is not specified use the content of storage_type if exist
192   if(!strcmp(storage->content,"") && strcmp(((storage_type_t) stype)->content,"")){
193     storage->content = ((storage_type_t) stype)->content;
194     storage->content_type = ((storage_type_t) stype)->content_type;
195     XBT_DEBUG("For disk '%s' content is empty, inherit the content (of type %s) from storage type '%s' ",
196         storage->id,((storage_type_t) stype)->content_type,
197         ((storage_type_t) stype)->type_id);
198   }
199
200   XBT_DEBUG("SURF storage create resource\n\t\tid '%s'\n\t\ttype '%s' "
201       "\n\t\tmodel '%s' \n\t\tcontent '%s'\n\t\tcontent_type '%s' "
202       "\n\t\tproperties '%p''\n",
203       storage->id,
204       ((storage_type_t) stype)->model,
205       ((storage_type_t) stype)->type_id,
206       storage->content,
207       storage->content_type,
208       storage->properties);
209
210   surf_storage_model->createStorage(storage->id,
211                                      ((storage_type_t) stype)->type_id,
212                                      storage->content,
213                                      storage->content_type,
214                                      storage->properties,
215                                      storage->attach);
216 }
217 void sg_platf_new_storage_type(sg_platf_storage_type_cbarg_t storage_type){
218
219   xbt_assert(!xbt_lib_get_or_null(storage_type_lib, storage_type->id,ROUTING_STORAGE_TYPE_LEVEL),
220                "Reading a storage type, processing unit \"%s\" already exists", storage_type->id);
221
222   storage_type_t stype = xbt_new0(s_storage_type_t, 1);
223   stype->model = xbt_strdup(storage_type->model);
224   stype->properties = storage_type->properties;
225   stype->content = xbt_strdup(storage_type->content);
226   stype->content_type = xbt_strdup(storage_type->content_type);
227   stype->type_id = xbt_strdup(storage_type->id);
228   stype->size = storage_type->size;
229   stype->model_properties = storage_type->model_properties;
230
231   XBT_DEBUG("ROUTING Create a storage type id '%s' with model '%s', "
232       "content '%s', and content_type '%s'",
233       stype->type_id,
234       stype->model,
235       storage_type->content,
236       storage_type->content_type);
237
238   xbt_lib_set(storage_type_lib,
239       stype->type_id,
240       ROUTING_STORAGE_TYPE_LEVEL,
241       (void *) stype);
242 }
243 void sg_platf_new_mstorage(sg_platf_mstorage_cbarg_t mstorage)
244 {
245   THROW_UNIMPLEMENTED;
246 //  mount_t mnt = xbt_new0(s_mount_t, 1);
247 //  mnt->id = xbt_strdup(mstorage->type_id);
248 //  mnt->name = xbt_strdup(mstorage->name);
249 //
250 //  if(!mount_list){
251 //    XBT_DEBUG("Creata a Mount list for %s",A_surfxml_host_id);
252 //    mount_list = xbt_dynar_new(sizeof(char *), NULL);
253 //  }
254 //  xbt_dynar_push(mount_list,(void *) mnt);
255 //  free(mnt->id);
256 //  free(mnt->name);
257 //  xbt_free(mnt);
258 //  XBT_DEBUG("ROUTING Mount a storage name '%s' with type_id '%s'",mstorage->name, mstorage->id);
259 }
260
261 static void mount_free(void *p)
262 {
263   mount_t mnt = (mount_t) p;
264   xbt_free(mnt->name);
265 }
266
267 void sg_platf_new_mount(sg_platf_mount_cbarg_t mount){
268   // Verification of an existing storage
269 #ifndef NDEBUG
270   void* storage = xbt_lib_get_or_null(storage_lib, mount->storageId, ROUTING_STORAGE_LEVEL);
271 #endif
272   xbt_assert(storage,"Disk id \"%s\" does not exists", mount->storageId);
273
274   XBT_DEBUG("ROUTING Mount '%s' on '%s'",mount->storageId, mount->name);
275
276   s_mount_t mnt;
277   mnt.storage = surf_storage_resource_priv(surf_storage_resource_by_name(mount->storageId));
278   mnt.name = xbt_strdup(mount->name);
279
280   if(!mount_list){
281     XBT_DEBUG("Create a Mount list for %s",A_surfxml_host_id);
282     mount_list = xbt_dynar_new(sizeof(s_mount_t), mount_free);
283   }
284   xbt_dynar_push(mount_list, &mnt);
285 }
286
287 void sg_platf_new_route(sg_platf_route_cbarg_t route)
288 {
289   routing_get_current()->parseRoute(route);
290 }
291
292 void sg_platf_new_ASroute(sg_platf_route_cbarg_t ASroute)
293 {
294   unsigned int iterator;
295   sg_platf_route_cb_t fun;
296   xbt_dynar_foreach(sg_platf_ASroute_cb_list, iterator, fun) {
297     fun(ASroute);
298   }
299 }
300
301 void sg_platf_new_bypassRoute(sg_platf_route_cbarg_t bypassRoute)
302 {
303   routing_get_current()->parseBypassroute(bypassRoute);
304 }
305
306 void sg_platf_new_bypassASroute(sg_platf_route_cbarg_t bypassASroute)
307 {
308   routing_get_current()->parseBypassroute(bypassASroute);
309 }
310
311 void sg_platf_new_process(sg_platf_process_cbarg_t process)
312 {
313   if (!simix_global)
314     xbt_die("Cannot create process without SIMIX.");
315
316   sg_host_t host = sg_host_by_name(process->host);
317   if (!host)
318     THROWF(arg_error, 0, "Host '%s' unknown", process->host);
319   xbt_main_func_t parse_code = SIMIX_get_registered_function(process->function);
320   xbt_assert(parse_code, "Function '%s' unknown", process->function);
321
322   double start_time = process->start_time;
323   double kill_time  = process->kill_time;
324   int auto_restart = process->on_failure == SURF_PROCESS_ON_FAILURE_DIE ? 0 : 1;
325
326   smx_process_arg_t arg = NULL;
327   smx_process_t process_created = NULL;
328
329   arg = xbt_new0(s_smx_process_arg_t, 1);
330   arg->code = parse_code;
331   arg->data = NULL;
332   arg->hostname = sg_host_get_name(host);
333   arg->argc = process->argc;
334   arg->argv = xbt_new(char *,process->argc);
335   int i;
336   for (i=0; i<process->argc; i++)
337     arg->argv[i] = xbt_strdup(process->argv[i]);
338   arg->name = xbt_strdup(arg->argv[0]);
339   arg->kill_time = kill_time;
340   arg->properties = current_property_set;
341   if (!sg_host_simix(host)->boot_processes) {
342     sg_host_simix(host)->boot_processes = xbt_dynar_new(sizeof(smx_process_arg_t), _SIMIX_host_free_process_arg);
343   }
344   xbt_dynar_push_as(sg_host_simix(host)->boot_processes,smx_process_arg_t,arg);
345
346   if (start_time > SIMIX_get_clock()) {
347     arg = xbt_new0(s_smx_process_arg_t, 1);
348     arg->name = (char*)(process->argv)[0];
349     arg->code = parse_code;
350     arg->data = NULL;
351     arg->hostname = sg_host_get_name(host);
352     arg->argc = process->argc;
353     arg->argv = (char**)(process->argv);
354     arg->kill_time = kill_time;
355     arg->properties = current_property_set;
356
357     XBT_DEBUG("Process %s(%s) will be started at time %f", arg->name,
358            arg->hostname, start_time);
359     SIMIX_timer_set(start_time, [](void* arg) {
360       SIMIX_process_create_from_wrapper((smx_process_arg_t) arg);
361     }, arg);
362   } else {                      // start_time <= SIMIX_get_clock()
363     XBT_DEBUG("Starting Process %s(%s) right now", process->argv[0], sg_host_get_name(host));
364
365     if (simix_global->create_process_function)
366       process_created = simix_global->create_process_function(
367                                             (char*)(process->argv)[0],
368                                             parse_code,
369                                             NULL,
370                                             sg_host_get_name(host),
371                                             kill_time,
372                                             process->argc,
373                                             (char**)(process->argv),
374                                             current_property_set,
375                                             auto_restart, NULL);
376     else
377       process_created = simcall_process_create((char*)(process->argv)[0], parse_code, NULL, sg_host_get_name(host), kill_time, process->argc,
378           (char**)process->argv, current_property_set,auto_restart);
379
380     /* verify if process has been created (won't be the case if the host is currently dead, but that's fine) */
381     if (!process_created) {
382       return;
383     }
384   }
385   current_property_set = NULL;
386 }
387
388 void sg_platf_route_begin (sg_platf_route_cbarg_t route){
389   route->link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
390 }
391 void sg_platf_ASroute_begin (sg_platf_route_cbarg_t ASroute){
392   ASroute->link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
393 }
394
395 void sg_platf_route_end (sg_platf_route_cbarg_t route){
396   sg_platf_new_route(route);
397 }
398 void sg_platf_ASroute_end (sg_platf_route_cbarg_t ASroute){
399   sg_platf_new_ASroute(ASroute);
400 }
401
402 void sg_platf_route_add_link (const char* link_id, sg_platf_route_cbarg_t route){
403   char *link_name = xbt_strdup(link_id);
404   xbt_dynar_push(route->link_list, &link_name);
405 }
406 void sg_platf_ASroute_add_link (const char* link_id, sg_platf_route_cbarg_t ASroute){
407   char *link_name = xbt_strdup(link_id);
408   xbt_dynar_push(ASroute->link_list, &link_name);
409 }
410
411 void sg_platf_begin() { /* Do nothing: just for symmetry of user code */ }
412
413 void sg_platf_end() {
414   unsigned int iterator;
415   void_f_void_t fun;
416   xbt_dynar_foreach(sg_platf_postparse_cb_list, iterator, fun) {
417     fun();
418   }
419 }
420
421 void sg_platf_new_AS_begin(sg_platf_AS_cbarg_t AS)
422 {
423   if (!surf_parse_models_setup_already_called) {
424     /* Initialize the surf models. That must be done after we got all config, and before we need the models.
425      * That is, after the last <config> tag, if any, and before the first of cluster|peer|AS|trace|trace_connect
426      *
427      * I'm not sure for <trace> and <trace_connect>, there may be a bug here
428      * (FIXME: check it out by creating a file beginning with one of these tags)
429      * but cluster and peer create ASes internally, so putting the code in there is ok.
430      *
431      * TODO, There used to be a guard protecting here against
432      * xbt_dynar_length(sg_platf_AS_begin_cb_list) because we don't want to
433      * initialize the models if we are parsing the file to get the deployment.
434      * That could happen if the same file would be used for platf and deploy:
435      * it'd contain AS tags even during the deploy parsing. Removing that guard
436      * would result of the models to get re-inited when parsing for deploy.
437      * Currently using the same file for platform and deployment is broken
438      * however. This guard will have to ba adapted in order to make this feature
439      * work again.
440      */
441     surf_parse_models_setup_already_called = 1;
442     surf_config_models_setup();
443   }
444
445   routing_AS_begin(AS);
446   if (TRACE_is_enabled())
447     sg_instr_AS_begin(AS);
448 }
449
450 void sg_platf_new_AS_end()
451 {
452   routing_AS_end();
453   if (TRACE_is_enabled())
454     sg_instr_AS_end();
455 }
456
457 /* ***************************************** */
458 /* TUTORIAL: New TAG                         */
459
460 void sg_platf_new_gpu(sg_platf_gpu_cbarg_t gpu) {
461   unsigned int iterator;
462   void_f_void_t fun;
463   xbt_dynar_foreach(sg_platf_gpu_cb_list, iterator, fun) {
464     fun();
465   }
466 }
467
468 void sg_platf_gpu_add_cb(sg_platf_gpu_cb_t fct) {
469   xbt_dynar_push(sg_platf_gpu_cb_list, &fct);
470 }
471
472 /* ***************************************** */
473
474 void sg_platf_link_add_cb(sg_platf_link_cb_t fct) {
475   xbt_dynar_push(sg_platf_link_cb_list, &fct);
476 }
477 void sg_platf_cluster_add_cb(sg_platf_cluster_cb_t fct) {
478   xbt_dynar_push(sg_platf_cluster_cb_list, &fct);
479 }
480 void sg_platf_postparse_add_cb(void_f_void_t fct) {
481   xbt_dynar_push(sg_platf_postparse_cb_list, &fct);
482 }
483 void sg_platf_ASroute_add_cb(sg_platf_route_cb_t fct) {
484   xbt_dynar_push(sg_platf_ASroute_cb_list, &fct);
485 }
486
487 void sg_platf_rng_stream_init(unsigned long seed[6]) {
488   RngStream_SetPackageSeed(seed);
489   sg_platf_rng_stream = RngStream_CreateStream(NULL);
490 }
491
492 RngStream sg_platf_rng_stream_get(const char* id) {
493   RngStream stream = NULL;
494   unsigned int id_hash;
495
496   stream = RngStream_CopyStream(sg_platf_rng_stream);
497   id_hash = xbt_str_hash(id);
498   RngStream_AdvanceState(stream, 0, (long)id_hash);
499
500   return stream;
501 }