Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
54355f624ef96634c4f45f51c00284a2df0f943d
[simgrid.git] / src / surf / surf.cpp
1 #include "surf_private.h"
2 #include "surf.hpp"
3 #include "cpu.hpp"
4 #include "simix/smx_host_private.h"
5 #include "surf_routing.hpp"
6 #include "simgrid/sg_config.h"
7 #include "mc/mc.h"
8
9 extern "C" {
10 XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
12                                 "Logging specific to SURF (kernel)");
13 }
14
15 /*********
16  * Utils *
17  *********/
18
19 /* This function is a pimple that we ought to fix. But it won't be easy.
20  *
21  * The surf_solve() function does properly return the set of actions that changed.
22  * Instead, each model change a global data, and then the caller of surf_solve must
23  * pick into these sets of action_failed and action_done.
24  *
25  * This was not clean but ok as long as we didn't had to restart the processes when the resource comes back up.
26  * We worked by putting sentinel actions on every resources we are interested in,
27  * so that surf informs us if/when the corresponding resource fails.
28  *
29  * But this does not work to get Simix informed of when a resource comes back up, and this is where this pimple comes.
30  * We have a set of resources that are currently down and for which simix needs to know when it comes back up.
31  * And the current function is called *at every simulation step* to sweep over that set, searching for a resource
32  * that was turned back up in the meanwhile. This is UGLY and slow.
33  *
34  * The proper solution would be to not rely on globals for the action_failed and action_done swags.
35  * They must be passed as parameter by the caller (the handling of these actions in simix may let you
36  * think that these two sets can be merged, but their handling in SimDag induce the contrary unless this
37  * simdag code can check by itself whether the action is done of failed -- seems very doable, but yet more
38  * cleanup to do).
39  *
40  * Once surf_solve() is passed the set of actions that changed, you want to add a new set of resources back up
41  * as parameter to this function. You also want to add a boolean field "restart_watched" to each resource, and
42  * make sure that whenever a resource with this field enabled comes back up, it's added to that set so that Simix
43  * sees it and react accordingly. This would kill that need for surf to call simix.
44  *
45  */
46
47 static void remove_watched_host(void *key)
48 {
49   xbt_dict_remove(watched_hosts_lib, *(char**)key);
50 }
51
52 void surf_watched_hosts(void)
53 {
54   char *key;
55   void *host;
56   xbt_dict_cursor_t cursor;
57   xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
58
59   XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
60   xbt_dict_foreach(watched_hosts_lib, cursor, key, host)
61   {
62     if(SIMIX_host_get_state((smx_host_t)host) == SURF_RESOURCE_ON){
63       XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host));
64       SIMIX_host_autorestart((smx_host_t)host);
65       xbt_dynar_push_as(hosts, char*, key);
66     }
67     else
68       XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
69   }
70   xbt_dynar_map(hosts, remove_watched_host);
71   xbt_dynar_free(&hosts);
72 }
73
74
75 xbt_dynar_t model_list = NULL;
76 tmgr_history_t history = NULL;
77 lmm_system_t maxmin_system = NULL;
78 xbt_dynar_t surf_path = NULL;
79
80 /* Don't forget to update the option description in smx_config when you change this */
81 s_surf_model_description_t surf_network_model_description[] = {
82   {"LV08",
83    "Realistic network analytic model (slow-start modeled by multiplying latency by 10.4, bandwidth by .92; bottleneck sharing uses a payload of S=8775 for evaluating RTT). ",
84    surf_network_model_init_LegrandVelho},
85   {"Constant",
86    "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
87    surf_network_model_init_Constant},
88   {"SMPI",
89    "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
90    surf_network_model_init_SMPI},
91   {"CM02",
92    "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
93    surf_network_model_init_CM02},
94 #ifdef HAVE_GTNETS
95   {"GTNets",
96    "Network pseudo-model using the GTNets simulator instead of an analytic model",
97    surf_network_model_init_GTNETS},
98 #endif
99 #ifdef HAVE_NS3
100   {"NS3",
101    "Network pseudo-model using the NS3 tcp model instead of an analytic model",
102   surf_network_model_init_NS3},
103 #endif
104   {"Reno",
105    "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
106    surf_network_model_init_Reno},
107   {"Reno2",
108    "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
109    surf_network_model_init_Reno2},
110   {"Vegas",
111    "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
112    surf_network_model_init_Vegas},
113   {NULL, NULL, NULL}      /* this array must be NULL terminated */
114 };
115
116 s_surf_model_description_t surf_cpu_model_description[] = {
117   {"Cas01",
118    "Simplistic CPU model (time=size/power).",
119    surf_cpu_model_init_Cas01},
120   {NULL, NULL,  NULL}      /* this array must be NULL terminated */
121 };
122
123 s_surf_model_description_t surf_workstation_model_description[] = {
124   {"default",
125    "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
126    surf_workstation_model_init_current_default},
127   {"compound",
128    "Workstation model that is automatically chosen if you change the network and CPU models",
129    surf_workstation_model_init_compound},
130   {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
131    surf_workstation_model_init_ptask_L07},
132   {NULL, NULL, NULL}      /* this array must be NULL terminated */
133 };
134
135 s_surf_model_description_t surf_optimization_mode_description[] = {
136   {"Lazy",
137    "Lazy action management (partial invalidation in lmm + heap in action remaining).",
138    NULL},
139   {"TI",
140    "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
141     NULL},
142   {"Full",
143    "Full update of remaining and variables. Slow but may be useful when debugging.",
144    NULL},
145   {NULL, NULL, NULL}      /* this array must be NULL terminated */
146 };
147
148 s_surf_model_description_t surf_storage_model_description[] = {
149   {"default",
150    "Simplistic storage model.",
151    surf_storage_model_init_default},
152   {NULL, NULL,  NULL}      /* this array must be NULL terminated */
153 };
154
155 /* ********************************************************************* */
156 /* TUTORIAL: New model                                                   */
157 s_surf_model_description_t surf_new_model_description[] = {
158   {"default",
159    "Tutorial model.",
160    surf_new_model_init_default},
161   {NULL, NULL,  NULL}      /* this array must be NULL terminated */
162 };
163 /* ********************************************************************* */
164
165 #ifdef CONTEXT_THREADS
166 static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
167 #endif
168
169 static double *surf_mins = NULL; /* return value of share_resources for each model */
170 static int surf_min_index;       /* current index in surf_mins */
171 static double min;               /* duration determined by surf_solve */
172
173 double NOW = 0;
174
175 XBT_INLINE double surf_get_clock(void)
176 {
177   return NOW;
178 }
179
180 /*TODO: keepit void surf_watched_hosts(void)
181 {
182   char *key;
183   void *_host;
184   smx_host_t host;
185   xbt_dict_cursor_t cursor;
186   xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
187
188   XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
189   xbt_dict_foreach(watched_hosts_lib,cursor,key,_host)
190   {
191     host = (smx_host_t) host;
192     if(SIMIX_host_get_state(host) == SURF_RESOURCE_ON){
193       XBT_INFO("Restart processes on host: %s",SIMIX_host_get_name(host));
194       SIMIX_host_autorestart(host);
195       xbt_dynar_push_as(hosts, char*, key);
196     }
197     else
198       XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
199   }
200   xbt_dynar_map(hosts, remove_watched_host);
201   xbt_dynar_free(&hosts);
202 }*/
203
204 #ifdef _XBT_WIN32
205 # define FILE_DELIM "\\"
206 #else
207 # define FILE_DELIM "/"         /* FIXME: move to better location */
208 #endif
209
210 FILE *surf_fopen(const char *name, const char *mode)
211 {
212   unsigned int cpt;
213   char *path_elm = NULL;
214   char *buff;
215   FILE *file = NULL;
216
217   xbt_assert(name);
218
219   if (__surf_is_absolute_file_path(name))       /* don't mess with absolute file names */
220     return fopen(name, mode);
221
222   /* search relative files in the path */
223   xbt_dynar_foreach(surf_path, cpt, path_elm) {
224     buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
225     file = fopen(buff, mode);
226     free(buff);
227
228     if (file)
229       return file;
230   }
231   return NULL;
232 }
233
234 /*
235  * Returns the initial path. On Windows the initial path is
236  * the current directory for the current process in the other
237  * case the function returns "./" that represents the current
238  * directory on Unix/Linux platforms.
239  */
240
241 const char *__surf_get_initial_path(void)
242 {
243
244 #ifdef _XBT_WIN32
245   unsigned i;
246   char current_directory[MAX_PATH + 1] = { 0 };
247   unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
248   char root[4] = { 0 };
249
250   if (!len)
251     return NULL;
252
253   strncpy(root, current_directory, 3);
254
255   for (i = 0; i < MAX_DRIVE; i++) {
256     if (toupper(root[0]) == disk_drives_letter_table[i][0])
257       return disk_drives_letter_table[i];
258   }
259
260   return NULL;
261 #else
262   return "./";
263 #endif
264 }
265
266 /* The __surf_is_absolute_file_path() returns 1 if
267  * file_path is a absolute file path, in the other
268  * case the function returns 0.
269  */
270 int __surf_is_absolute_file_path(const char *file_path)
271 {
272 #ifdef _XBT_WIN32
273   WIN32_FIND_DATA wfd = { 0 };
274   HANDLE hFile = FindFirstFile(file_path, &wfd);
275
276   if (INVALID_HANDLE_VALUE == hFile)
277     return 0;
278
279   FindClose(hFile);
280   return 1;
281 #else
282   return (file_path[0] == '/');
283 #endif
284 }
285
286 /** Displays the long description of all registered models, and quit */
287 void model_help(const char *category, s_surf_model_description_t * table)
288 {
289   int i;
290   printf("Long description of the %s models accepted by this simulator:\n",
291          category);
292   for (i = 0; table[i].name; i++)
293     printf("  %s: %s\n", table[i].name, table[i].description);
294 }
295
296 int find_model_description(s_surf_model_description_t * table,
297                            const char *name)
298 {
299   int i;
300   char *name_list = NULL;
301
302   for (i = 0; table[i].name; i++)
303     if (!strcmp(name, table[i].name)) {
304       return i;
305     }
306   name_list = strdup(table[0].name);
307   for (i = 1; table[i].name; i++) {
308     name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
309     strcat(name_list, ", ");
310     strcat(name_list, table[i].name);
311   }
312   xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
313   return -1;
314 }
315
316 static XBT_INLINE void routing_asr_host_free(void *p)
317 {
318   delete ((RoutingEdgePtr) p);
319 }
320
321 static XBT_INLINE void routing_asr_prop_free(void *p)
322 {
323   xbt_dict_t elm = (xbt_dict_t) p;
324   xbt_dict_free(&elm);
325 }
326
327 static XBT_INLINE void surf_resource_free(void *r)
328 {
329   ResourcePtr resource = (ResourcePtr) r;
330   delete resource;
331 }
332
333 void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
334   *ver_major = SIMGRID_VERSION_MAJOR;
335   *ver_minor = SIMGRID_VERSION_MINOR;
336   *ver_patch = SIMGRID_VERSION_PATCH;
337 }
338
339 void surf_init(int *argc, char **argv)
340 {
341   XBT_DEBUG("Create all Libs");
342   host_lib = xbt_lib_new();
343   link_lib = xbt_lib_new();
344   as_router_lib = xbt_lib_new();
345   storage_lib = xbt_lib_new();
346   storage_type_lib = xbt_lib_new();
347   watched_hosts_lib = xbt_dict_new();
348
349   XBT_DEBUG("Add routing levels");
350   ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
351   ROUTING_ASR_LEVEL  = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
352   ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
353
354   XBT_DEBUG("Add SURF levels");
355   SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
356   SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free);
357   SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free);
358
359   xbt_init(argc, argv);
360   if (!model_list)
361     model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
362   if (!history)
363     history = tmgr_history_new();
364
365 #ifdef HAVE_TRACING
366   TRACE_add_start_function(TRACE_surf_alloc);
367   TRACE_add_end_function(TRACE_surf_release);
368 #endif
369
370   sg_config_init(argc, argv);
371
372   surf_action_init();
373   if (MC_is_active())
374     MC_memory_init();
375 }
376
377 void surf_exit(void)
378 {
379   unsigned int iter;
380   ModelPtr model = NULL;
381
382   sg_config_finalize();
383
384   xbt_dynar_foreach(model_list, iter, model)
385     delete model;
386   xbt_dynar_free(&model_list);
387   routing_exit();
388
389   if (maxmin_system) {
390     lmm_system_free(maxmin_system);
391     maxmin_system = NULL;
392   }
393   if (history) {
394     tmgr_history_free(history);
395     history = NULL;
396   }
397   surf_action_exit();
398
399 #ifdef CONTEXT_THREADS
400   xbt_parmap_destroy(surf_parmap);
401   xbt_free(surf_mins);
402   surf_mins = NULL;
403 #endif
404
405   xbt_dynar_free(&surf_path);
406
407   xbt_lib_free(&host_lib);
408   xbt_lib_free(&link_lib);
409   xbt_lib_free(&as_router_lib);
410   xbt_lib_free(&storage_lib);
411   xbt_lib_free(&storage_type_lib);
412
413   xbt_dict_free(&watched_hosts_lib);
414
415   tmgr_finalize();
416   surf_parse_lex_destroy();
417   surf_parse_free_callbacks();
418
419   NOW = 0;                      /* Just in case the user plans to restart the simulation afterward */
420 }
421 /*********
422  * Model *
423  *********/
424
425 Model::Model(string name)
426  : m_name(name), m_resOnCB(0), m_resOffCB(0), m_actSuspendCB(0), m_actCancelCB(0), m_actResumeCB(0)
427 {
428   ActionPtr action;
429   p_readyActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
430   p_runningActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
431   p_failedActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
432   p_doneActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
433
434   p_modifiedSet = NULL;
435   p_actionHeap = NULL;
436   p_updateMechanism = UM_UNDEFINED;
437   m_selectiveUpdate = 0;
438 }
439
440 Model::~Model(){
441 xbt_swag_free(p_readyActionSet);
442 xbt_swag_free(p_runningActionSet);
443 xbt_swag_free(p_failedActionSet);
444 xbt_swag_free(p_doneActionSet);
445 }
446
447 double Model::shareResources(double now)
448 {
449   //FIXME: to implement
450 }
451
452 double Model::shareResourcesLazy(double now)
453 {
454   ActionLmmPtr action = NULL;
455   double min = -1;
456   double value;
457
458   XBT_DEBUG
459       ("Before share resources, the size of modified actions set is %d",
460        xbt_swag_size(p_modifiedSet));
461
462   lmm_solve(p_maxminSystem);
463
464   XBT_DEBUG
465       ("After share resources, The size of modified actions set is %d",
466        xbt_swag_size(p_modifiedSet));
467
468   while((action = (ActionLmmPtr) xbt_swag_extract(p_modifiedSet))) {
469     int max_dur_flag = 0;
470
471     if (action->p_stateSet != p_runningActionSet)
472       continue;
473
474     /* bogus priority, skip it */
475     if (action->m_priority <= 0)
476       continue;
477
478     action->updateRemainingLazy(now);
479
480     min = -1;
481     value = lmm_variable_getvalue(action->p_variable);
482     if (value > 0) {
483       if (action->m_remains > 0) {
484         value = action->m_remains / value;
485         min = now + value;
486       } else {
487         value = 0.0;
488         min = now;
489       }
490     }
491
492     if ((action->m_maxDuration != NO_MAX_DURATION)
493         && (min == -1
494             || action->m_start +
495             action->m_maxDuration < min)) {
496       min = action->m_start +
497           action->m_maxDuration;
498       max_dur_flag = 1;
499     }
500
501     XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
502         action->m_start, now + value,
503         action->m_maxDuration);
504
505     if (min != -1) {
506       action->heapRemove(p_actionHeap);
507       action->heapInsert(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
508       XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
509                 now);
510     } else DIE_IMPOSSIBLE;
511   }
512
513   //hereafter must have already the min value for this resource model
514   if (xbt_heap_size(p_actionHeap) > 0)
515     min = xbt_heap_maxkey(p_actionHeap) - now;
516   else
517     min = -1;
518
519   XBT_DEBUG("The minimum with the HEAP %lf", min);
520
521   return min;
522 }
523
524 double Model::shareResourcesMaxMin(xbt_swag_t running_actions,
525                           size_t offset,
526                           lmm_system_t sys,
527                           void (*solve) (lmm_system_t))
528 {
529   void *_action = NULL;
530   ActionPtr action = NULL;
531   double min = -1;
532   double value = -1;
533 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + (offset))))
534
535   solve(sys);
536
537   xbt_swag_foreach(_action, running_actions) {
538     action = (ActionPtr)_action;
539     value = lmm_variable_getvalue(VARIABLE(action));
540     if ((value > 0) || (action->m_maxDuration >= 0))
541       break;
542   }
543
544   if (!action)
545     return -1.0;
546
547   if (value > 0) {
548     if (action->m_remains > 0)
549       min = action->m_remains / value;
550     else
551       min = 0.0;
552     if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min))
553       min = action->m_maxDuration;
554   } else
555     min = action->m_maxDuration;
556
557
558   for (action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset);
559        action;
560        action = (ActionPtr) xbt_swag_getNext(action, running_actions->offset)) {
561     value = lmm_variable_getvalue(VARIABLE(action));
562     if (value > 0) {
563       if (action->m_remains > 0)
564         value = action->m_remains / value;
565       else
566         value = 0.0;
567       if (value < min) {
568         min = value;
569         XBT_DEBUG("Updating min (value) with %p: %f", action, min);
570       }
571     }
572     if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min)) {
573       min = action->m_maxDuration;
574       XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
575     }
576   }
577   XBT_DEBUG("min value : %f", min);
578
579 #undef VARIABLE
580   return min;
581 }
582
583 void Model::updateActionsState(double now, double delta)
584 {
585   if (p_updateMechanism == UM_FULL)
586         updateActionsStateFull(now, delta);
587   else if (p_updateMechanism == UM_LAZY)
588         updateActionsStateLazy(now, delta);
589   else
590         xbt_die("Invalid cpu update mechanism!");
591 }
592
593 void Model::updateActionsStateLazy(double now, double delta)
594 {
595
596 }
597
598 void Model::updateActionsStateFull(double now, double delta)
599 {
600
601 }
602
603
604 void Model::addTurnedOnCallback(ResourceCallback rc)
605 {
606   m_resOnCB = rc;
607 }
608
609 void Model::notifyResourceTurnedOn(ResourcePtr r)
610 {
611   m_resOnCB(r);
612 }
613
614 void Model::addTurnedOffCallback(ResourceCallback rc)
615 {
616   m_resOffCB = rc;
617 }
618
619 void Model::notifyResourceTurnedOff(ResourcePtr r)
620 {
621   m_resOffCB(r);
622 }
623
624 void Model::addActionCancelCallback(ActionCallback ac)
625 {
626   m_actCancelCB = ac;
627 }
628
629 void Model::notifyActionCancel(ActionPtr a)
630 {
631   m_actCancelCB(a);
632 }
633
634 void Model::addActionResumeCallback(ActionCallback ac)
635 {
636   m_actResumeCB = ac;
637 }
638
639 void Model::notifyActionResume(ActionPtr a)
640 {
641   m_actResumeCB(a);
642 }
643
644 void Model::addActionSuspendCallback(ActionCallback ac)
645 {
646   m_actSuspendCB = ac;
647 }
648
649 void Model::notifyActionSuspend(ActionPtr a)
650 {
651   m_actSuspendCB(a);
652 }
653
654
655 /************
656  * Resource *
657  ************/
658
659 Resource::Resource(surf_model_t model, const char *name, xbt_dict_t props)
660   : m_name(xbt_strdup(name)), m_running(true), p_model(model), m_properties(props)
661 {}
662
663 Resource::Resource(){
664   //FIXME:free(m_name);
665   xbt_dict_free(&m_properties);
666 }
667
668 const char *Resource::getName()
669 {
670   return m_name;
671 }
672
673 xbt_dict_t Resource::getProperties()
674 {
675   return m_properties;
676 }
677
678 e_surf_resource_state_t Resource::getState()
679 {
680   return m_stateCurrent;
681 }
682
683 bool Resource::isOn()
684 {
685   return m_running;
686 }
687
688 void Resource::turnOn()
689 {
690   if (!m_running) {
691     m_running = true;
692     p_model->notifyResourceTurnedOn(this);
693   }
694 }
695
696 void Resource::turnOff()
697 {
698   if (m_running) {
699     m_running = false;
700     p_model->notifyResourceTurnedOff(this);
701   }
702 }
703
704 ResourceLmm::ResourceLmm(surf_model_t model, const char *name, xbt_dict_t props,
705                          lmm_system_t system,
706                          double constraint_value,
707                          tmgr_history_t history,
708                          e_surf_resource_state_t state_init,
709                          tmgr_trace_t state_trace,
710                          double metric_peak,
711                          tmgr_trace_t metric_trace)
712   : Resource(model, name, props)
713 {
714   p_constraint = lmm_constraint_new(system, this, constraint_value);
715   p_stateCurrent = state_init;
716   if (state_trace)
717     p_stateEvent = tmgr_history_add_trace(history, state_trace, 0.0, 0, this);
718   p_power.scale = 1.0;
719   p_power.peak = metric_peak;
720   if (metric_trace)
721     p_power.event = tmgr_history_add_trace(history, metric_trace, 0.0, 0, this);
722 }
723
724 /**********
725  * Action *
726  **********/
727
728 const char *surf_action_state_names[6] = {
729   "SURF_ACTION_READY",
730   "SURF_ACTION_RUNNING",
731   "SURF_ACTION_FAILED",
732   "SURF_ACTION_DONE",
733   "SURF_ACTION_TO_FREE",
734   "SURF_ACTION_NOT_IN_THE_SYSTEM"
735 };
736
737 /**
738  * \brief Initializes the action module of Surf.
739  */
740 void surf_action_init(void) {
741
742   /* the action mallocator will always provide actions of the following size,
743    * so this size should be set to the maximum size of the surf action structures
744    */
745   /*FIXME:action_mallocator_allocated_size = sizeof(s_surf_action_network_CM02_t);
746   action_mallocator = xbt_mallocator_new(65536, surf_action_mallocator_new_f,
747       surf_action_mallocator_free_f, surf_action_mallocator_reset_f);*/
748 }
749
750 /**
751  * \brief Uninitializes the action module of Surf.
752  */
753 void surf_action_exit(void) {
754   //FIXME:xbt_mallocator_free(action_mallocator);
755 }
756
757 Action::Action(){}
758
759 Action::Action(ModelPtr model, double cost, bool failed):
760          m_cost(cost), p_model(model), m_failed(failed), m_remains(cost),
761          m_refcount(1), m_priority(1.0), m_maxDuration(NO_MAX_DURATION),
762          m_start(surf_get_clock()), m_finish(-1.0)
763 {
764   #ifdef HAVE_TRACING
765     p_category = NULL;
766   #endif
767   if (failed)
768     p_stateSet = p_model->p_failedActionSet;
769   else
770     p_stateSet = p_model->p_runningActionSet;
771
772   xbt_swag_insert(this, p_stateSet);
773 }
774
775 Action::~Action() {}
776
777 int Action::unref(){
778   DIE_IMPOSSIBLE;
779 }
780
781 void Action::cancel(){
782   DIE_IMPOSSIBLE;
783 }
784
785 void Action::recycle(){
786   DIE_IMPOSSIBLE;
787 }
788
789 e_surf_action_state_t Action::getState()
790 {
791   if (p_stateSet ==  p_model->p_readyActionSet)
792     return SURF_ACTION_READY;
793   if (p_stateSet ==  p_model->p_runningActionSet)
794     return SURF_ACTION_RUNNING;
795   if (p_stateSet ==  p_model->p_failedActionSet)
796     return SURF_ACTION_FAILED;
797   if (p_stateSet ==  p_model->p_doneActionSet)
798     return SURF_ACTION_DONE;
799   return SURF_ACTION_NOT_IN_THE_SYSTEM;
800 }
801
802 void Action::setState(e_surf_action_state_t state)
803 {
804   //surf_action_state_t action_state = &(action->model_type->states);
805   XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
806   xbt_swag_remove(this, p_stateSet);
807
808   if (state == SURF_ACTION_READY)
809     p_stateSet = p_model->p_readyActionSet;
810   else if (state == SURF_ACTION_RUNNING)
811     p_stateSet = p_model->p_runningActionSet;
812   else if (state == SURF_ACTION_FAILED)
813     p_stateSet = p_model->p_failedActionSet;
814   else if (state == SURF_ACTION_DONE)
815     p_stateSet = p_model->p_doneActionSet;
816   else
817     p_stateSet = NULL;
818
819   if (p_stateSet)
820     xbt_swag_insert(this, p_stateSet);
821   XBT_OUT();
822 }
823
824 double Action::getStartTime()
825 {
826   return m_start;
827 }
828
829 double Action::getFinishTime()
830 {
831   /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
832   return m_remains == 0 ? m_finish : -1;
833 }
834
835 void Action::setData(void* data)
836 {
837   p_data = data;
838 }
839
840 #ifdef HAVE_TRACING
841 void Action::setCategory(const char *category)
842 {
843   XBT_IN("(%p,%s)", this, category);
844   p_category = xbt_strdup(category);
845   XBT_OUT();
846 }
847 #endif
848
849 void Action::ref(){
850   m_refcount++;
851 }
852
853 void ActionLmm::setMaxDuration(double duration)
854 {
855   XBT_IN("(%p,%g)", this, duration);
856   m_maxDuration = duration;
857   if (p_model->p_updateMechanism == UM_LAZY)      // remove action from the heap
858     heapRemove(p_model->p_actionHeap);
859   XBT_OUT();
860 }
861
862 void ActionLmm::gapRemove() {}
863
864 void ActionLmm::setPriority(double priority)
865 {
866   XBT_IN("(%p,%g)", this, priority);
867   m_priority = priority;
868   lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, priority);
869
870   if (p_model->p_updateMechanism == UM_LAZY)
871         heapRemove(p_model->p_actionHeap);
872   XBT_OUT();
873 }
874
875 void ActionLmm::cancel(){
876   setState(SURF_ACTION_FAILED);
877   if (p_model->p_updateMechanism == UM_LAZY) {
878     xbt_swag_remove(this, p_model->p_modifiedSet);
879     heapRemove(p_model->p_actionHeap);
880   }
881 }
882
883 int ActionLmm::unref(){
884   m_refcount--;
885   if (!m_refcount) {
886         xbt_swag_remove(this, p_stateSet);
887         if (p_variable)
888           lmm_variable_free(p_model->p_maxminSystem, p_variable);
889         if (p_model->p_updateMechanism == UM_LAZY) {
890           /* remove from heap */
891           heapRemove(p_model->p_actionHeap);
892           xbt_swag_remove(this, p_model->p_modifiedSet);
893     }
894 #ifdef HAVE_TRACING
895     xbt_free(p_category);
896 #endif
897         delete this;
898         return 1;
899   }
900   return 0;
901 }
902
903 void ActionLmm::suspend()
904 {
905   XBT_IN("(%p)", this);
906   if (m_suspended != 2) {
907     lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, 0.0);
908     m_suspended = 1;
909     if (p_model->p_updateMechanism == UM_LAZY)
910       heapRemove(p_model->p_actionHeap);
911   }
912   XBT_OUT();
913 }
914
915 void ActionLmm::resume()
916 {
917   XBT_IN("(%p)", this);
918   if (m_suspended != 2) {
919     lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, m_priority);
920     m_suspended = 0;
921     if (p_model->p_updateMechanism == UM_LAZY)
922       heapRemove(p_model->p_actionHeap);
923   }
924   XBT_OUT();
925 }
926
927 bool ActionLmm::isSuspended()
928 {
929   return m_suspended == 1;
930 }
931 /* insert action on heap using a given key and a hat (heap_action_type)
932  * a hat can be of three types for communications:
933  *
934  * NORMAL = this is a normal heap entry stating the date to finish transmitting
935  * LATENCY = this is a heap entry to warn us when the latency is payed
936  * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
937  */
938 void ActionLmm::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
939 {
940   m_hat = hat;
941   xbt_heap_push(heap, this, key);
942 }
943
944 void ActionLmm::heapRemove(xbt_heap_t heap)
945 {
946   m_hat = NOTSET;
947   if (m_indexHeap >= 0) {
948     xbt_heap_remove(heap, m_indexHeap);
949   }
950 }
951
952 /* added to manage the communication action's heap */
953 void surf_action_lmm_update_index_heap(void *action, int i) {
954   ((ActionLmmPtr)action)->updateIndexHeap(i);
955 }
956
957 void ActionLmm::updateIndexHeap(int i) {
958   m_indexHeap = i;
959 }
960
961
962 double ActionLmm::getRemains()
963 {
964   XBT_IN("(%p)", this);
965   /* update remains before return it */
966   if (p_updateMechanism == UM_LAZY)      /* update remains before return it */
967     updateRemainingLazy(surf_get_clock());
968   XBT_OUT();
969   return m_remains;
970 }
971
972 /*void Action::cancel()
973 {
974   p_model->notifyActionCancel(this);
975 }
976
977 void Action::suspend()
978 {
979   p_model->notifyActionSuspend(this);
980 }
981
982 void Action::resume()
983 {
984   p_model->notifyActionResume(this);
985 }
986
987 bool Action::isSuspended()
988 {
989   return false;
990 }*/
991