Logo AND Algorithmique Numérique Distribuée

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