Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
28468d0ecd75000cd49d67469434f0fd772ccdb9
[simgrid.git] / src / surf / workstation_ptask_L07.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2007 Arnaud Legrand. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/ex.h"
9 #include "xbt/dict.h"
10 #include "surf_private.h"
11
12 typedef enum {
13   SURF_WORKSTATION_RESOURCE_CPU,
14   SURF_WORKSTATION_RESOURCE_LINK,
15 } e_surf_workstation_model_type_t;
16
17 /**************************************/
18 /********* cpu object *****************/
19 /**************************************/
20 typedef struct cpu_L07 {
21   surf_model_t model;   /* Do not move this field */
22   e_surf_workstation_model_type_t type; /* Do not move this field */
23   char *name;                   /* Do not move this field */
24   lmm_constraint_t constraint;  /* Do not move this field */
25   double power_scale;
26   double power_current;
27   tmgr_trace_event_t power_event;
28   e_surf_cpu_state_t state_current;
29   tmgr_trace_event_t state_event;
30   int id;                       /* cpu and network card are a single object... */
31 } s_cpu_L07_t, *cpu_L07_t;
32
33 /**************************************/
34 /*********** network object ***********/
35 /**************************************/
36
37 typedef struct network_link_L07 {
38   surf_model_t model;   /* Do not move this field */
39   e_surf_workstation_model_type_t type; /* Do not move this field */
40   char *name;                   /* Do not move this field */
41   lmm_constraint_t constraint;  /* Do not move this field */
42   double bw_current;
43   tmgr_trace_event_t bw_event;
44   e_surf_network_link_state_t state_current;
45   tmgr_trace_event_t state_event;
46 } s_network_link_L07_t, *network_link_L07_t;
47
48
49 typedef struct s_route_L07 {
50   network_link_L07_t *links;
51   int size;
52 } s_route_L07_t, *route_L07_t;
53
54 /**************************************/
55 /*************** actions **************/
56 /**************************************/
57 typedef struct surf_action_workstation_L07 {
58   s_surf_action_t generic_action;
59   lmm_variable_t variable;
60   double rate;
61   int suspended;
62 } s_surf_action_workstation_L07_t, *surf_action_workstation_L07_t;
63
64
65 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_workstation);
66
67 static int nb_workstation = 0;
68 static s_route_L07_t *routing_table = NULL;
69 #define ROUTE(i,j) routing_table[(i)+(j)*nb_workstation]
70 static network_link_L07_t loopback = NULL;
71 static xbt_dict_t parallel_task_network_link_set = NULL;
72 lmm_system_t ptask_maxmin_system = NULL;
73
74 /**************************************/
75 /******* Resource Public     **********/
76 /**************************************/
77
78 static void *name_service(const char *name)
79 {
80   return xbt_dict_get_or_null(workstation_set, name);
81 }
82
83 static const char *get_model_name(void *model_id)
84 {
85   /* We can freely cast as a cpu_L07_t because it has the same
86      prefix as network_link_L07_t. However, only cpu_L07_t
87      will theoretically be given as an argument here. */
88   return ((cpu_L07_t) model_id)->name;
89 }
90
91 /* action_get_state is inherited from the surf module */
92
93 static void action_use(surf_action_t action)
94 {
95   action->using++;
96   return;
97 }
98
99 static int action_free(surf_action_t action)
100 {
101   action->using--;
102
103   if (!action->using) {
104     xbt_swag_remove(action, action->state_set);
105     if (((surf_action_workstation_L07_t) action)->variable)
106       lmm_variable_free(ptask_maxmin_system,
107                         ((surf_action_workstation_L07_t) action)->
108                         variable);
109     free(action);
110     return 1;
111   }
112   return 0;
113 }
114
115 static void action_cancel(surf_action_t action)
116 {
117   surf_action_change_state(action, SURF_ACTION_FAILED);
118   return;
119 }
120
121 static void action_recycle(surf_action_t action)
122 {
123   DIE_IMPOSSIBLE;
124   return;
125 }
126
127 /* action_change_state is inherited from the surf module */
128 /* action_set_data is inherited from the surf module */
129
130 static void action_suspend(surf_action_t action)
131 {
132   XBT_IN1("(%p))", action);
133   if (((surf_action_workstation_L07_t) action)->suspended != 2) {
134     ((surf_action_workstation_L07_t) action)->suspended = 1;
135     lmm_update_variable_weight(ptask_maxmin_system,
136                                ((surf_action_workstation_L07_t)
137                                 action)->variable, 0.0);
138   }
139   XBT_OUT;
140 }
141
142 static void action_resume(surf_action_t action)
143 {
144   XBT_IN1("(%p)", action);
145   if (((surf_action_workstation_L07_t) action)->suspended != 2) {
146     lmm_update_variable_weight(ptask_maxmin_system,
147                                ((surf_action_workstation_L07_t)
148                                 action)->variable, 1.0);
149     ((surf_action_workstation_L07_t) action)->suspended = 0;
150   }
151   XBT_OUT;
152 }
153
154 static int action_is_suspended(surf_action_t action)
155 {
156   return (((surf_action_workstation_L07_t) action)->suspended == 1);
157 }
158
159 static void action_set_max_duration(surf_action_t action, double duration)
160 {                               /* FIXME: should inherit */
161   XBT_IN2("(%p,%g)", action, duration);
162   action->max_duration = duration;
163   XBT_OUT;
164 }
165
166
167 static void action_set_priority(surf_action_t action, double priority)
168 {                               /* FIXME: should inherit */
169   XBT_IN2("(%p,%g)", action, priority);
170   action->priority = priority;
171   XBT_OUT;
172 }
173
174 /**************************************/
175 /******* Resource Private    **********/
176 /**************************************/
177
178 static int model_used(void *model_id)
179 {
180   /* We can freely cast as a network_link_L07_t because it has
181      the same prefix as cpu_L07_t */
182   return lmm_constraint_used(ptask_maxmin_system,
183                              ((network_link_L07_t) model_id)->
184                              constraint);
185
186 }
187
188 static double share_models(double now)
189 {
190   s_surf_action_workstation_L07_t s_action;
191
192   xbt_swag_t running_actions =
193       surf_workstation_model->common_public->states.running_action_set;
194   double min = generic_maxmin_share_models2(running_actions,
195                                                xbt_swag_offset(s_action,
196                                                                variable),
197                                                ptask_maxmin_system,
198                                                bottleneck_solve);
199
200   DEBUG1("min value : %f", min);
201
202   return min;
203 }
204
205 static void update_actions_state(double now, double delta)
206 {
207   surf_action_workstation_L07_t action = NULL;
208   surf_action_workstation_L07_t next_action = NULL;
209   xbt_swag_t running_actions =
210       surf_workstation_model->common_public->states.running_action_set;
211
212   xbt_swag_foreach_safe(action, next_action, running_actions) {
213     DEBUG3("Action (%p) : remains (%g) updated by %g.",
214            action, action->generic_action.remains,
215            lmm_variable_getvalue(action->variable) * delta);
216     double_update(&(action->generic_action.remains),
217                   lmm_variable_getvalue(action->variable) * delta);
218
219     if (action->generic_action.max_duration != NO_MAX_DURATION)
220       double_update(&(action->generic_action.max_duration), delta);
221
222     DEBUG2("Action (%p) : remains (%g).",
223            action, action->generic_action.remains);
224     if ((action->generic_action.remains <= 0) &&
225         (lmm_get_variable_weight(action->variable) > 0)) {
226       action->generic_action.finish = surf_get_clock();
227       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
228     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
229                (action->generic_action.max_duration <= 0)) {
230       action->generic_action.finish = surf_get_clock();
231       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
232     } else {
233       /* Need to check that none of the model has failed */
234       lmm_constraint_t cnst = NULL;
235       int i = 0;
236       void *constraint_id = NULL;
237
238       while ((cnst =
239               lmm_get_cnst_from_var(ptask_maxmin_system, action->variable,
240                                     i++))) {
241         constraint_id = lmm_constraint_id(cnst);
242
243 /*      if(((network_link_L07_t)constraint_id)->type== */
244 /*         SURF_WORKSTATION_RESOURCE_LINK) { */
245 /*        DEBUG2("Checking for link %s (%p)", */
246 /*               ((network_link_L07_t)constraint_id)->name, */
247 /*               ((network_link_L07_t)constraint_id)); */
248 /*      } */
249 /*      if(((cpu_L07_t)constraint_id)->type== */
250 /*         SURF_WORKSTATION_RESOURCE_CPU) { */
251 /*        DEBUG3("Checking for cpu %s (%p) : %s", */
252 /*               ((cpu_L07_t)constraint_id)->name, */
253 /*               ((cpu_L07_t)constraint_id), */
254 /*               ((cpu_L07_t)constraint_id)->state_current==SURF_CPU_OFF?"Off":"On"); */
255 /*      } */
256
257         if (((((network_link_L07_t) constraint_id)->type ==
258               SURF_WORKSTATION_RESOURCE_LINK) &&
259              (((network_link_L07_t) constraint_id)->state_current ==
260               SURF_NETWORK_LINK_OFF)) ||
261             ((((cpu_L07_t) constraint_id)->type ==
262               SURF_WORKSTATION_RESOURCE_CPU) &&
263              (((cpu_L07_t) constraint_id)->state_current ==
264               SURF_CPU_OFF))) {
265           DEBUG1("Action (%p) Failed!!", action);
266           action->generic_action.finish = surf_get_clock();
267           surf_action_change_state((surf_action_t) action,
268                                    SURF_ACTION_FAILED);
269           break;
270         }
271       }
272     }
273   }
274   return;
275 }
276
277 static void update_model_state(void *id,
278                                   tmgr_trace_event_t event_type,
279                                   double value)
280 {
281   cpu_L07_t cpu = id;
282   network_link_L07_t nw_link = id;
283
284   if (nw_link->type == SURF_WORKSTATION_RESOURCE_LINK) {
285     DEBUG2("Updating link %s (%p)", nw_link->name, nw_link);
286     if (event_type == nw_link->bw_event) {
287       nw_link->bw_current = value;
288       lmm_update_constraint_bound(ptask_maxmin_system, nw_link->constraint,
289                                   nw_link->bw_current);
290     } else if (event_type == nw_link->state_event) {
291       if (value > 0)
292         nw_link->state_current = SURF_NETWORK_LINK_ON;
293       else
294         nw_link->state_current = SURF_NETWORK_LINK_OFF;
295     } else {
296       CRITICAL0("Unknown event ! \n");
297       xbt_abort();
298     }
299     return;
300   } else if (cpu->type == SURF_WORKSTATION_RESOURCE_CPU) {
301     DEBUG3("Updating cpu %s (%p) with value %g", cpu->name, cpu, value);
302     if (event_type == cpu->power_event) {
303       cpu->power_current = value;
304       lmm_update_constraint_bound(ptask_maxmin_system, cpu->constraint,
305                                   cpu->power_current);
306     } else if (event_type == cpu->state_event) {
307       if (value > 0)
308         cpu->state_current = SURF_CPU_ON;
309       else
310         cpu->state_current = SURF_CPU_OFF;
311     } else {
312       CRITICAL0("Unknown event ! \n");
313       xbt_abort();
314     }
315     return;
316   } else {
317     DIE_IMPOSSIBLE;
318   }
319   return;
320 }
321
322 static void finalize(void)
323 {
324   int i, j;
325
326   xbt_dict_free(&network_link_set);
327   xbt_dict_free(&workstation_set);
328   if (parallel_task_network_link_set != NULL) {
329     xbt_dict_free(&parallel_task_network_link_set);
330   }
331   xbt_swag_free(surf_workstation_model->common_public->states.
332                 ready_action_set);
333   xbt_swag_free(surf_workstation_model->common_public->states.
334                 running_action_set);
335   xbt_swag_free(surf_workstation_model->common_public->states.
336                 failed_action_set);
337   xbt_swag_free(surf_workstation_model->common_public->states.
338                 done_action_set);
339
340   free(surf_workstation_model->common_public);
341   free(surf_workstation_model->common_private);
342   free(surf_workstation_model->extension_public);
343
344   free(surf_workstation_model);
345   surf_workstation_model = NULL;
346
347   for (i = 0; i < nb_workstation; i++)
348     for (j = 0; j < nb_workstation; j++)
349       free(ROUTE(i, j).links);
350   free(routing_table);
351   routing_table = NULL;
352   nb_workstation = 0;
353
354   if (ptask_maxmin_system) {
355     lmm_system_free(ptask_maxmin_system);
356     ptask_maxmin_system = NULL;
357   }
358 }
359
360 /**************************************/
361 /******* Resource Private    **********/
362 /**************************************/
363
364 static e_surf_cpu_state_t model_get_state(void *cpu)
365 {
366   return ((cpu_L07_t) cpu)->state_current;
367 }
368
369 static double get_speed(void *cpu, double load)
370 {
371   return load * (((cpu_L07_t) cpu)->power_scale);
372 }
373
374 static double get_available_speed(void *cpu)
375 {
376   return ((cpu_L07_t) cpu)->power_current;
377 }
378
379 static surf_action_t execute_parallel_task(int workstation_nb,
380                                            void **workstation_list,
381                                            double *computation_amount,
382                                            double *communication_amount,
383                                            double amount, double rate)
384 {
385   surf_action_workstation_L07_t action = NULL;
386   int i, j, k;
387   int nb_link = 0;
388   int nb_host = 0;
389
390   if (parallel_task_network_link_set == NULL) {
391     parallel_task_network_link_set =
392         xbt_dict_new_ext(workstation_nb * workstation_nb * 10);
393   }
394
395   /* Compute the number of affected models... */
396   for (i = 0; i < workstation_nb; i++) {
397     for (j = 0; j < workstation_nb; j++) {
398       cpu_L07_t card_src = workstation_list[i];
399       cpu_L07_t card_dst = workstation_list[j];
400       int route_size = ROUTE(card_src->id, card_dst->id).size;
401       network_link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
402
403       if (communication_amount[i * workstation_nb + j] > 0)
404         for (k = 0; k < route_size; k++) {
405           xbt_dict_set(parallel_task_network_link_set, route[k]->name,
406                        route[k], NULL);
407         }
408     }
409   }
410   nb_link = xbt_dict_length(parallel_task_network_link_set);
411   xbt_dict_reset(parallel_task_network_link_set);
412
413   for (i = 0; i < workstation_nb; i++)
414     if (computation_amount[i] > 0)
415       nb_host++;
416
417   action = xbt_new0(s_surf_action_workstation_L07_t, 1);
418   DEBUG3("Creating a parallel task (%p) with %d cpus and %d links.",
419          action, workstation_nb, nb_link);
420   action->generic_action.using = 1;
421   action->generic_action.cost = amount;
422   action->generic_action.remains = amount;
423   action->generic_action.max_duration = NO_MAX_DURATION;
424   action->generic_action.start = -1.0;
425   action->generic_action.finish = -1.0;
426   action->generic_action.model_type =
427       (surf_model_t) surf_workstation_model;
428   action->suspended = 0;        /* Should be useless because of the
429                                    calloc but it seems to help valgrind... */
430   action->generic_action.state_set =
431       surf_workstation_model->common_public->states.running_action_set;
432
433   xbt_swag_insert(action, action->generic_action.state_set);
434   action->rate = rate;
435
436   if (action->rate > 0)
437     action->variable =
438         lmm_variable_new(ptask_maxmin_system, action, 1.0, -1.0,
439                          workstation_nb + nb_link);
440   else
441     action->variable =
442         lmm_variable_new(ptask_maxmin_system, action, 1.0, action->rate,
443                          workstation_nb + nb_link);
444
445   for (i = 0; i < workstation_nb; i++)
446     lmm_expand(ptask_maxmin_system,
447                ((cpu_L07_t) workstation_list[i])->constraint,
448                action->variable, computation_amount[i]);
449   
450   for (i = 0; i < workstation_nb; i++) {
451     for (j = 0; j < workstation_nb; j++) {
452       cpu_L07_t card_src = workstation_list[i];
453       cpu_L07_t card_dst = workstation_list[j];
454       int route_size = ROUTE(card_src->id, card_dst->id).size;
455       network_link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
456       
457       if (communication_amount[i * workstation_nb + j] == 0.0) 
458         continue;
459       for (k = 0; k < route_size; k++) {
460           lmm_expand_add(ptask_maxmin_system, route[k]->constraint,
461                          action->variable,
462                          communication_amount[i * workstation_nb + j]);
463       }
464     }
465   }
466
467   if (nb_link + nb_host == 0) {
468     action->generic_action.cost = 1.0;
469     action->generic_action.remains = 0.0;
470   }
471
472   return (surf_action_t) action;
473 }
474
475 static surf_action_t execute(void *cpu, double size)
476 {
477   double val = 0.0;
478
479   return execute_parallel_task(1, &cpu, &size, &val, 1, -1);
480 }
481
482 static surf_action_t communicate(void *src, void *dst, double size,
483                                  double rate)
484 {
485   void **workstation_list = xbt_new0(void *, 2);
486   double *computation_amount = xbt_new0(double, 2);
487   double *communication_amount = xbt_new0(double, 4);
488   surf_action_t res = NULL;
489
490   workstation_list[0] = src;
491   workstation_list[1] = dst;
492   communication_amount[1] = size;
493
494   res = execute_parallel_task(2, workstation_list,
495                               computation_amount, communication_amount,
496                               1, rate);
497
498   free(computation_amount);
499   free(communication_amount);
500   free(workstation_list);
501
502   return res;
503 }
504
505 static surf_action_t action_sleep(void *cpu, double duration)
506 {
507   surf_action_workstation_L07_t action = NULL;
508
509   XBT_IN2("(%s,%g)", ((cpu_L07_t) cpu)->name, duration);
510
511   action = (surf_action_workstation_L07_t) execute(cpu, 1.0);
512   action->generic_action.max_duration = duration;
513   action->suspended = 2;
514   lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
515
516   XBT_OUT;
517   return (surf_action_t) action;
518 }
519
520 /* returns an array of network_link_L07_t */
521 static const void **get_route(void *src, void *dst)
522 {
523   cpu_L07_t card_src = src;
524   cpu_L07_t card_dst = dst;
525   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
526
527   return (const void **) route->links;
528 }
529
530 static int get_route_size(void *src, void *dst)
531 {
532   cpu_L07_t card_src = src;
533   cpu_L07_t card_dst = dst;
534   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
535   return route->size;
536 }
537
538 static const char *get_link_name(const void *link)
539 {
540   return ((network_link_L07_t) link)->name;
541 }
542
543 static double get_link_bandwidth(const void *link)
544 {
545   return ((network_link_L07_t) link)->bw_current;
546 }
547
548 static double get_link_latency(const void *link)
549 {
550   static int warned = 0;
551
552   if(!warned) {
553     WARN0("This model does not take latency into account.");
554     warned = 1;
555   }
556   return 0.0;
557 }
558
559 /**************************************/
560 /*** Resource Creation & Destruction **/
561 /**************************************/
562
563 static void cpu_free(void *cpu)
564 {
565   free(((cpu_L07_t) cpu)->name);
566   free(cpu);
567 }
568
569 static cpu_L07_t cpu_new(const char *name, double power_scale,
570                          double power_initial,
571                          tmgr_trace_t power_trace,
572                          e_surf_cpu_state_t state_initial,
573                          tmgr_trace_t state_trace)
574 {
575   cpu_L07_t cpu = xbt_new0(s_cpu_L07_t, 1);
576
577   cpu->model = (surf_model_t) surf_workstation_model;
578   cpu->type = SURF_WORKSTATION_RESOURCE_CPU;
579   cpu->name = xbt_strdup(name);
580   cpu->id = nb_workstation++;
581
582   cpu->power_scale = power_scale;
583   xbt_assert0(cpu->power_scale > 0, "Power has to be >0");
584
585   cpu->power_current = power_initial;
586   if (power_trace)
587     cpu->power_event =
588         tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
589
590   cpu->state_current = state_initial;
591   if (state_trace)
592     cpu->state_event =
593         tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
594
595   cpu->constraint =
596       lmm_constraint_new(ptask_maxmin_system, cpu,
597                          cpu->power_current * cpu->power_scale);
598
599   xbt_dict_set(workstation_set, name, cpu, cpu_free);
600
601   return cpu;
602 }
603
604 static void parse_cpu(void)
605 {
606   double power_scale = 0.0;
607   double power_initial = 0.0;
608   tmgr_trace_t power_trace = NULL;
609   e_surf_cpu_state_t state_initial = SURF_CPU_OFF;
610   tmgr_trace_t state_trace = NULL;
611
612   surf_parse_get_double(&power_scale, A_surfxml_cpu_power);
613   surf_parse_get_double(&power_initial, A_surfxml_cpu_availability);
614   surf_parse_get_trace(&power_trace, A_surfxml_cpu_availability_file);
615
616   xbt_assert0((A_surfxml_cpu_state == A_surfxml_cpu_state_ON) ||
617               (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF),
618               "Invalid state");
619   if (A_surfxml_cpu_state == A_surfxml_cpu_state_ON)
620     state_initial = SURF_CPU_ON;
621   if (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF)
622     state_initial = SURF_CPU_OFF;
623   surf_parse_get_trace(&state_trace, A_surfxml_cpu_state_file);
624
625   cpu_new(A_surfxml_cpu_name, power_scale, power_initial, power_trace,
626           state_initial, state_trace);
627 }
628
629 static void create_routing_table(void)
630 {
631   routing_table = xbt_new0(s_route_L07_t, nb_workstation * nb_workstation);
632 }
633
634 static void network_link_free(void *nw_link)
635 {
636   free(((network_link_L07_t) nw_link)->name);
637   free(nw_link);
638 }
639
640 static network_link_L07_t network_link_new(char *name,
641                                            double bw_initial,
642                                            tmgr_trace_t bw_trace,
643                                            e_surf_network_link_state_t
644                                            state_initial,
645                                            tmgr_trace_t state_trace,
646                                            e_surf_network_link_sharing_policy_t
647                                            policy)
648 {
649   network_link_L07_t nw_link = xbt_new0(s_network_link_L07_t, 1);
650
651
652   nw_link->model = (surf_model_t) surf_workstation_model;
653   nw_link->type = SURF_WORKSTATION_RESOURCE_LINK;
654   nw_link->name = name;
655   nw_link->bw_current = bw_initial;
656   if (bw_trace)
657     nw_link->bw_event =
658         tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
659   nw_link->state_current = state_initial;
660   if (state_trace)
661     nw_link->state_event =
662         tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
663
664   nw_link->constraint =
665       lmm_constraint_new(ptask_maxmin_system, nw_link,
666                          nw_link->bw_current);
667
668   if (policy == SURF_NETWORK_LINK_FATPIPE)
669     lmm_constraint_shared(nw_link->constraint);
670
671   xbt_dict_set(network_link_set, name, nw_link, network_link_free);
672
673   return nw_link;
674 }
675
676 static void parse_network_link(void)
677 {
678   char *name;
679   double bw_initial;
680   tmgr_trace_t bw_trace;
681   e_surf_network_link_state_t state_initial = SURF_NETWORK_LINK_ON;
682   e_surf_network_link_sharing_policy_t policy_initial =
683       SURF_NETWORK_LINK_SHARED;
684   tmgr_trace_t state_trace;
685
686   name = xbt_strdup(A_surfxml_network_link_name);
687   surf_parse_get_double(&bw_initial, A_surfxml_network_link_bandwidth);
688   surf_parse_get_trace(&bw_trace, A_surfxml_network_link_bandwidth_file);
689
690   xbt_assert0((A_surfxml_network_link_state ==
691                A_surfxml_network_link_state_ON)
692               || (A_surfxml_network_link_state ==
693                   A_surfxml_network_link_state_OFF), "Invalid state");
694   if (A_surfxml_network_link_state == A_surfxml_network_link_state_ON)
695     state_initial = SURF_NETWORK_LINK_ON;
696   else if (A_surfxml_network_link_state ==
697            A_surfxml_network_link_state_OFF)
698     state_initial = SURF_NETWORK_LINK_OFF;
699
700   if (A_surfxml_network_link_sharing_policy ==
701       A_surfxml_network_link_sharing_policy_SHARED)
702     policy_initial = SURF_NETWORK_LINK_SHARED;
703   else if (A_surfxml_network_link_sharing_policy ==
704            A_surfxml_network_link_sharing_policy_FATPIPE)
705     policy_initial = SURF_NETWORK_LINK_FATPIPE;
706
707   surf_parse_get_trace(&state_trace, A_surfxml_network_link_state_file);
708
709   network_link_new(name, bw_initial, bw_trace, state_initial, state_trace,
710                    policy_initial);
711 }
712
713 static void route_new(int src_id, int dst_id,
714                       network_link_L07_t * link_list, int nb_link)
715 {
716   route_L07_t route = &(ROUTE(src_id, dst_id));
717
718   route->size = nb_link;
719   route->links = link_list =
720       xbt_realloc(link_list, sizeof(network_link_L07_t) * nb_link);
721 }
722
723 static int nb_link;
724 static int link_list_capacity;
725 static network_link_L07_t *link_list = NULL;
726 static int src_id = -1;
727 static int dst_id = -1;
728
729 static void parse_route_set_endpoints(void)
730 {
731   cpu_L07_t cpu_tmp = NULL;
732
733   cpu_tmp = (cpu_L07_t) name_service(A_surfxml_route_src);
734   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_src);
735   if (cpu_tmp != NULL)
736     src_id = cpu_tmp->id;
737
738   cpu_tmp = (cpu_L07_t) name_service(A_surfxml_route_dst);
739   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_dst);
740   if (cpu_tmp != NULL)
741     dst_id = cpu_tmp->id;
742
743   nb_link = 0;
744   link_list_capacity = 1;
745   link_list = xbt_new(network_link_L07_t, link_list_capacity);
746 }
747
748 static void parse_route_elem(void)
749 {
750   xbt_ex_t e;
751   if (nb_link == link_list_capacity) {
752     link_list_capacity *= 2;
753     link_list =
754         xbt_realloc(link_list,
755                     (link_list_capacity) * sizeof(network_link_L07_t));
756   }
757   TRY {
758     link_list[nb_link++] =
759         xbt_dict_get(network_link_set, A_surfxml_route_element_name);
760   }
761   CATCH(e) {
762     RETHROW1("Link %s not found (dict raised this exception: %s)",
763              A_surfxml_route_element_name);
764   }
765 }
766
767 static void parse_route_set_route(void)
768 {
769   if (src_id != -1 && dst_id != -1)
770     route_new(src_id, dst_id, link_list, nb_link);
771 }
772
773 static void parse_file(const char *file)
774 {
775   int i;
776
777   /* Figuring out the cpus */
778   surf_parse_reset_parser();
779   ETag_surfxml_cpu_fun = parse_cpu;
780   surf_parse_open(file);
781   xbt_assert1((!surf_parse()), "Parse error in %s", file);
782   surf_parse_close();
783
784   create_routing_table();
785
786   /* Figuring out the network links */
787   surf_parse_reset_parser();
788   ETag_surfxml_network_link_fun = parse_network_link;
789   surf_parse_open(file);
790   xbt_assert1((!surf_parse()), "Parse error in %s", file);
791   surf_parse_close();
792
793   /* Building the routes */
794   surf_parse_reset_parser();
795   STag_surfxml_route_fun = parse_route_set_endpoints;
796   ETag_surfxml_route_element_fun = parse_route_elem;
797   ETag_surfxml_route_fun = parse_route_set_route;
798   surf_parse_open(file);
799   xbt_assert1((!surf_parse()), "Parse error in %s", file);
800   surf_parse_close();
801
802   /* Adding loopback if needed */
803   for (i = 0; i < nb_workstation; i++)
804     if (!ROUTE(i, i).size) {
805       if (!loopback)
806         loopback = network_link_new(xbt_strdup("__MSG_loopback__"),
807                                     498000000, NULL,
808                                     SURF_NETWORK_LINK_ON, NULL,
809                                     SURF_NETWORK_LINK_FATPIPE);
810
811       ROUTE(i, i).size = 1;
812       ROUTE(i, i).links = xbt_new0(network_link_L07_t, 1);
813       ROUTE(i, i).links[0] = loopback;
814     }
815 }
816
817 /**************************************/
818 /********* Module  creation ***********/
819 /**************************************/
820
821 static void model_init_internal(void)
822 {
823   s_surf_action_t action;
824
825   surf_workstation_model = xbt_new0(s_surf_workstation_model_t, 1);
826
827   surf_workstation_model->common_private =
828       xbt_new0(s_surf_model_private_t, 1);
829   surf_workstation_model->common_public =
830       xbt_new0(s_surf_model_public_t, 1);
831   surf_workstation_model->extension_public =
832       xbt_new0(s_surf_workstation_model_extension_public_t, 1);
833
834   surf_workstation_model->common_public->states.ready_action_set =
835       xbt_swag_new(xbt_swag_offset(action, state_hookup));
836   surf_workstation_model->common_public->states.running_action_set =
837       xbt_swag_new(xbt_swag_offset(action, state_hookup));
838   surf_workstation_model->common_public->states.failed_action_set =
839       xbt_swag_new(xbt_swag_offset(action, state_hookup));
840   surf_workstation_model->common_public->states.done_action_set =
841       xbt_swag_new(xbt_swag_offset(action, state_hookup));
842
843   surf_workstation_model->common_public->name_service = name_service;
844   surf_workstation_model->common_public->get_model_name =
845       get_model_name;
846   surf_workstation_model->common_public->action_get_state =
847       surf_action_get_state;
848   surf_workstation_model->common_public->action_get_start_time =
849       surf_action_get_start_time;
850   surf_workstation_model->common_public->action_get_finish_time =
851       surf_action_get_finish_time;
852   surf_workstation_model->common_public->action_use = action_use;
853   surf_workstation_model->common_public->action_free = action_free;
854   surf_workstation_model->common_public->action_cancel = action_cancel;
855   surf_workstation_model->common_public->action_recycle =
856       action_recycle;
857   surf_workstation_model->common_public->action_change_state =
858       surf_action_change_state;
859   surf_workstation_model->common_public->action_set_data =
860       surf_action_set_data;
861   surf_workstation_model->common_public->suspend = action_suspend;
862   surf_workstation_model->common_public->resume = action_resume;
863   surf_workstation_model->common_public->is_suspended =
864       action_is_suspended;
865   surf_workstation_model->common_public->set_max_duration =
866       action_set_max_duration;
867   surf_workstation_model->common_public->set_priority =
868       action_set_priority;
869   surf_workstation_model->common_public->name = "Workstation ptask_L07";
870
871   surf_workstation_model->common_private->model_used = model_used;
872   surf_workstation_model->common_private->share_models =
873       share_models;
874   surf_workstation_model->common_private->update_actions_state =
875       update_actions_state;
876   surf_workstation_model->common_private->update_model_state =
877       update_model_state;
878   surf_workstation_model->common_private->finalize = finalize;
879
880   surf_workstation_model->extension_public->execute = execute;
881   surf_workstation_model->extension_public->sleep = action_sleep;
882   surf_workstation_model->extension_public->get_state =
883       model_get_state;
884   surf_workstation_model->extension_public->get_speed = get_speed;
885   surf_workstation_model->extension_public->get_available_speed =
886       get_available_speed;
887   surf_workstation_model->extension_public->communicate = communicate;
888   surf_workstation_model->extension_public->execute_parallel_task =
889       execute_parallel_task;
890   surf_workstation_model->extension_public->get_route = get_route;
891   surf_workstation_model->extension_public->get_route_size =
892       get_route_size;
893   surf_workstation_model->extension_public->get_link_name =
894       get_link_name;
895   surf_workstation_model->extension_public->get_link_bandwidth =
896       get_link_bandwidth;
897   surf_workstation_model->extension_public->get_link_latency =
898       get_link_latency;
899
900   workstation_set = xbt_dict_new();
901   network_link_set = xbt_dict_new();
902
903   if (!ptask_maxmin_system)
904     ptask_maxmin_system = lmm_system_new();
905 }
906
907 /**************************************/
908 /*************** Generic **************/
909 /**************************************/
910 void surf_workstation_model_init_ptask_L07(const char *filename)
911 {
912   xbt_assert0(!surf_cpu_model, "CPU model type already defined");
913   xbt_assert0(!surf_network_model,
914               "network model type already defined");
915   model_init_internal();
916   parse_file(filename);
917   WARN0("This model does not take latency into account.");
918
919   update_model_description(surf_workstation_model_description,
920                               surf_workstation_model_description_size,
921                               "ptask_L07",
922                               (surf_model_t) surf_workstation_model);
923   xbt_dynar_push(model_list, &surf_workstation_model);
924 }