Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
check this constraint exists before testing something on it
[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(workstation_KCCFLN05, 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 static 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
112     if(src) {
113       xbt_dynar_foreach(src->outgoing_communications, cpt, act)
114         if (act == action) {
115           xbt_dynar_remove_at(src->outgoing_communications, cpt, &act);
116           
117           break;
118         }    
119       if(!xbt_dynar_length(src->outgoing_communications))
120         __update_cpu_usage(src);
121     }
122     if(dst) {
123       xbt_dynar_foreach(dst->incomming_communications, cpt, act)
124         if (act == action) {
125           xbt_dynar_remove_at(dst->incomming_communications, cpt, &act);
126           break;
127         }
128       if(!xbt_dynar_length(dst->incomming_communications))
129         __update_cpu_usage(dst);
130     }
131     free(action);
132     return 1;
133   }
134   return 0;
135 }
136
137 static void action_cancel(surf_action_t action)
138 {
139   surf_action_change_state(action, SURF_ACTION_FAILED);
140   return;
141 }
142
143 static void action_recycle(surf_action_t action)
144 {
145   DIE_IMPOSSIBLE;
146   return;
147 }
148
149 /* action_change_state is inherited from the surf module */
150 /* action_set_data is inherited from the surf module */
151
152 static void action_suspend(surf_action_t action)
153 {
154   XBT_IN1("(%p))",action);
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   lmm_update_variable_weight(maxmin_system,
165                              ((surf_action_workstation_KCCFLN05_t)
166                               action)->variable, 1.0);
167   XBT_OUT;
168 }
169
170 static int action_is_suspended(surf_action_t action)
171 {
172   return (lmm_get_variable_weight
173           (((surf_action_workstation_KCCFLN05_t) action)->variable) ==
174           0.0);
175 }
176
177 static void action_set_max_duration(surf_action_t action, double duration)
178 {                               /* FIXME: should inherit */
179   XBT_IN2("(%p,%g)",action,duration);
180   action->max_duration = duration;
181   XBT_OUT;
182 }
183
184
185 static void action_set_priority(surf_action_t action, double priority)
186 {                               /* FIXME: should inherit */
187   XBT_IN2("(%p,%g)",action,priority);
188   action->priority = priority;
189   XBT_OUT;
190 }
191
192 /**************************************/
193 /******* Resource Private    **********/
194 /**************************************/
195
196 static int resource_used(void *resource_id)
197 {
198   /* We can freely cast as a network_link_KCCFLN05_t because it has
199      the same prefix as cpu_KCCFLN05_t */
200   if(((cpu_KCCFLN05_t) resource_id)->type == SURF_WORKSTATION_RESOURCE_CPU)
201     return (lmm_constraint_used(maxmin_system,
202                                ((cpu_KCCFLN05_t) resource_id)->
203                                constraint) || 
204             ((((cpu_KCCFLN05_t) resource_id)->bus)?
205              lmm_constraint_used(maxmin_system,
206                                 ((cpu_KCCFLN05_t) resource_id)->
207                                 bus):0));
208   else 
209     return lmm_constraint_used(maxmin_system,
210                                ((network_link_KCCFLN05_t) resource_id)->
211                                constraint);
212
213 }
214
215 static double share_resources(double now)
216 {
217   s_surf_action_workstation_KCCFLN05_t s_action;
218   surf_action_workstation_KCCFLN05_t action = NULL;
219
220   xbt_swag_t running_actions = surf_workstation_resource->common_public->states.running_action_set;
221   double min = generic_maxmin_share_resources(running_actions,
222                                               xbt_swag_offset(s_action, variable));
223
224   xbt_swag_foreach(action, running_actions) {
225     if(action->latency>0) {
226       if(min<0) min = action->latency;
227       else if (action->latency<min) min = action->latency;
228     }
229   }
230
231   return min;
232 /*   return generic_maxmin_share_resources(surf_workstation_resource->common_public-> */
233 /*                                      states.running_action_set, */
234 /*                                      xbt_swag_offset(action, variable)); */
235 }
236
237 static void update_actions_state(double now, double delta)
238 {
239   double deltap = 0.0;
240   surf_action_workstation_KCCFLN05_t action = NULL;
241   surf_action_workstation_KCCFLN05_t next_action = NULL;
242   xbt_swag_t running_actions =
243       surf_workstation_resource->common_public->states.running_action_set;
244
245   xbt_swag_foreach_safe(action, next_action, running_actions) {
246     deltap = delta;
247     if (action->latency > 0) {
248       if (action->latency > deltap) {
249         surf_double_update(&(action->latency), deltap);
250         deltap = 0.0;
251       } else {
252         surf_double_update(&(deltap), action->latency);
253         action->latency = 0.0;
254       }
255       if ((action->latency == 0.0) && !(action->suspended))
256         lmm_update_variable_weight(maxmin_system, action->variable, 1.0);
257     }
258     surf_double_update(&(action->generic_action.remains),
259                        lmm_variable_getvalue(action->variable) * deltap);
260     if (action->generic_action.max_duration != NO_MAX_DURATION)
261       surf_double_update(&(action->generic_action.max_duration), delta);
262
263     /*   if(action->generic_action.remains<.00001) action->generic_action.remains=0; */
264
265     if ((action->generic_action.remains <= 0) && 
266         (lmm_get_variable_weight(action->variable)>0)) {
267       action->generic_action.finish = surf_get_clock();
268       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
269     } else if ((action->generic_action.max_duration != NO_MAX_DURATION) &&
270                (action->generic_action.max_duration <= 0)) {
271       action->generic_action.finish = surf_get_clock();
272       surf_action_change_state((surf_action_t) action, SURF_ACTION_DONE);
273     } else {                    /* Need to check that none of the resource has failed */
274       lmm_constraint_t cnst = NULL;
275       int i = 0;
276       void *constraint_id = NULL;
277
278       while ((cnst =
279               lmm_get_cnst_from_var(maxmin_system, action->variable,
280                                     i++))) {
281         constraint_id = lmm_constraint_id(cnst);
282         if(((((network_link_KCCFLN05_t)constraint_id)->type==
283              SURF_WORKSTATION_RESOURCE_LINK) &&
284             (((network_link_KCCFLN05_t)constraint_id)->state_current==
285              SURF_NETWORK_LINK_OFF)) ||
286            ((((cpu_KCCFLN05_t)constraint_id)->type==
287              SURF_WORKSTATION_RESOURCE_CPU) &&
288             (((cpu_KCCFLN05_t)constraint_id)->state_current==
289              SURF_CPU_OFF))) {
290           action->generic_action.finish = surf_get_clock();
291           surf_action_change_state((surf_action_t) action, SURF_ACTION_FAILED);
292           break;
293         }
294       }
295     }
296   }
297   return;
298 }
299
300 static void update_resource_state(void *id,
301                                   tmgr_trace_event_t event_type,
302                                   double value)
303 {
304   cpu_KCCFLN05_t cpu = id;
305   network_link_KCCFLN05_t nw_link = id ;
306
307   if(nw_link->type == SURF_WORKSTATION_RESOURCE_LINK) {
308     if (event_type == nw_link->bw_event) {
309       nw_link->bw_current = value;
310       lmm_update_constraint_bound(maxmin_system, nw_link->constraint,
311                                   nw_link->bw_current);
312     } else if (event_type == nw_link->lat_event) {
313       double delta = value - nw_link->lat_current;
314       lmm_variable_t var = NULL;
315       surf_action_workstation_KCCFLN05_t action = NULL;
316       
317       nw_link->lat_current = value;
318       while (lmm_get_var_from_cnst(maxmin_system, nw_link->constraint, &var)) {
319         action = lmm_variable_id(var);
320         action->lat_current += delta;
321         if(action->rate<0)
322           lmm_update_variable_bound(maxmin_system, action->variable,
323                                     SG_TCP_CTE_GAMMA / (2.0 * action->lat_current));
324         else 
325           lmm_update_variable_bound(maxmin_system, action->variable,
326                                     min(action->rate,SG_TCP_CTE_GAMMA / (2.0 * action->lat_current)));
327       }
328     } else if (event_type == nw_link->state_event) {
329       if (value > 0)
330         nw_link->state_current = SURF_NETWORK_LINK_ON;
331       else
332         nw_link->state_current = SURF_NETWORK_LINK_OFF;
333     } else {
334       CRITICAL0("Unknown event ! \n");
335       xbt_abort();
336     }
337     return;
338   } else if(cpu->type == SURF_WORKSTATION_RESOURCE_CPU) {
339     if (event_type == cpu->power_event) {
340       cpu->power_current = value;
341       __update_cpu_usage(cpu);
342     } else if (event_type == cpu->state_event) {
343       if (value > 0)
344         cpu->state_current = SURF_CPU_ON;
345       else
346         cpu->state_current = SURF_CPU_OFF;
347     } else {
348       CRITICAL0("Unknown event ! \n");
349       xbt_abort();
350     }    
351     return;
352   } else {
353     DIE_IMPOSSIBLE;
354   }
355   return;
356 }
357
358 static void finalize(void)
359 {
360   int i,j;
361
362   xbt_dict_free(&network_link_set);
363   xbt_dict_free(&workstation_set);
364   xbt_swag_free(surf_workstation_resource->common_public->states.
365                 ready_action_set);
366   xbt_swag_free(surf_workstation_resource->common_public->states.
367                 running_action_set);
368   xbt_swag_free(surf_workstation_resource->common_public->states.
369                 failed_action_set);
370   xbt_swag_free(surf_workstation_resource->common_public->states.
371                 done_action_set);
372
373   free(surf_workstation_resource->common_public);
374   free(surf_workstation_resource->common_private);
375   free(surf_workstation_resource->extension_public);
376
377   free(surf_workstation_resource);
378   surf_workstation_resource = NULL;
379
380   for (i = 0; i < nb_workstation; i++)
381     for (j = 0; j < nb_workstation; j++)
382       free(ROUTE(i, j).links);
383   free(routing_table);
384   routing_table = NULL;
385   nb_workstation = 0;
386
387   if (maxmin_system) {
388     lmm_system_free(maxmin_system);
389     maxmin_system = NULL;
390   }
391 }
392
393 /**************************************/
394 /******* Resource Private    **********/
395 /**************************************/
396
397 static surf_action_t execute(void *cpu, double size)
398 {
399   surf_action_workstation_KCCFLN05_t action = NULL;
400   cpu_KCCFLN05_t CPU = cpu;
401
402   XBT_IN2("(%s,%g)",CPU->name,size);
403   action = xbt_new0(s_surf_action_workstation_KCCFLN05_t, 1);
404
405   action->generic_action.using = 1;
406   action->generic_action.cost = size;
407   action->generic_action.remains = size;
408   action->generic_action.priority = 1.0;
409   action->generic_action.max_duration = NO_MAX_DURATION;
410   action->generic_action.start = surf_get_clock();
411   action->generic_action.finish = -1.0;
412   action->generic_action.resource_type =
413       (surf_resource_t) surf_workstation_resource;
414
415   if (CPU->state_current == SURF_CPU_ON)
416     action->generic_action.state_set =
417         surf_workstation_resource->common_public->states.running_action_set;
418   else
419     action->generic_action.state_set =
420         surf_workstation_resource->common_public->states.failed_action_set;
421   xbt_swag_insert(action, action->generic_action.state_set);
422
423   action->variable = lmm_variable_new(maxmin_system, action, 
424                                       action->generic_action.priority, -1.0, 1);
425   lmm_expand(maxmin_system, CPU->constraint, action->variable,
426              1.0);
427   XBT_OUT;
428   return (surf_action_t) action;
429 }
430
431 static surf_action_t action_sleep(void *cpu, double duration)
432 {
433   surf_action_workstation_KCCFLN05_t action = NULL;
434
435   XBT_IN2("(%s,%g)",((cpu_KCCFLN05_t)cpu)->name,duration);
436
437   action = (surf_action_workstation_KCCFLN05_t) execute(cpu, 1.0);
438   action->generic_action.max_duration = duration;
439   lmm_update_variable_weight(maxmin_system, action->variable, 0.0);
440
441   XBT_OUT;
442   return (surf_action_t) action;
443 }
444
445 static e_surf_cpu_state_t resource_get_state(void *cpu)
446 {
447   return ((cpu_KCCFLN05_t) cpu)->state_current;
448 }
449
450 static double get_speed(void *cpu, double load)
451 {
452   return load*(((cpu_KCCFLN05_t) cpu)->power_scale);
453 }
454
455 static surf_action_t communicate(void *src, void *dst, double size, double rate)
456 {
457   surf_action_workstation_KCCFLN05_t action = NULL;
458   cpu_KCCFLN05_t card_src = src;
459   cpu_KCCFLN05_t card_dst = dst;
460   route_KCCFLN05_t route = &(ROUTE(card_src->id, card_dst->id));
461   int route_size = route->size;
462   int i;
463
464   XBT_IN4("(%s,%s,%g,%g)",card_src->name,card_dst->name,size,rate);
465   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);
466
467   action = xbt_new0(s_surf_action_workstation_KCCFLN05_t, 1);
468
469   action->generic_action.using = 1;
470   action->generic_action.cost = size;
471   action->generic_action.remains = size;
472   action->generic_action.max_duration = NO_MAX_DURATION;
473   action->generic_action.start = -1.0;
474   action->generic_action.finish = -1.0;
475   action->src = src;
476   action->dst = dst;
477   action->generic_action.resource_type =
478     (surf_resource_t) surf_workstation_resource;
479   action->suspended = 0;  /* Should be useless because of the 
480                              calloc but it seems to help valgrind... */
481   action->generic_action.state_set =
482       surf_workstation_resource->common_public->states.running_action_set;
483
484   xbt_dynar_push(card_src->outgoing_communications, &action);
485   xbt_dynar_push(card_dst->incomming_communications, &action);
486
487   xbt_swag_insert(action, action->generic_action.state_set);
488   action->rate = rate;
489
490   action->latency = 0.0;
491   for (i = 0; i < route_size; i++)
492     action->latency += route->links[i]->lat_current;
493   action->lat_current = action->latency;
494
495   if(action->latency>0)
496     action->variable = lmm_variable_new(maxmin_system, action, 0.0, -1.0,
497                                         route_size+4); /* +1 for the src bus
498                                                           +1 for the dst bus
499                                                           +1 for the src cpu
500                                                           +1 for the dst cpu */
501   else
502     action->variable = lmm_variable_new(maxmin_system, action, 1.0, -1.0,
503                                         route_size+4);
504
505   if(action->rate<0) {
506     if(action->lat_current>0)
507       lmm_update_variable_bound(maxmin_system, action->variable,
508                                 SG_TCP_CTE_GAMMA / (2.0 * action->lat_current));
509     else
510       lmm_update_variable_bound(maxmin_system, action->variable, -1.0);
511   } else {
512     if(action->lat_current>0)
513       lmm_update_variable_bound(maxmin_system, action->variable,
514                                 min(action->rate,SG_TCP_CTE_GAMMA / (2.0 * action->lat_current)));
515     else
516       lmm_update_variable_bound(maxmin_system, action->variable, action->rate);
517   }
518
519   for (i = 0; i < route_size; i++)
520     lmm_expand(maxmin_system, route->links[i]->constraint, action->variable, 1.0);
521   if (card_src->bus)
522     lmm_expand(maxmin_system, card_src->bus, action->variable, 1.0);
523   if (card_dst->bus)
524     lmm_expand(maxmin_system, card_dst->bus, action->variable, 1.0);
525   lmm_expand(maxmin_system, card_src->constraint, action->variable, 0.0);
526   lmm_expand(maxmin_system, card_dst->constraint, action->variable, 0.0);
527
528   XBT_OUT;
529   return (surf_action_t) action;
530 }
531
532 /* FIXME: execute_parallel_task */
533 static surf_action_t execute_parallel_task(int cpu_nb,
534                                            void **cpu_list, 
535                                            double *computation_amount, 
536                                            double *communication_amount,
537                                            double amount,
538                                            double rate)
539 {
540   DIE_IMPOSSIBLE;
541   return NULL;
542 }
543
544
545 /**************************************/
546 /*** Resource Creation & Destruction **/
547 /**************************************/
548
549 static void cpu_free(void *cpu)
550 {
551   free(((cpu_KCCFLN05_t) cpu)->name);
552   xbt_dynar_free(&(((cpu_KCCFLN05_t) cpu)->incomming_communications));
553   xbt_dynar_free(&(((cpu_KCCFLN05_t) cpu)->outgoing_communications));
554   free(cpu);
555 }
556
557 static cpu_KCCFLN05_t cpu_new(const char *name, double power_scale,
558                               double power_initial,
559                               tmgr_trace_t power_trace,
560                               e_surf_cpu_state_t state_initial,
561                               tmgr_trace_t state_trace,
562                               double interference_send,
563                               double interference_recv,
564                               double interference_send_recv,
565                               double max_outgoing_rate)
566 {
567   cpu_KCCFLN05_t cpu = xbt_new0(s_cpu_KCCFLN05_t, 1);
568
569   cpu->resource = (surf_resource_t) surf_workstation_resource;
570   cpu->type = SURF_WORKSTATION_RESOURCE_CPU;
571   cpu->name = xbt_strdup(name);
572   cpu->id = nb_workstation++;
573
574   cpu->power_scale = power_scale;
575   xbt_assert0(cpu->power_scale > 0, "Power has to be >0");
576
577   cpu->power_current = power_initial;
578   if (power_trace)
579     cpu->power_event =
580         tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
581
582   cpu->state_current = state_initial;
583   if (state_trace)
584     cpu->state_event =
585         tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
586
587   cpu->interference_send = interference_send;
588   cpu->interference_recv = interference_recv;
589   cpu->interference_send_recv = interference_send_recv;
590
591   cpu->constraint =
592       lmm_constraint_new(maxmin_system, cpu,
593                          cpu->power_current * cpu->power_scale);
594   if (max_outgoing_rate > 0)
595     cpu->bus = lmm_constraint_new(maxmin_system, cpu, max_outgoing_rate);
596
597   cpu->incomming_communications =
598       xbt_dynar_new(sizeof(surf_action_workstation_KCCFLN05_t), NULL);
599   cpu->outgoing_communications =
600       xbt_dynar_new(sizeof(surf_action_workstation_KCCFLN05_t), NULL);
601
602   xbt_dict_set(workstation_set, name, cpu, cpu_free);
603
604   return cpu;
605 }
606
607 static void parse_cpu(void)
608 {
609   double power_scale = 0.0;
610   double power_initial = 0.0;
611   tmgr_trace_t power_trace = NULL;
612   e_surf_cpu_state_t state_initial = SURF_CPU_OFF;
613   tmgr_trace_t state_trace = NULL;
614   double interference_send = 0.0;
615   double interference_recv = 0.0;
616   double interference_send_recv = 0.0;
617   double max_outgoing_rate = -1.0;
618
619   surf_parse_get_double(&power_scale, A_surfxml_cpu_power);
620   surf_parse_get_double(&power_initial, A_surfxml_cpu_availability);
621   surf_parse_get_trace(&power_trace, A_surfxml_cpu_availability_file);
622
623   xbt_assert0((A_surfxml_cpu_state == A_surfxml_cpu_state_ON) ||
624               (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF),
625               "Invalid state");
626   if (A_surfxml_cpu_state == A_surfxml_cpu_state_ON)
627     state_initial = SURF_CPU_ON;
628   if (A_surfxml_cpu_state == A_surfxml_cpu_state_OFF)
629     state_initial = SURF_CPU_OFF;
630   surf_parse_get_trace(&state_trace, A_surfxml_cpu_state_file);
631
632   surf_parse_get_double(&interference_send,
633                         A_surfxml_cpu_interference_send);
634   surf_parse_get_double(&interference_recv,
635                         A_surfxml_cpu_interference_recv);
636   surf_parse_get_double(&interference_send_recv,
637                         A_surfxml_cpu_interference_send_recv);
638   surf_parse_get_double(&max_outgoing_rate,
639                         A_surfxml_cpu_max_outgoing_rate);
640
641   cpu_new(A_surfxml_cpu_name, power_scale, power_initial, power_trace,
642           state_initial, state_trace, interference_send, interference_recv,
643           interference_send_recv, max_outgoing_rate);
644 }
645
646 static void create_routing_table(void)
647 {
648   routing_table =
649       xbt_new0(s_route_KCCFLN05_t, nb_workstation * nb_workstation);
650 }
651
652 static void network_link_free(void *nw_link)
653 {
654   free(((network_link_KCCFLN05_t) nw_link)->name);
655   free(nw_link);
656 }
657
658 static network_link_KCCFLN05_t network_link_new(char *name,
659                                                 double bw_initial,
660                                                 tmgr_trace_t bw_trace,
661                                                 double lat_initial,
662                                                 tmgr_trace_t lat_trace,
663                                                 e_surf_network_link_state_t
664                                                 state_initial,
665                                                 tmgr_trace_t state_trace,
666                                                 e_surf_network_link_sharing_policy_t policy)
667 {
668   network_link_KCCFLN05_t nw_link = xbt_new0(s_network_link_KCCFLN05_t, 1);
669
670
671   nw_link->resource = (surf_resource_t) surf_workstation_resource;
672   nw_link->type = SURF_WORKSTATION_RESOURCE_LINK;
673   nw_link->name = name;
674   nw_link->bw_current = bw_initial;
675   if (bw_trace)
676     nw_link->bw_event =
677         tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link);
678   nw_link->state_current = state_initial;
679   nw_link->lat_current = lat_initial;
680   if (lat_trace)
681     nw_link->lat_event =
682         tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link);
683   if (state_trace)
684     nw_link->state_event =
685         tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link);
686
687   nw_link->constraint =
688       lmm_constraint_new(maxmin_system, nw_link, nw_link->bw_current);
689
690   if(policy == SURF_NETWORK_LINK_FATPIPE)
691     lmm_constraint_shared(nw_link->constraint);
692
693   xbt_dict_set(network_link_set, name, nw_link, network_link_free);
694
695   return nw_link;
696 }
697
698 static void parse_network_link(void)
699 {
700   char *name;
701   double bw_initial;
702   tmgr_trace_t bw_trace;
703   double lat_initial;
704   tmgr_trace_t lat_trace;
705   e_surf_network_link_state_t state_initial = SURF_NETWORK_LINK_ON;
706   e_surf_network_link_sharing_policy_t policy_initial = SURF_NETWORK_LINK_SHARED;
707   tmgr_trace_t state_trace;
708
709   name = xbt_strdup(A_surfxml_network_link_name);
710   surf_parse_get_double(&bw_initial,A_surfxml_network_link_bandwidth);
711   surf_parse_get_trace(&bw_trace, A_surfxml_network_link_bandwidth_file);
712   surf_parse_get_double(&lat_initial,A_surfxml_network_link_latency);
713   surf_parse_get_trace(&lat_trace, A_surfxml_network_link_latency_file);
714
715   xbt_assert0((A_surfxml_network_link_state==A_surfxml_network_link_state_ON)||
716               (A_surfxml_network_link_state==A_surfxml_network_link_state_OFF),
717               "Invalid state");
718   if (A_surfxml_network_link_state==A_surfxml_network_link_state_ON) 
719     state_initial = SURF_NETWORK_LINK_ON;
720   else if (A_surfxml_network_link_state==A_surfxml_network_link_state_OFF) 
721     state_initial = SURF_NETWORK_LINK_OFF;
722
723   if (A_surfxml_network_link_sharing_policy==A_surfxml_network_link_sharing_policy_SHARED) 
724     policy_initial = SURF_NETWORK_LINK_SHARED;
725   else if (A_surfxml_network_link_sharing_policy==A_surfxml_network_link_sharing_policy_FATPIPE) 
726     policy_initial = SURF_NETWORK_LINK_FATPIPE;
727
728   surf_parse_get_trace(&state_trace,A_surfxml_network_link_state_file);
729
730   network_link_new(name, bw_initial, bw_trace,
731                    lat_initial, lat_trace, state_initial, state_trace,
732                    policy_initial);
733 }
734
735 static void route_new(int src_id, int dst_id, char **links, int nb_link,
736                       double impact_on_src, double impact_on_dst,
737                       double impact_on_src_with_other_recv,
738                       double impact_on_dst_with_other_send)
739 {
740   network_link_KCCFLN05_t *link_list = NULL;
741   int i;
742   route_KCCFLN05_t route = &(ROUTE(src_id, dst_id));
743
744   route->size = nb_link;
745   link_list = route->links = xbt_new0(network_link_KCCFLN05_t, nb_link);
746   for (i = 0; i < nb_link; i++) {
747     link_list[i] = xbt_dict_get_or_null(network_link_set, links[i]);
748     free(links[i]);
749   }
750   free(links);
751   route->impact_on_src = impact_on_src;
752   route->impact_on_dst = impact_on_src;
753   route->impact_on_src_with_other_recv = impact_on_src_with_other_recv;
754   route->impact_on_dst_with_other_send = impact_on_dst_with_other_send;
755 }
756
757 static int nb_link = 0;
758 static char **link_name = NULL;
759 static int src_id = -1;
760 static int dst_id = -1;
761 static double impact_on_src;
762 static double impact_on_dst;
763 static double impact_on_src_with_other_recv;
764 static double impact_on_dst_with_other_send;
765
766 static void parse_route_set_endpoints(void)
767 {
768   src_id = ((cpu_KCCFLN05_t) name_service(A_surfxml_route_src))->id;
769   dst_id = ((cpu_KCCFLN05_t) name_service(A_surfxml_route_dst))->id;
770   surf_parse_get_double(&impact_on_src, A_surfxml_route_impact_on_src);
771   surf_parse_get_double(&impact_on_dst, A_surfxml_route_impact_on_dst);
772   surf_parse_get_double(&impact_on_src_with_other_recv,
773                         A_surfxml_route_impact_on_src_with_other_recv);
774   surf_parse_get_double(&impact_on_dst_with_other_send,
775                         A_surfxml_route_impact_on_dst_with_other_send);
776
777   nb_link = 0;
778   link_name = NULL;
779 }
780
781 static void parse_route_elem(void)
782 {
783   nb_link++;
784   link_name = xbt_realloc(link_name, (nb_link) * sizeof(char *));
785   link_name[(nb_link) - 1] = xbt_strdup(A_surfxml_route_element_name);
786 }
787
788 static void parse_route_set_route(void)
789 {
790   route_new(src_id, dst_id, link_name, nb_link, impact_on_src,
791             impact_on_dst, impact_on_src_with_other_recv,
792             impact_on_dst_with_other_send);
793 }
794
795 static void parse_file(const char *file)
796 {
797   int i ;
798
799   /* Figuring out the cpus */
800   surf_parse_reset_parser();
801   ETag_surfxml_cpu_fun = parse_cpu;
802   surf_parse_open(file);
803   xbt_assert1((!surf_parse()), "Parse error in %s", file);
804   surf_parse_close();
805
806   create_routing_table();
807
808   /* Figuring out the network links */
809   surf_parse_reset_parser();
810   ETag_surfxml_network_link_fun = parse_network_link;
811   surf_parse_open(file);
812   xbt_assert1((!surf_parse()), "Parse error in %s", file);
813   surf_parse_close();
814
815   /* Building the routes */
816   surf_parse_reset_parser();
817   STag_surfxml_route_fun = parse_route_set_endpoints;
818   ETag_surfxml_route_element_fun = parse_route_elem;
819   ETag_surfxml_route_fun = parse_route_set_route;
820   surf_parse_open(file);
821   xbt_assert1((!surf_parse()), "Parse error in %s", file);
822   surf_parse_close();
823
824   /* Adding loopback if needed */    
825   for (i = 0; i < nb_workstation; i++) 
826     if(!ROUTE(i,i).size) {
827       if(!loopback)
828         loopback = network_link_new(xbt_strdup("__MSG_loopback__"), 
829                                    498.00, NULL, 0.000015, NULL, 
830                                    SURF_NETWORK_LINK_ON, NULL,
831                                    SURF_NETWORK_LINK_FATPIPE);
832       ROUTE(i,i).size=1;
833       ROUTE(i,i).links = xbt_new0(network_link_KCCFLN05_t, 1);
834       ROUTE(i,i).links[0] = loopback;
835     }
836
837 }
838
839 /**************************************/
840 /********* Module  creation ***********/
841 /**************************************/
842
843 static void resource_init_internal(void)
844 {
845   s_surf_action_t action;
846
847   surf_workstation_resource = xbt_new0(s_surf_workstation_resource_t, 1);
848
849   surf_workstation_resource->common_private =
850       xbt_new0(s_surf_resource_private_t, 1);
851   surf_workstation_resource->common_public =
852       xbt_new0(s_surf_resource_public_t, 1);
853   surf_workstation_resource->extension_public =
854       xbt_new0(s_surf_workstation_resource_extension_public_t, 1);
855
856   surf_workstation_resource->common_public->states.ready_action_set =
857       xbt_swag_new(xbt_swag_offset(action, state_hookup));
858   surf_workstation_resource->common_public->states.running_action_set =
859       xbt_swag_new(xbt_swag_offset(action, state_hookup));
860   surf_workstation_resource->common_public->states.failed_action_set =
861       xbt_swag_new(xbt_swag_offset(action, state_hookup));
862   surf_workstation_resource->common_public->states.done_action_set =
863       xbt_swag_new(xbt_swag_offset(action, state_hookup));
864
865   surf_workstation_resource->common_public->name_service = name_service;
866   surf_workstation_resource->common_public->get_resource_name = get_resource_name;
867   surf_workstation_resource->common_public->action_get_state = surf_action_get_state;
868   surf_workstation_resource->common_public->action_use = action_use;
869   surf_workstation_resource->common_public->action_free = action_free;
870   surf_workstation_resource->common_public->action_cancel = action_cancel;
871   surf_workstation_resource->common_public->action_recycle = action_recycle;
872   surf_workstation_resource->common_public->action_change_state = surf_action_change_state;
873   surf_workstation_resource->common_public->action_set_data = surf_action_set_data;
874   surf_workstation_resource->common_public->suspend = action_suspend;
875   surf_workstation_resource->common_public->resume = action_resume;
876   surf_workstation_resource->common_public->is_suspended = action_is_suspended;
877   surf_workstation_resource->common_public->set_max_duration = action_set_max_duration;
878   surf_workstation_resource->common_public->set_priority = action_set_priority;
879   surf_workstation_resource->common_public->name = "Workstation KCCFLN05";
880
881   surf_workstation_resource->common_private->resource_used = resource_used;
882   surf_workstation_resource->common_private->share_resources = share_resources;
883   surf_workstation_resource->common_private->update_actions_state = update_actions_state;
884   surf_workstation_resource->common_private->update_resource_state = update_resource_state;
885   surf_workstation_resource->common_private->finalize = finalize;
886
887   surf_workstation_resource->extension_public->execute = execute;
888   surf_workstation_resource->extension_public->sleep = action_sleep;
889   surf_workstation_resource->extension_public->get_state = resource_get_state;
890   surf_workstation_resource->extension_public->communicate = communicate;
891   surf_workstation_resource->extension_public->execute_parallel_task = execute_parallel_task;
892
893   workstation_set = xbt_dict_new();
894   network_link_set = xbt_dict_new();
895
896   xbt_assert0(maxmin_system, "surf_init has to be called first!");
897 }
898
899 /**************************************/
900 /*************** Generic **************/
901 /**************************************/
902 void surf_workstation_resource_init_KCCFLN05(const char *filename)
903 {
904   xbt_assert0(!surf_cpu_resource, "CPU resource type already defined");
905   xbt_assert0(!surf_network_resource, "network resource type already defined");
906   resource_init_internal();
907   parse_file(filename);
908
909   xbt_dynar_push(resource_list, &surf_workstation_resource);
910 }