Logo AND Algorithmique Numérique Distribuée

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