Logo AND Algorithmique Numérique Distribuée

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