Logo AND Algorithmique Numérique Distribuée

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