Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Surf: factorize resource sets into common_public
[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->common_public.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->common_public.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_model_t)surf_workstation_model);
421
422   free(surf_workstation_model->extension_public);
423
424   free(surf_workstation_model);
425   surf_workstation_model = NULL;
426
427   for (i = 0; i < nb_workstation; i++)
428     for (j = 0; j < nb_workstation; j++)
429       free(ROUTE(i, j).links);
430   free(routing_table);
431   routing_table = NULL;
432   nb_workstation = 0;
433
434   if (ptask_maxmin_system) {
435     lmm_system_free(ptask_maxmin_system);
436     ptask_maxmin_system = NULL;
437   }
438 }
439
440 /**************************************/
441 /******* Resource Private    **********/
442 /**************************************/
443
444 static e_surf_cpu_state_t resource_get_state(void *cpu)
445 {
446   return ((cpu_L07_t) cpu)->state_current;
447 }
448
449 static double get_speed(void *cpu, double load)
450 {
451   return load * (((cpu_L07_t) cpu)->power_scale);
452 }
453
454 static double get_available_speed(void *cpu)
455 {
456   return ((cpu_L07_t) cpu)->power_current;
457 }
458
459 static surf_action_t execute_parallel_task(int workstation_nb,
460                                            void **workstation_list,
461                                            double *computation_amount,
462                                            double *communication_amount,
463                                            double amount, double rate)
464 {
465   surf_action_workstation_L07_t action = NULL;
466   int i, j, k;
467   int nb_link = 0;
468   int nb_host = 0;
469   double latency = 0.0;
470
471   if (parallel_task_link_set == NULL)
472     parallel_task_link_set = xbt_dict_new();
473
474   xbt_dict_reset(parallel_task_link_set);
475
476   /* Compute the number of affected resources... */
477   for (i = 0; i < workstation_nb; i++) {
478     for (j = 0; j < workstation_nb; j++) {
479       cpu_L07_t card_src = workstation_list[i];
480       cpu_L07_t card_dst = workstation_list[j];
481       int route_size = ROUTE(card_src->id, card_dst->id).size;
482       link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
483       double lat = 0.0;
484
485       if (communication_amount[i * workstation_nb + j] > 0)
486         for (k = 0; k < route_size; k++) {
487           lat += route[k]->lat_current;
488           xbt_dict_set(parallel_task_link_set, route[k]->name,
489                        route[k], NULL);
490         }
491       latency = MAX(latency, lat);
492     }
493   }
494
495   nb_link = xbt_dict_length(parallel_task_link_set);
496   xbt_dict_reset(parallel_task_link_set);
497
498   for (i = 0; i < workstation_nb; i++)
499     if (computation_amount[i] > 0)
500       nb_host++;
501
502   action = xbt_new0(s_surf_action_workstation_L07_t, 1);
503   DEBUG3("Creating a parallel task (%p) with %d cpus and %d links.",
504          action, workstation_nb, nb_link);
505   action->generic_action.refcount = 1;
506   action->generic_action.cost = amount;
507   action->generic_action.remains = amount;
508   action->generic_action.max_duration = NO_MAX_DURATION;
509   action->generic_action.start = surf_get_clock();
510   action->generic_action.finish = -1.0;
511   action->generic_action.model_type = (surf_model_t) surf_workstation_model;
512   action->suspended = 0;        /* Should be useless because of the
513                                    calloc but it seems to help valgrind... */
514   action->workstation_nb = workstation_nb;
515   action->workstation_list = (cpu_L07_t *) workstation_list;
516   action->computation_amount = computation_amount;
517   action->communication_amount = communication_amount;
518   action->latency = latency;
519   action->generic_action.state_set =
520     surf_workstation_model->common_public.states.running_action_set;
521
522   xbt_swag_insert(action, action->generic_action.state_set);
523   action->rate = rate;
524
525   action->variable =
526     lmm_variable_new(ptask_maxmin_system, action, 1.0,
527                      (action->rate > 0) ? action->rate : -1.0,
528                      workstation_nb + nb_link);
529
530   if (action->latency > 0)
531     lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
532
533   for (i = 0; i < workstation_nb; i++)
534     lmm_expand(ptask_maxmin_system,
535                ((cpu_L07_t) workstation_list[i])->constraint,
536                action->variable, computation_amount[i]);
537
538   for (i = 0; i < workstation_nb; i++) {
539     for (j = 0; j < workstation_nb; j++) {
540       cpu_L07_t card_src = workstation_list[i];
541       cpu_L07_t card_dst = workstation_list[j];
542       int route_size = ROUTE(card_src->id, card_dst->id).size;
543       link_L07_t *route = ROUTE(card_src->id, card_dst->id).links;
544
545       if (communication_amount[i * workstation_nb + j] == 0.0)
546         continue;
547       for (k = 0; k < route_size; k++) {
548         lmm_expand_add(ptask_maxmin_system, route[k]->constraint,
549                        action->variable,
550                        communication_amount[i * workstation_nb + j]);
551       }
552     }
553   }
554
555   if (nb_link + nb_host == 0) {
556     action->generic_action.cost = 1.0;
557     action->generic_action.remains = 0.0;
558   }
559
560   return (surf_action_t) action;
561 }
562
563 static surf_action_t execute(void *cpu, double size)
564 {
565   void **workstation_list = xbt_new0(void *, 1);
566   double *computation_amount = xbt_new0(double, 1);
567   double *communication_amount = xbt_new0(double, 1);
568
569   workstation_list[0] = cpu;
570   communication_amount[0] = 0.0;
571   computation_amount[0] = size;
572
573   return execute_parallel_task(1, workstation_list, computation_amount,
574                                communication_amount, 1, -1);
575 }
576
577 static surf_action_t communicate(void *src, void *dst, double size,
578                                  double rate)
579 {
580   void **workstation_list = xbt_new0(void *, 2);
581   double *computation_amount = xbt_new0(double, 2);
582   double *communication_amount = xbt_new0(double, 4);
583   surf_action_t res = NULL;
584
585   workstation_list[0] = src;
586   workstation_list[1] = dst;
587   communication_amount[1] = size;
588
589   res = execute_parallel_task(2, workstation_list,
590                               computation_amount, communication_amount,
591                               1, rate);
592
593   return res;
594 }
595
596 static surf_action_t action_sleep(void *cpu, double duration)
597 {
598   surf_action_workstation_L07_t action = NULL;
599
600   XBT_IN2("(%s,%g)", ((cpu_L07_t) cpu)->name, duration);
601
602   action = (surf_action_workstation_L07_t) execute(cpu, 1.0);
603   action->generic_action.max_duration = duration;
604   action->suspended = 2;
605   lmm_update_variable_weight(ptask_maxmin_system, action->variable, 0.0);
606
607   XBT_OUT;
608   return (surf_action_t) action;
609 }
610
611 /* returns an array of link_L07_t */
612 static const void **get_route(void *src, void *dst)
613 {
614   cpu_L07_t card_src = src;
615   cpu_L07_t card_dst = dst;
616   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
617
618   return (const void **) route->links;
619 }
620
621 static int get_route_size(void *src, void *dst)
622 {
623   cpu_L07_t card_src = src;
624   cpu_L07_t card_dst = dst;
625   route_L07_t route = &(ROUTE(card_src->id, card_dst->id));
626   return route->size;
627 }
628
629 static const char *get_link_name(const void *link)
630 {
631   return ((link_L07_t) link)->name;
632 }
633
634 static double get_link_bandwidth(const void *link)
635 {
636   return ((link_L07_t) link)->bw_current;
637 }
638
639 static double get_link_latency(const void *link)
640 {
641   return ((link_L07_t) link)->lat_current;
642 }
643
644 static int link_shared(const void *link)
645 {
646   return lmm_constraint_is_shared(((link_L07_t) link)->constraint);
647 }
648
649 /**************************************/
650 /*** Resource Creation & Destruction **/
651 /**************************************/
652
653 static void cpu_free(void *cpu)
654 {
655   free(((cpu_L07_t) cpu)->name);
656   xbt_dict_free(&(((cpu_L07_t) cpu)->properties));
657   free(cpu);
658 }
659
660 static cpu_L07_t cpu_new(const char *name, double power_scale,
661                          double power_initial,
662                          tmgr_trace_t power_trace,
663                          e_surf_cpu_state_t state_initial,
664                          tmgr_trace_t state_trace, xbt_dict_t cpu_properties)
665 {
666   cpu_L07_t cpu = xbt_new0(s_cpu_L07_t, 1);
667   xbt_assert1(!surf_model_resource_by_name(surf_workstation_model, name),
668               "Host '%s' declared several times in the platform file.", name);
669
670   cpu->model = (surf_model_t) surf_workstation_model;
671   cpu->type = SURF_WORKSTATION_RESOURCE_CPU;
672   cpu->name = xbt_strdup(name);
673   cpu->id = nb_workstation++;
674
675   cpu->power_scale = power_scale;
676   xbt_assert0(cpu->power_scale > 0, "Power has to be >0");
677
678   cpu->power_current = power_initial;
679   if (power_trace)
680     cpu->power_event =
681       tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
682
683   cpu->state_current = state_initial;
684   if (state_trace)
685     cpu->state_event =
686       tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
687
688   cpu->constraint =
689     lmm_constraint_new(ptask_maxmin_system, cpu,
690                        cpu->power_current * cpu->power_scale);
691
692   /*add the property set */
693   cpu->properties = current_property_set;
694
695   xbt_dict_set(surf_model_resource_set(surf_workstation_model), name, cpu, cpu_free);
696
697   return cpu;
698 }
699
700 static void create_routing_table(void)
701 {
702   routing_table = xbt_new0(s_route_L07_t, nb_workstation * nb_workstation);
703 }
704
705 static void parse_cpu_init(void)
706 {
707   double power_scale = 0.0;
708   double power_initial = 0.0;
709   tmgr_trace_t power_trace = NULL;
710   e_surf_cpu_state_t state_initial = SURF_CPU_OFF;
711   tmgr_trace_t state_trace = NULL;
712
713   power_scale = get_cpu_power(A_surfxml_host_power);
714   surf_parse_get_double(&power_initial, A_surfxml_host_availability);
715   surf_parse_get_trace(&power_trace, A_surfxml_host_availability_file);
716
717   xbt_assert0((A_surfxml_host_state == A_surfxml_host_state_ON) ||
718               (A_surfxml_host_state == A_surfxml_host_state_OFF),
719               "Invalid state");
720   if (A_surfxml_host_state == A_surfxml_host_state_ON)
721     state_initial = SURF_CPU_ON;
722   if (A_surfxml_host_state == A_surfxml_host_state_OFF)
723     state_initial = SURF_CPU_OFF;
724   surf_parse_get_trace(&state_trace, A_surfxml_host_state_file);
725
726   current_property_set = xbt_dict_new();
727   cpu_new(A_surfxml_host_id, power_scale, power_initial, power_trace,
728           state_initial, state_trace, current_property_set);
729 }
730
731 static void link_free(void *nw_link)
732 {
733   free(((link_L07_t) nw_link)->name);
734   xbt_dict_free(&(((link_L07_t) nw_link)->properties));
735   free(nw_link);
736 }
737
738 static link_L07_t link_new(char *name,
739                            double bw_initial,
740                            tmgr_trace_t bw_trace,
741                            double lat_initial,
742                            tmgr_trace_t lat_trace,
743                            e_surf_link_state_t
744                            state_initial,
745                            tmgr_trace_t state_trace,
746                            e_surf_link_sharing_policy_t
747                            policy, xbt_dict_t properties)
748 {
749   link_L07_t nw_link = xbt_new0(s_link_L07_t, 1);
750   xbt_assert1(!xbt_dict_get_or_null(link_set, name),
751               "Link '%s' declared several times in the platform file.", name);
752
753   nw_link->model = (surf_model_t) surf_workstation_model;
754   nw_link->type = SURF_WORKSTATION_RESOURCE_LINK;
755   nw_link->name = name;
756   nw_link->bw_current = bw_initial;
757   if (bw_trace)
758     nw_link->bw_event =
759       tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
760   nw_link->state_current = state_initial;
761   nw_link->lat_current = lat_initial;
762   if (lat_trace)
763     nw_link->lat_event =
764       tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
765   if (state_trace)
766     nw_link->state_event =
767       tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
768
769   nw_link->constraint =
770     lmm_constraint_new(ptask_maxmin_system, nw_link, nw_link->bw_current);
771
772   if (policy == SURF_LINK_FATPIPE)
773     lmm_constraint_shared(nw_link->constraint);
774
775   nw_link->properties = properties;
776
777   xbt_dict_set(link_set, name, nw_link, link_free);
778
779   return nw_link;
780 }
781
782 static void parse_link_init(void)
783 {
784   char *name_link;
785   double bw_initial;
786   tmgr_trace_t bw_trace;
787   double lat_initial;
788   tmgr_trace_t lat_trace;
789   e_surf_link_state_t state_initial_link = SURF_LINK_ON;
790   e_surf_link_sharing_policy_t policy_initial_link = SURF_LINK_SHARED;
791   tmgr_trace_t state_trace;
792
793   name_link = xbt_strdup(A_surfxml_link_id);
794   surf_parse_get_double(&bw_initial, A_surfxml_link_bandwidth);
795   surf_parse_get_trace(&bw_trace, A_surfxml_link_bandwidth_file);
796   surf_parse_get_double(&lat_initial, A_surfxml_link_latency);
797   surf_parse_get_trace(&lat_trace, A_surfxml_link_latency_file);
798
799   xbt_assert0((A_surfxml_link_state == A_surfxml_link_state_ON)
800               || (A_surfxml_link_state ==
801                   A_surfxml_link_state_OFF), "Invalid state");
802   if (A_surfxml_link_state == A_surfxml_link_state_ON)
803     state_initial_link = SURF_LINK_ON;
804   else if (A_surfxml_link_state == A_surfxml_link_state_OFF)
805     state_initial_link = SURF_LINK_OFF;
806
807   if (A_surfxml_link_sharing_policy == A_surfxml_link_sharing_policy_SHARED)
808     policy_initial_link = SURF_LINK_SHARED;
809   else if (A_surfxml_link_sharing_policy ==
810            A_surfxml_link_sharing_policy_FATPIPE)
811     policy_initial_link = SURF_LINK_FATPIPE;
812
813   surf_parse_get_trace(&state_trace, A_surfxml_link_state_file);
814
815   current_property_set = xbt_dict_new();
816   link_new(name_link, bw_initial, bw_trace, lat_initial, lat_trace,
817            state_initial_link, state_trace, policy_initial_link,
818            current_property_set);
819 }
820
821 static void route_new(int src_id, int dst_id,
822                       link_L07_t * link_list, int nb_link)
823 {
824   route_L07_t route = &(ROUTE(src_id, dst_id));
825
826   route->size = nb_link;
827   route->links = link_list =
828     xbt_realloc(link_list, sizeof(link_L07_t) * nb_link);
829 }
830
831
832 static int src_id = -1;
833 static int dst_id = -1;
834
835 static void parse_route_set_endpoints(void)
836 {
837   cpu_L07_t cpu_tmp = NULL;
838
839   cpu_tmp = (cpu_L07_t) surf_model_resource_by_name(surf_workstation_model, A_surfxml_route_src);
840   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_src);
841   if (cpu_tmp != NULL)
842     src_id = cpu_tmp->id;
843
844   cpu_tmp = (cpu_L07_t) surf_model_resource_by_name(surf_workstation_model, A_surfxml_route_dst);
845   xbt_assert1(cpu_tmp, "Invalid cpu %s", A_surfxml_route_dst);
846   if (cpu_tmp != NULL)
847     dst_id = cpu_tmp->id;
848
849   route_action = A_surfxml_route_action;
850 }
851
852 static void parse_route_set_route(void)
853 {
854   char *name;
855   if (src_id != -1 && dst_id != -1) {
856     name = bprintf("%x#%x", src_id, dst_id);
857     manage_route(route_table, name, route_action, 0);
858     free(name);
859   }
860 }
861
862 static void add_loopback(void)
863 {
864   int i;
865
866   /* Adding loopback if needed */
867   for (i = 0; i < nb_workstation; i++)
868     if (!ROUTE(i, i).size) {
869       if (!loopback)
870         loopback = link_new(xbt_strdup("__MSG_loopback__"),
871                             498000000, NULL, 0.000015, NULL,
872                             SURF_LINK_ON, NULL, SURF_LINK_FATPIPE, NULL);
873
874       ROUTE(i, i).size = 1;
875       ROUTE(i, i).links = xbt_new0(link_L07_t, 1);
876       ROUTE(i, i).links[0] = loopback;
877     }
878 }
879
880 static void add_route(void)
881 {
882   xbt_ex_t e;
883   int nb_link = 0;
884   unsigned int cpt = 0;
885   int link_list_capacity = 0;
886   link_L07_t *link_list = NULL;
887   xbt_dict_cursor_t cursor = NULL;
888   char *key, *data, *end;
889   const char *sep = "#";
890   xbt_dynar_t links, keys;
891   char *link = NULL;
892
893   if (routing_table == NULL)
894     create_routing_table();
895
896   xbt_dict_foreach(route_table, cursor, key, data) {
897     nb_link = 0;
898     links = (xbt_dynar_t) data;
899     keys = xbt_str_split_str(key, sep);
900
901     src_id = strtol(xbt_dynar_get_as(keys, 0, char *), &end, 16);
902     dst_id = strtol(xbt_dynar_get_as(keys, 1, char *), &end, 16);
903     xbt_dynar_free(&keys);
904
905     link_list_capacity = xbt_dynar_length(links);
906     link_list = xbt_new(link_L07_t, link_list_capacity);
907
908
909     xbt_dynar_foreach(links, cpt, link) {
910       TRY {
911         link_list[nb_link++] = xbt_dict_get(link_set, link);
912       }
913       CATCH(e) {
914         RETHROW1("Link %s not found (dict raised this exception: %s)", link);
915       }
916     }
917     route_new(src_id, dst_id, link_list, nb_link);
918   }
919 }
920
921 static void add_traces(void)
922 {
923   xbt_dict_cursor_t cursor = NULL;
924   char *trace_name, *elm;
925
926   if (!trace_connect_list_host_avail)
927     return;
928
929   /* Connect traces relative to cpu */
930   xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
931     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
932     cpu_L07_t host = surf_model_resource_by_name(surf_workstation_model, elm);
933
934     xbt_assert1(host, "Host %s undefined", elm);
935     xbt_assert1(trace, "Trace %s undefined", trace_name);
936
937     host->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, host);
938   }
939
940   xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
941     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
942     cpu_L07_t host = surf_model_resource_by_name(surf_workstation_model, elm);
943
944     xbt_assert1(host, "Host %s undefined", elm);
945     xbt_assert1(trace, "Trace %s undefined", trace_name);
946
947     host->power_event = tmgr_history_add_trace(history, trace, 0.0, 0, host);
948   }
949
950   /* Connect traces relative to network */
951   xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
952     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
953     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
954
955     xbt_assert1(link, "Link %s undefined", elm);
956     xbt_assert1(trace, "Trace %s undefined", trace_name);
957
958     link->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
959   }
960
961   xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
962     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
963     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
964
965     xbt_assert1(link, "Link %s undefined", elm);
966     xbt_assert1(trace, "Trace %s undefined", trace_name);
967
968     link->bw_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
969   }
970
971   xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
972     tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
973     link_L07_t link = xbt_dict_get_or_null(link_set, elm);
974
975     xbt_assert1(link, "Link %s undefined", elm);
976     xbt_assert1(trace, "Trace %s undefined", trace_name);
977
978     link->lat_event = tmgr_history_add_trace(history, trace, 0.0, 0, link);
979   }
980 }
981
982 static void define_callbacks(const char *file)
983 {
984   /* Adding callback functions */
985   surf_parse_reset_parser();
986   surfxml_add_callback(STag_surfxml_host_cb_list, &parse_cpu_init);
987   surfxml_add_callback(STag_surfxml_link_cb_list, &parse_link_init);
988   surfxml_add_callback(STag_surfxml_route_cb_list,
989                        &parse_route_set_endpoints);
990   surfxml_add_callback(ETag_surfxml_route_cb_list, &parse_route_set_route);
991   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_route);
992   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_loopback);
993   surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_traces);
994 }
995
996
997 /**************************************/
998 /********* Module  creation ***********/
999 /**************************************/
1000
1001 static void model_init_internal(void)
1002 {
1003   surf_workstation_model = xbt_new0(s_surf_workstation_model_t, 1);
1004
1005   surf_model_init((surf_model_t)surf_workstation_model);
1006   surf_workstation_model->extension_public =
1007     xbt_new0(s_surf_workstation_model_extension_public_t, 1);
1008
1009   surf_workstation_model->common_public.get_resource_name =
1010     get_resource_name;
1011   surf_workstation_model->common_public.action_get_state =
1012     surf_action_get_state;
1013   surf_workstation_model->common_public.action_get_start_time =
1014     surf_action_get_start_time;
1015   surf_workstation_model->common_public.action_get_finish_time =
1016     surf_action_get_finish_time;
1017   surf_workstation_model->common_public.action_use = action_use;
1018   surf_workstation_model->common_public.action_free = action_free;
1019   surf_workstation_model->common_public.action_cancel = action_cancel;
1020   surf_workstation_model->common_public.action_change_state =
1021     surf_action_change_state;
1022   surf_workstation_model->common_public.action_set_data =
1023     surf_action_set_data;
1024   surf_workstation_model->common_public.suspend = action_suspend;
1025   surf_workstation_model->common_public.resume = action_resume;
1026   surf_workstation_model->common_public.is_suspended = action_is_suspended;
1027   surf_workstation_model->common_public.set_max_duration =
1028     action_set_max_duration;
1029   surf_workstation_model->common_public.set_priority = action_set_priority;
1030   surf_workstation_model->common_public.name = "Workstation ptask_L07";
1031
1032   surf_workstation_model->common_private->resource_used = resource_used;
1033   surf_workstation_model->common_private->share_resources = share_resources;
1034   surf_workstation_model->common_private->update_actions_state =
1035     update_actions_state;
1036   surf_workstation_model->common_private->update_resource_state =
1037     update_resource_state;
1038   surf_workstation_model->common_private->finalize = finalize;
1039
1040   surf_workstation_model->extension_public->execute = execute;
1041   surf_workstation_model->extension_public->sleep = action_sleep;
1042   surf_workstation_model->extension_public->get_state = resource_get_state;
1043   surf_workstation_model->extension_public->get_speed = get_speed;
1044   surf_workstation_model->extension_public->get_available_speed =
1045     get_available_speed;
1046   surf_workstation_model->extension_public->communicate = communicate;
1047   surf_workstation_model->extension_public->execute_parallel_task =
1048     execute_parallel_task;
1049   surf_workstation_model->extension_public->get_route = get_route;
1050   surf_workstation_model->extension_public->get_route_size = get_route_size;
1051   surf_workstation_model->extension_public->get_link_name = get_link_name;
1052   surf_workstation_model->extension_public->get_link_bandwidth =
1053     get_link_bandwidth;
1054   surf_workstation_model->extension_public->get_link_latency =
1055     get_link_latency;
1056   surf_workstation_model->extension_public->link_shared = link_shared;
1057
1058   surf_workstation_model->common_public.get_properties = get_properties;
1059
1060   link_set = xbt_dict_new();
1061
1062   if (!ptask_maxmin_system)
1063     ptask_maxmin_system = lmm_system_new();
1064 }
1065
1066 /**************************************/
1067 /*************** Generic **************/
1068 /**************************************/
1069 void surf_workstation_model_init_ptask_L07(const char *filename)
1070 {
1071   xbt_assert0(!surf_cpu_model, "CPU model type already defined");
1072   xbt_assert0(!surf_network_model, "network model type already defined");
1073   model_init_internal();
1074   define_callbacks(filename);
1075
1076   update_model_description(surf_workstation_model_description,
1077                            "ptask_L07",
1078                            (surf_model_t) surf_workstation_model);
1079   xbt_dynar_push(model_list, &surf_workstation_model);
1080 }