Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Extract the routing logic into its own object.
[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/str.h"
10 #include "xbt/dict.h"
11 #include "surf_private.h"
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   s_surf_resource_t generic_resource;  /* Do not move this field: must match surf_resource_t */
23   xbt_dict_t properties;        /* Do not move this field: must match link_L07_t */
24   e_surf_workstation_model_type_t type; /* Do not move this field: must match link_L07_t */
25   lmm_constraint_t constraint;  /* Do not move this field: must match link_L07_t */
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 link_L07 {
39   s_surf_resource_t generic_resource;  /* Do not move this field: must match surf_resource_t */
40   xbt_dict_t properties;        /* Do not move this field: must match link_L07_t */
41   e_surf_workstation_model_type_t type; /* Do not move this field: must match cpu_L07_t */
42   lmm_constraint_t constraint;  /* Do not move this field: must match cpu_L07_t */
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_link_state_t state_current;
48   tmgr_trace_event_t state_event;
49 } s_link_L07_t, *link_L07_t;
50
51 /**************************************/
52 /*************** actions **************/
53 /**************************************/
54 typedef struct surf_action_workstation_L07 {
55   s_surf_action_t generic_action;
56   lmm_variable_t variable;
57   int workstation_nb;
58   cpu_L07_t *workstation_list;
59   double *computation_amount;
60   double *communication_amount;
61   double latency;
62   double rate;
63   int suspended;
64 } s_surf_action_workstation_L07_t, *surf_action_workstation_L07_t;
65
66
67 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_workstation);
68
69 static int host_count = 0;
70 static xbt_dict_t parallel_task_link_set = NULL;
71 lmm_system_t ptask_maxmin_system = NULL;
72
73
74 static void update_action_bound(surf_action_workstation_L07_t action)
75 {
76   int workstation_nb = action->workstation_nb;
77   double lat_current = 0.0;
78   double lat_bound = -1.0;
79   int i, j;
80   unsigned int cpt;
81   link_L07_t link;
82
83   for (i = 0; i < workstation_nb; i++) {
84     for (j = 0; j < workstation_nb; j++) {
85       cpu_L07_t card_src = action->workstation_list[i];
86       cpu_L07_t card_dst = action->workstation_list[j];
87       xbt_dynar_t route = used_routing->get_route(card_src->id, card_dst->id);
88       double lat = 0.0;
89
90       if (action->communication_amount[i * workstation_nb + j] > 0) {
91         xbt_dynar_foreach(route,cpt,link) {
92           lat += link->lat_current;
93         }
94         lat_current =
95           MAX(lat_current,
96               lat * action->communication_amount[i * workstation_nb + j]);
97       }
98     }
99   }
100   lat_bound = sg_tcp_gamma / (2.0 * lat_current);
101   DEBUG2("action (%p) : lat_bound = %g", action, lat_bound);
102   if ((action->latency == 0.0) && (action->suspended == 0)) {
103     if (action->rate < 0)
104       lmm_update_variable_bound(ptask_maxmin_system, action->variable,
105                                 lat_bound);
106     else
107       lmm_update_variable_bound(ptask_maxmin_system, action->variable,
108                                 min(action->rate, lat_bound));
109   }
110 }
111
112 /**************************************/
113 /******* Resource Public     **********/
114 /**************************************/
115
116 static xbt_dict_t get_properties(void *r)
117 {
118   /* We can freely cast as a cpu_L07_t since it has the same prefix than link_L07_t */
119   return ((cpu_L07_t) r)->properties;
120 }
121
122 static int action_unref(surf_action_t action)
123 {
124   action->refcount--;
125
126   if (!action->refcount) {
127     xbt_swag_remove(action, action->state_set);
128     if (((surf_action_workstation_L07_t) action)->variable)
129       lmm_variable_free(ptask_maxmin_system,
130                         ((surf_action_workstation_L07_t) action)->variable);
131     free(((surf_action_workstation_L07_t) action)->workstation_list);
132     free(((surf_action_workstation_L07_t) action)->communication_amount);
133     free(((surf_action_workstation_L07_t) action)->computation_amount);
134     free(action);
135     return 1;
136   }
137   return 0;
138 }
139
140 static void action_cancel(surf_action_t action)
141 {
142   surf_action_state_set(action, SURF_ACTION_FAILED);
143   return;
144 }
145
146 /* action_change_state is inherited from the surf module */
147 /* action_set_data is inherited from the surf module */
148
149 static void action_suspend(surf_action_t action)
150 {
151   XBT_IN1("(%p))", action);
152   if (((surf_action_workstation_L07_t) action)->suspended != 2) {
153     ((surf_action_workstation_L07_t) action)->suspended = 1;
154     lmm_update_variable_weight(ptask_maxmin_system,
155                                ((surf_action_workstation_L07_t)
156                                 action)->variable, 0.0);
157   }
158   XBT_OUT;
159 }
160
161 static void action_resume(surf_action_t action)
162 {
163   surf_action_workstation_L07_t act = (surf_action_workstation_L07_t) action;
164
165   XBT_IN1("(%p)", act);
166   if (act->suspended != 2) {
167     lmm_update_variable_weight(ptask_maxmin_system, act->variable, 1.0);
168     act->suspended = 0;
169   }
170   XBT_OUT;
171 }
172
173 static int action_is_suspended(surf_action_t action)
174 {
175   return (((surf_action_workstation_L07_t) action)->suspended == 1);
176 }
177
178 static void action_set_max_duration(surf_action_t action, double duration)
179 {                               /* FIXME: should inherit */
180   XBT_IN2("(%p,%g)", action, duration);
181   action->max_duration = duration;
182   XBT_OUT;
183 }
184
185
186 static void action_set_priority(surf_action_t action, double priority)
187 {                               /* FIXME: should inherit */
188   XBT_IN2("(%p,%g)", action, priority);
189   action->priority = priority;
190   XBT_OUT;
191 }
192
193 /**************************************/
194 /******* Resource Private    **********/
195 /**************************************/
196
197 static int resource_used(void *resource_id)
198 {
199   /* We can freely cast as a link_L07_t because it has
200      the same prefix as cpu_L07_t */
201   return lmm_constraint_used(ptask_maxmin_system,
202                              ((link_L07_t) resource_id)->constraint);
203
204 }
205
206 static double share_resources(double now)
207 {
208   s_surf_action_workstation_L07_t s_action;
209   surf_action_workstation_L07_t action = NULL;
210
211   xbt_swag_t running_actions =
212     surf_workstation_model->states.running_action_set;
213   double min = generic_maxmin_share_resources(running_actions,
214                                               xbt_swag_offset(s_action,
215                                                               variable),
216                                               ptask_maxmin_system,
217                                               bottleneck_solve);
218
219   xbt_swag_foreach(action, running_actions) {
220     if (action->latency > 0) {
221       if (min < 0) {
222         min = action->latency;
223         DEBUG3("Updating min (value) with %p (start %f): %f", action,
224                action->generic_action.start, min);
225       } else if (action->latency < min) {
226         min = action->latency;
227         DEBUG3("Updating min (latency) with %p (start %f): %f", action,
228                action->generic_action.start, min);
229       }
230     }
231   }
232
233   DEBUG1("min value : %f", min);
234
235   return min;
236 }
237
238 static void update_actions_state(double now, double delta)
239 {
240   double deltap = 0.0;
241   surf_action_workstation_L07_t action = NULL;
242   surf_action_workstation_L07_t next_action = NULL;
243   xbt_swag_t running_actions =
244     surf_workstation_model->states.running_action_set;
245
246   xbt_swag_foreach_safe(action, next_action, running_actions) {
247     deltap = delta;
248     if (action->latency > 0) {
249       if (action->latency > deltap) {
250         double_update(&(action->latency), deltap);
251         deltap = 0.0;
252       } else {
253         double_update(&(deltap), action->latency);
254         action->latency = 0.0;
255       }
256       if ((action->latency == 0.0) && (action->suspended == 0)) {
257         update_action_bound(action);
258         lmm_update_variable_weight(ptask_maxmin_system, action->variable,
259                                    1.0);
260       }
261     }
262     DEBUG3("Action (%p) : remains (%g) updated by %g.",
263            action, action->generic_action.remains,
264            lmm_variable_getvalue(action->variable) * delta);
265     double_update(&(action->generic_action.remains),
266                   lmm_variable_getvalue(action->variable) * delta);
267
268     if (action->generic_action.max_duration != NO_MAX_DURATION)
269       double_update(&(action->generic_action.max_duration), delta);
270
271     DEBUG2("Action (%p) : remains (%g).",
272            action, action->generic_action.remains);
273     if ((action->generic_action.remains <= 0) &&
274         (lmm_get_variable_weight(action->variable) > 0)) {
275       action->generic_action.finish = surf_get_clock();
276       surf_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
277     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
278                (action->generic_action.max_duration <= 0)) {
279       action->generic_action.finish = surf_get_clock();
280       surf_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
281     } else {
282       /* Need to check that none of the model has failed */
283       lmm_constraint_t cnst = NULL;
284       int i = 0;
285       void *constraint_id = NULL;
286
287       while ((cnst =
288               lmm_get_cnst_from_var(ptask_maxmin_system, action->variable,
289                                     i++))) {
290         constraint_id = lmm_constraint_id(cnst);
291
292 /*      if(((link_L07_t)constraint_id)->type== */
293 /*         SURF_WORKSTATION_RESOURCE_LINK) { */
294 /*        DEBUG2("Checking for link %s (%p)", */
295 /*               ((link_L07_t)constraint_id)->name, */
296 /*               ((link_L07_t)constraint_id)); */
297 /*      } */
298 /*      if(((cpu_L07_t)constraint_id)->type== */
299 /*         SURF_WORKSTATION_RESOURCE_CPU) { */
300 /*        DEBUG3("Checking for cpu %s (%p) : %s", */
301 /*               ((cpu_L07_t)constraint_id)->name, */
302 /*               ((cpu_L07_t)constraint_id), */
303 /*               ((cpu_L07_t)constraint_id)->state_current==SURF_CPU_OFF?"Off":"On"); */
304 /*      } */
305
306         if (((((link_L07_t) constraint_id)->type ==
307               SURF_WORKSTATION_RESOURCE_LINK) &&
308              (((link_L07_t) constraint_id)->state_current ==
309               SURF_LINK_OFF)) ||
310             ((((cpu_L07_t) constraint_id)->type ==
311               SURF_WORKSTATION_RESOURCE_CPU) &&
312              (((cpu_L07_t) constraint_id)->state_current == SURF_CPU_OFF))) {
313           DEBUG1("Action (%p) Failed!!", action);
314           action->generic_action.finish = surf_get_clock();
315           surf_action_state_set((surf_action_t) action,
316                                    SURF_ACTION_FAILED);
317           break;
318         }
319       }
320     }
321   }
322   return;
323 }
324
325 static void update_resource_state(void *id,
326                                   tmgr_trace_event_t event_type,
327                                   double value, double date)
328 {
329   cpu_L07_t cpu = id;
330   link_L07_t nw_link = id;
331
332   if (nw_link->type == SURF_WORKSTATION_RESOURCE_LINK) {
333     DEBUG2("Updating link %s (%p)", nw_link->generic_resource.name, nw_link);
334     if (event_type == nw_link->bw_event) {
335       nw_link->bw_current = value;
336       lmm_update_constraint_bound(ptask_maxmin_system, nw_link->constraint,
337                                   nw_link->bw_current);
338     } else if (event_type == nw_link->lat_event) {
339       lmm_variable_t var = NULL;
340       surf_action_workstation_L07_t action = NULL;
341       lmm_element_t elem = NULL;
342
343       nw_link->lat_current = value;
344       while ((var = lmm_get_var_from_cnst
345               (ptask_maxmin_system, nw_link->constraint, &elem))) {
346
347
348         action = lmm_variable_id(var);
349         update_action_bound(action);
350       }
351
352     } else if (event_type == nw_link->state_event) {
353       if (value > 0)
354         nw_link->state_current = SURF_LINK_ON;
355       else
356         nw_link->state_current = SURF_LINK_OFF;
357     } else {
358       CRITICAL0("Unknown event ! \n");
359       xbt_abort();
360     }
361     return;
362   } else if (cpu->type == SURF_WORKSTATION_RESOURCE_CPU) {
363     DEBUG3("Updating cpu %s (%p) with value %g", cpu->generic_resource.name, cpu, value);
364     if (event_type == cpu->power_event) {
365       cpu->power_current = value;
366       lmm_update_constraint_bound(ptask_maxmin_system, cpu->constraint,
367                                   cpu->power_current * cpu->power_scale);
368     } else if (event_type == cpu->state_event) {
369       if (value > 0)
370         cpu->state_current = SURF_CPU_ON;
371       else
372         cpu->state_current = SURF_CPU_OFF;
373     } else {
374       CRITICAL0("Unknown event ! \n");
375       xbt_abort();
376     }
377     return;
378   } else {
379     DIE_IMPOSSIBLE;
380   }
381   return;
382 }
383
384 static void finalize(void)
385 {
386   xbt_dict_free(&link_set);
387   if (parallel_task_link_set != NULL) {
388     xbt_dict_free(&parallel_task_link_set);
389   }
390
391   surf_model_exit(surf_workstation_model);
392   surf_workstation_model = NULL;
393   used_routing->finalize();
394
395   host_count = 0; // FIXME: KILLME?
396
397   if (ptask_maxmin_system) {
398     lmm_system_free(ptask_maxmin_system);
399     ptask_maxmin_system = NULL;
400   }
401 }
402
403 /**************************************/
404 /******* Resource Private    **********/
405 /**************************************/
406
407 static e_surf_cpu_state_t resource_get_state(void *cpu)
408 {
409   return ((cpu_L07_t) cpu)->state_current;
410 }
411
412 static double get_speed(void *cpu, double load)
413 {
414   return load * (((cpu_L07_t) cpu)->power_scale);
415 }
416
417 static double get_available_speed(void *cpu)
418 {
419   return ((cpu_L07_t) cpu)->power_current;
420 }
421
422 static surf_action_t execute_parallel_task(int workstation_nb,
423                                            void **workstation_list,
424                                            double *computation_amount,
425                                            double *communication_amount,
426                                            double amount, double rate)
427 {
428   surf_action_workstation_L07_t action = NULL;
429   int i, j;
430   unsigned int cpt;
431   int nb_link = 0;
432   int nb_host = 0;
433   double latency = 0.0;
434
435   if (parallel_task_link_set == NULL)
436     parallel_task_link_set = xbt_dict_new();
437
438   xbt_dict_reset(parallel_task_link_set);
439
440   /* Compute the number of affected resources... */
441   for (i = 0; i < workstation_nb; i++) {
442     for (j = 0; j < workstation_nb; j++) {
443       cpu_L07_t card_src = workstation_list[i];
444       cpu_L07_t card_dst = workstation_list[j];
445       link_L07_t link;
446       xbt_dynar_t route = used_routing->get_route(card_src->id, card_dst->id);
447       double lat = 0.0;
448
449       if (communication_amount[i * workstation_nb + j] > 0)
450         xbt_dynar_foreach(route,cpt,link) {
451           lat += link->lat_current;
452           xbt_dict_set(parallel_task_link_set, link->generic_resource.name,
453                        link, NULL);
454         }
455       latency = MAX(latency, lat);
456     }
457   }
458
459   nb_link = xbt_dict_length(parallel_task_link_set);
460   xbt_dict_reset(parallel_task_link_set);
461
462   for (i = 0; i < workstation_nb; i++)
463     if (computation_amount[i] > 0)
464       nb_host++;
465
466   action = xbt_new0(s_surf_action_workstation_L07_t, 1);
467   DEBUG3("Creating a parallel task (%p) with %d cpus and %d links.",
468          action, workstation_nb, nb_link);
469   action->generic_action.refcount = 1;
470   action->generic_action.cost = amount;
471   action->generic_action.remains = amount;
472   action->generic_action.max_duration = NO_MAX_DURATION;
473   action->generic_action.start = surf_get_clock();
474   action->generic_action.finish = -1.0;
475   action->generic_action.model_type = surf_workstation_model;
476   action->suspended = 0;        /* Should be useless because of the
477                                    calloc but it seems to help valgrind... */
478   action->workstation_nb = workstation_nb;
479   action->workstation_list = (cpu_L07_t *) workstation_list;
480   action->computation_amount = computation_amount;
481   action->communication_amount = communication_amount;
482   action->latency = latency;
483   action->generic_action.state_set =
484     surf_workstation_model->states.running_action_set;
485
486   xbt_swag_insert(action, action->generic_action.state_set);
487   action->rate = rate;
488
489   action->variable =
490     lmm_variable_new(ptask_maxmin_system, action, 1.0,
491                      (action->rate > 0) ? action->rate : -1.0,
492                      workstation_nb + nb_link);
493
494   if (action->latency > 0)
495     lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
496
497   for (i = 0; i < workstation_nb; i++)
498     lmm_expand(ptask_maxmin_system,
499                ((cpu_L07_t) workstation_list[i])->constraint,
500                action->variable, computation_amount[i]);
501
502   for (i = 0; i < workstation_nb; i++) {
503     for (j = 0; j < workstation_nb; j++) {
504       cpu_L07_t card_src = workstation_list[i];
505       cpu_L07_t card_dst = workstation_list[j];
506       link_L07_t link;
507       xbt_dynar_t route = used_routing->get_route(card_src->id, card_dst->id);
508
509       if (communication_amount[i * workstation_nb + j] == 0.0)
510         continue;
511       xbt_dynar_foreach(route,cpt,link) {
512         lmm_expand_add(ptask_maxmin_system, link->constraint,
513                        action->variable,
514                        communication_amount[i * workstation_nb + j]);
515       }
516     }
517   }
518
519   if (nb_link + nb_host == 0) {
520     action->generic_action.cost = 1.0;
521     action->generic_action.remains = 0.0;
522   }
523
524   return (surf_action_t) action;
525 }
526
527 static surf_action_t execute(void *cpu, double size)
528 {
529   void **workstation_list = xbt_new0(void *, 1);
530   double *computation_amount = xbt_new0(double, 1);
531   double *communication_amount = xbt_new0(double, 1);
532
533   workstation_list[0] = cpu;
534   communication_amount[0] = 0.0;
535   computation_amount[0] = size;
536
537   return execute_parallel_task(1, workstation_list, computation_amount,
538                                communication_amount, 1, -1);
539 }
540
541 static surf_action_t communicate(void *src, void *dst, double size,
542                                  double rate)
543 {
544   void **workstation_list = xbt_new0(void *, 2);
545   double *computation_amount = xbt_new0(double, 2);
546   double *communication_amount = xbt_new0(double, 4);
547   surf_action_t res = NULL;
548
549   workstation_list[0] = src;
550   workstation_list[1] = dst;
551   communication_amount[1] = size;
552
553   res = execute_parallel_task(2, workstation_list,
554                               computation_amount, communication_amount,
555                               1, rate);
556
557   return res;
558 }
559
560 static surf_action_t action_sleep(void *cpu, double duration)
561 {
562   surf_action_workstation_L07_t action = NULL;
563
564   XBT_IN2("(%s,%g)", ((cpu_L07_t) cpu)->generic_resource.name, duration);
565
566   action = (surf_action_workstation_L07_t) execute(cpu, 1.0);
567   action->generic_action.max_duration = duration;
568   action->suspended = 2;
569   lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
570
571   XBT_OUT;
572   return (surf_action_t) action;
573 }
574
575 static xbt_dynar_t get_route(void *src, void *dst)
576 {
577   cpu_L07_t host_src = src;
578   cpu_L07_t host_dst = dst;
579
580   return used_routing->get_route(host_src->id, host_dst->id);
581 }
582
583 static double get_link_bandwidth(const void *link)
584 {
585   return ((link_L07_t) link)->bw_current;
586 }
587
588 static double get_link_latency(const void *link)
589 {
590   return ((link_L07_t) link)->lat_current;
591 }
592
593 static int link_shared(const void *link)
594 {
595   return lmm_constraint_is_shared(((link_L07_t) link)->constraint);
596 }
597
598 /**************************************/
599 /*** Resource Creation & Destruction **/
600 /**************************************/
601
602 static void cpu_free(void *cpu)
603 {
604   xbt_dict_free(&(((cpu_L07_t) cpu)->properties));
605   surf_resource_free(cpu);
606 }
607
608 static cpu_L07_t cpu_new(const char *name, double power_scale,
609                          double power_initial,
610                          tmgr_trace_t power_trace,
611                          e_surf_cpu_state_t state_initial,
612                          tmgr_trace_t state_trace, xbt_dict_t cpu_properties)
613 {
614   cpu_L07_t cpu = xbt_new0(s_cpu_L07_t, 1);
615   xbt_assert1(!surf_model_resource_by_name(surf_workstation_model, name),
616               "Host '%s' declared several times in the platform file.", name);
617
618   cpu->generic_resource.model = surf_workstation_model;
619   cpu->type = SURF_WORKSTATION_RESOURCE_CPU;
620   cpu->generic_resource.name = xbt_strdup(name);
621   cpu->id = host_count++;
622
623   cpu->power_scale = power_scale;
624   xbt_assert0(cpu->power_scale > 0, "Power has to be >0");
625
626   cpu->power_current = power_initial;
627   if (power_trace)
628     cpu->power_event =
629       tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
630
631   cpu->state_current = state_initial;
632   if (state_trace)
633     cpu->state_event =
634       tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
635
636   cpu->constraint =
637     lmm_constraint_new(ptask_maxmin_system, cpu,
638                        cpu->power_current * cpu->power_scale);
639
640   /*add the property set */
641   cpu->properties = current_property_set;
642
643   xbt_dict_set(surf_model_resource_set(surf_workstation_model), name, cpu,
644                cpu_free);
645
646   return cpu;
647 }
648
649 static void parse_cpu_init(void)
650 {
651   double power_scale = 0.0;
652   double power_initial = 0.0;
653   tmgr_trace_t power_trace = NULL;
654   e_surf_cpu_state_t state_initial = SURF_CPU_OFF;
655   tmgr_trace_t state_trace = NULL;
656
657   power_scale = get_cpu_power(A_surfxml_host_power);
658   surf_parse_get_double(&power_initial, A_surfxml_host_availability);
659   surf_parse_get_trace(&power_trace, A_surfxml_host_availability_file);
660
661   xbt_assert0((A_surfxml_host_state == A_surfxml_host_state_ON) ||
662               (A_surfxml_host_state == A_surfxml_host_state_OFF),
663               "Invalid state");
664   if (A_surfxml_host_state == A_surfxml_host_state_ON)
665     state_initial = SURF_CPU_ON;
666   if (A_surfxml_host_state == A_surfxml_host_state_OFF)
667     state_initial = SURF_CPU_OFF;
668   surf_parse_get_trace(&state_trace, A_surfxml_host_state_file);
669
670   current_property_set = xbt_dict_new();
671   cpu_new(A_surfxml_host_id, power_scale, power_initial, power_trace,
672           state_initial, state_trace, current_property_set);
673 }
674
675 static void link_free(void *nw_link)
676 {
677   xbt_dict_free(&(((link_L07_t) nw_link)->properties));
678   surf_resource_free(nw_link);
679 }
680
681 static link_L07_t link_new(char *name,
682                            double bw_initial,
683                            tmgr_trace_t bw_trace,
684                            double lat_initial,
685                            tmgr_trace_t lat_trace,
686                            e_surf_link_state_t
687                            state_initial,
688                            tmgr_trace_t state_trace,
689                            e_surf_link_sharing_policy_t
690                            policy, xbt_dict_t properties)
691 {
692   link_L07_t nw_link = xbt_new0(s_link_L07_t, 1);
693   xbt_assert1(!xbt_dict_get_or_null(link_set, name),
694               "Link '%s' declared several times in the platform file.", name);
695
696   nw_link->generic_resource.model = surf_workstation_model;
697   nw_link->type = SURF_WORKSTATION_RESOURCE_LINK;
698   nw_link->generic_resource.name = name;
699   nw_link->bw_current = bw_initial;
700   if (bw_trace)
701     nw_link->bw_event =
702       tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
703   nw_link->state_current = state_initial;
704   nw_link->lat_current = lat_initial;
705   if (lat_trace)
706     nw_link->lat_event =
707       tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
708   if (state_trace)
709     nw_link->state_event =
710       tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
711
712   nw_link->constraint =
713     lmm_constraint_new(ptask_maxmin_system, nw_link, nw_link->bw_current);
714
715   if (policy == SURF_LINK_FATPIPE)
716     lmm_constraint_shared(nw_link->constraint);
717
718   nw_link->properties = properties;
719
720   xbt_dict_set(link_set, name, nw_link, link_free);
721
722   return nw_link;
723 }
724
725 static void parse_link_init(void)
726 {
727   char *name_link;
728   double bw_initial;
729   tmgr_trace_t bw_trace;
730   double lat_initial;
731   tmgr_trace_t lat_trace;
732   e_surf_link_state_t state_initial_link = SURF_LINK_ON;
733   e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
734   tmgr_trace_t state_trace;
735
736   name_link = xbt_strdup(A_surfxml_link_id);
737   surf_parse_get_double(&bw_initial, A_surfxml_link_bandwidth);
738   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
739   surf_parse_get_double(&lat_initial, A_surfxml_link_latency);
740   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
741
742   xbt_assert0((A_surfxml_link_state == A_surfxml_link_state_ON)
743               || (A_surfxml_link_state ==
744                   A_surfxml_link_state_OFF), "Invalid state");
745   if (A_surfxml_link_state == A_surfxml_link_state_ON)
746     state_initial_link = SURF_LINK_ON;
747   else if (A_surfxml_link_state == A_surfxml_link_state_OFF)
748     state_initial_link = SURF_LINK_OFF;
749
750   if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_SHARED)
751     policy_initial_link = SURF_LINK_SHARED;
752   else if (A_surfxml_link_sharing_policy ==
753            A_surfxml_link_sharing_policy_FATPIPE)
754     policy_initial_link = SURF_LINK_FATPIPE;
755
756   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
757
758   current_property_set = xbt_dict_new();
759   link_new(name_link, bw_initial, bw_trace, lat_initial, lat_trace,
760            state_initial_link, state_trace, policy_initial_link,
761            current_property_set);
762 }
763
764 static void add_traces(void)
765 {
766   xbt_dict_cursor_t cursor = NULL;
767   char *trace_name, *elm;
768
769   if (!trace_connect_list_host_avail)
770     return;
771
772   /* Connect traces relative to cpu */
773   xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
774     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
775     cpu_L07_t host = surf_model_resource_by_name(surf_workstation_model, elm);
776
777     xbt_assert1(host, "Host %s undefined", elm);
778     xbt_assert1(trace, "Trace %s undefined", trace_name);
779
780     host->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, host);
781   }
782
783   xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
784     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
785     cpu_L07_t host = surf_model_resource_by_name(surf_workstation_model, elm);
786
787     xbt_assert1(host, "Host %s undefined", elm);
788     xbt_assert1(trace, "Trace %s undefined", trace_name);
789
790     host->power_event = tmgr_history_add_trace(history, trace, 0.0, 0, host);
791   }
792
793   /* Connect traces relative to network */
794   xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
795     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
796     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
797
798     xbt_assert1(link, "Link %s undefined", elm);
799     xbt_assert1(trace, "Trace %s undefined", trace_name);
800
801     link->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
802   }
803
804   xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
805     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
806     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
807
808     xbt_assert1(link, "Link %s undefined", elm);
809     xbt_assert1(trace, "Trace %s undefined", trace_name);
810
811     link->bw_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
812   }
813
814   xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
815     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
816     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
817
818     xbt_assert1(link, "Link %s undefined", elm);
819     xbt_assert1(trace, "Trace %s undefined", trace_name);
820
821     link->lat_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
822   }
823 }
824
825 static void define_callbacks(const char *file)
826 {
827   /* Adding callback functions */
828   surf_parse_reset_parser();
829   surfxml_add_callback(STag_surfxml_host_cb_list, &parse_cpu_init);
830   surfxml_add_callback(STag_surfxml_link_cb_list, &parse_link_init);
831   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_traces);
832 }
833
834
835 /**************************************/
836 /********* Module  creation ***********/
837 /**************************************/
838
839 static void model_init_internal(void)
840 {
841   surf_workstation_model = surf_model_init();
842
843   surf_workstation_model->action_unref = action_unref;
844   surf_workstation_model->action_cancel = action_cancel;
845   surf_workstation_model->action_state_set = surf_action_state_set;
846   surf_workstation_model->suspend = action_suspend;
847   surf_workstation_model->resume = action_resume;
848   surf_workstation_model->is_suspended = action_is_suspended;
849   surf_workstation_model->set_max_duration = action_set_max_duration;
850   surf_workstation_model->set_priority = action_set_priority;
851   surf_workstation_model->name = "Workstation ptask_L07";
852
853   surf_workstation_model->model_private->resource_used = resource_used;
854   surf_workstation_model->model_private->share_resources = share_resources;
855   surf_workstation_model->model_private->update_actions_state =
856     update_actions_state;
857   surf_workstation_model->model_private->update_resource_state =
858     update_resource_state;
859   surf_workstation_model->model_private->finalize = finalize;
860
861   surf_workstation_model->extension.workstation.execute = execute;
862   surf_workstation_model->extension.workstation.sleep = action_sleep;
863   surf_workstation_model->extension.workstation.get_state =
864     resource_get_state;
865   surf_workstation_model->extension.workstation.get_speed = get_speed;
866   surf_workstation_model->extension.workstation.get_available_speed =
867     get_available_speed;
868   surf_workstation_model->extension.workstation.communicate = communicate;
869   surf_workstation_model->extension.workstation.get_route = get_route;
870   surf_workstation_model->extension.workstation.execute_parallel_task =
871     execute_parallel_task;
872   surf_workstation_model->extension.workstation.get_link_bandwidth =
873     get_link_bandwidth;
874   surf_workstation_model->extension.workstation.get_link_latency =
875     get_link_latency;
876   surf_workstation_model->extension.workstation.link_shared = link_shared;
877
878   surf_workstation_model->get_properties = get_properties;
879
880   link_set = xbt_dict_new();
881
882   if (!ptask_maxmin_system)
883     ptask_maxmin_system = lmm_system_new();
884
885   routing_model_full_create(sizeof(link_L07_t),
886         link_new(xbt_strdup("__MSG_loopback__"),
887             498000000, NULL, 0.000015, NULL,
888             SURF_LINK_ON, NULL, SURF_LINK_FATPIPE, NULL));
889
890 }
891
892 /**************************************/
893 /*************** Generic **************/
894 /**************************************/
895 void surf_workstation_model_init_ptask_L07(const char *filename)
896 {
897   xbt_assert0(!surf_cpu_model, "CPU model type already defined");
898   xbt_assert0(!surf_network_model, "network model type already defined");
899   define_callbacks(filename);
900   model_init_internal();
901
902   update_model_description(surf_workstation_model_description,
903                            "ptask_L07", surf_workstation_model);
904   xbt_dynar_push(model_list, &surf_workstation_model);
905 }