Logo AND Algorithmique Numérique Distribuée

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