Logo AND Algorithmique Numérique Distribuée

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