Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fix leak of memory caused by DefineEventTypeEvent call
[simgrid.git] / src / instr / instr_paje_trace.cpp
1 /* Copyright (c) 2010-2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "src/instr/instr_private.h"
8 #include "src/instr/instr_smpi.h"
9 #include "src/smpi/private.hpp"
10 #include "typeinfo"
11 #include "xbt/virtu.h" /* sg_cmdline */
12 #include "simgrid/sg_config.h"
13
14 #include <sstream>
15 #include <vector>
16 #include <iomanip> /** std::setprecision **/
17 #include <sys/stat.h>
18 #ifdef WIN32
19 #include <direct.h> // _mkdir
20 #endif
21
22 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_paje_trace, instr, "tracing event system");
23
24 static std::stringstream stream;
25 FILE *tracing_file = nullptr;
26
27 static xbt_dict_t tracing_files = nullptr; // TI specific
28 static double prefix=0.0; // TI specific
29
30
31 void print_NULL(PajeEvent* event){}
32
33 /* The active set of functions for the selected trace format
34  * By default, they all do nothing, hence the print_NULL to avoid segfaults */
35
36 std::vector<PajeEvent*> buffer;
37 void buffer_debug(std::vector<PajeEvent*> *buf);
38
39 void dump_comment (const char *comment)
40 {
41   if (not strlen(comment))
42     return;
43   fprintf (tracing_file, "# %s\n", comment);
44 }
45
46 void dump_comment_file (const char *filename)
47 {
48   if (not strlen(filename))
49     return;
50   FILE *file = fopen (filename, "r");
51   if (not file) {
52     THROWF (system_error, 1, "Comment file %s could not be opened for reading.", filename);
53   }
54   while (not feof(file)) {
55     char c;
56     c = fgetc(file);
57     if (feof(file)) break;
58     fprintf (tracing_file, "# ");
59     while (c != '\n'){
60       fprintf (tracing_file, "%c", c);
61       c = fgetc(file);
62       if (feof(file)) break;
63     }
64     fprintf (tracing_file, "\n");
65   }
66   fclose(file);
67 }
68
69 double TRACE_last_timestamp_to_dump = 0;
70 //dumps the trace file until the timestamp TRACE_last_timestamp_to_dump
71 void TRACE_paje_dump_buffer (int force)
72 {
73   if (not TRACE_is_enabled())
74     return;
75   XBT_DEBUG("%s: dump until %f. starts", __FUNCTION__, TRACE_last_timestamp_to_dump);
76   if (force){
77     for (auto event : buffer){
78       event->print();
79       delete event;
80     }
81     buffer.clear();
82   }else{
83     std::vector<PajeEvent*>::iterator i = buffer.begin();
84     for (auto event :buffer){
85       double head_timestamp = event->timestamp;
86       if (head_timestamp > TRACE_last_timestamp_to_dump)
87         break;
88       event->print();
89       delete event;
90       ++i;
91     }
92     buffer.erase(buffer.begin(), i);
93   }
94   XBT_DEBUG("%s: ends", __FUNCTION__);
95 }
96
97 void buffer_debug(std::vector<PajeEvent*> *buf);
98 void buffer_debug(std::vector<PajeEvent*> *buf) {
99   return;
100   XBT_DEBUG(">>>>>> Dump the state of the buffer. %zu events", buf->size());
101   for (auto event :*buf){
102     event->print();
103     XBT_DEBUG("%p %s", event, stream.str().c_str());
104     stream.str("");
105     stream.clear();
106   }
107   XBT_DEBUG("<<<<<<");
108 }
109
110 static void print_row() {
111   stream << std::endl;
112   fprintf(tracing_file, "%s", stream.str().c_str());
113   XBT_DEBUG("Dump %s", stream.str().c_str());
114   stream.str("");
115   stream.clear();
116 }
117
118 static void print_timestamp(PajeEvent* event) {
119   stream << " ";
120   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
121   if (event->timestamp < 1e-12)
122     stream << 0;
123   else
124     stream << event->timestamp;
125 }
126
127 /* internal do the instrumentation module */
128 static void insert_into_buffer (PajeEvent* tbi)
129 {
130   if (TRACE_buffer() == 0){
131     tbi->print ();
132     delete tbi;
133     return;
134   }
135   buffer_debug(&buffer);
136
137   XBT_DEBUG("%s: insert event_type=%d, timestamp=%f, buffersize=%zu)",
138       __FUNCTION__, (int)tbi->event_type, tbi->timestamp, buffer.size());
139   std::vector<PajeEvent*>::reverse_iterator i;
140   for (i = buffer.rbegin(); i != buffer.rend(); ++i) {
141     PajeEvent* e1 = *i;
142     XBT_DEBUG("compare to %p is of type %d; timestamp:%f", e1,
143         (int)e1->event_type, e1->timestamp);
144     if (e1->timestamp <= tbi->timestamp)
145       break;
146   }
147   if (i == buffer.rend())
148     XBT_DEBUG("%s: inserted at beginning", __FUNCTION__);
149   else if (i == buffer.rbegin())
150     XBT_DEBUG("%s: inserted at end", __FUNCTION__);
151   else
152     XBT_DEBUG("%s: inserted at pos= %zd from its end", __FUNCTION__,
153         std::distance(buffer.rbegin(),i));
154   buffer.insert(i.base(), tbi);
155
156   buffer_debug(&buffer);
157 }
158
159 PajeEvent:: ~PajeEvent()
160 {
161   XBT_DEBUG("%s not implemented for %p: event_type=%d, timestamp=%f", __FUNCTION__,
162       this, (int)event_type, timestamp);
163 //  xbt_backtrace_display_current();
164
165  /* switch (event->event_type){
166   case PAJE_StartLink:
167     xbt_free (((startLink_t)(event->data))->value);
168     xbt_free (((startLink_t)(event->data))->key);
169     break;
170   case PAJE_EndLink:
171     xbt_free (((endLink_t)(event->data))->value);
172     xbt_free (((endLink_t)(event->data))->key);
173     break;
174   default:
175     break;
176   }*/
177 }
178
179 void TRACE_paje_start() {
180   char *filename = TRACE_get_filename();
181   tracing_file = fopen(filename, "w");
182   if (tracing_file == nullptr){
183     THROWF (system_error, 1, "Tracefile %s could not be opened for writing.", filename);
184   }
185
186   XBT_DEBUG("Filename %s is open for writing", filename);
187
188   /* output generator version */
189   fprintf (tracing_file, "#This file was generated using SimGrid-%d.%d.%d\n",
190            SIMGRID_VERSION_MAJOR, SIMGRID_VERSION_MINOR, SIMGRID_VERSION_PATCH);
191   fprintf (tracing_file, "#[");
192   unsigned int cpt;
193   char *str;
194   xbt_dynar_foreach (xbt_cmdline, cpt, str){
195     fprintf(tracing_file, "%s ",str);
196   }
197   fprintf (tracing_file, "]\n");
198
199   /* output one line comment */
200   dump_comment (TRACE_get_comment());
201
202   /* output comment file */
203   dump_comment_file (TRACE_get_comment_file());
204
205   /* output header */
206   TRACE_header(TRACE_basic(),TRACE_display_sizes());
207 }
208
209 void TRACE_paje_end() {
210   fclose(tracing_file);
211   char *filename = TRACE_get_filename();
212   XBT_DEBUG("Filename %s is closed", filename);
213 }
214
215 void DefineContainerEvent(type_t type)
216 {
217   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineContainerType);
218   //print it
219   if (instr_fmt_type == instr_fmt_paje) {
220                 XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineContainerType, TRACE_precision(), 0.);
221                 stream << std::fixed << std::setprecision(TRACE_precision());
222                 stream << PAJE_DefineContainerType;
223                 stream << " " << type->id
224                                 << " " << type->father->id
225                                 << " " << type->name;
226                 print_row();
227         } else if (instr_fmt_type == instr_fmt_TI) {
228                 /* Nothing to do */
229         } else {
230                 THROW_IMPOSSIBLE;
231         }
232   //--
233 }
234
235
236
237 void LogVariableTypeDefinition(type_t type)
238 {
239
240   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineVariableType);
241
242   //print it
243 if (instr_fmt_type == instr_fmt_paje) {
244     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineVariableType, TRACE_precision(), 0.);
245     stream << std::fixed << std::setprecision(TRACE_precision());
246     stream << PAJE_DefineVariableType;
247     stream << " " << type->id << " " << type->father->id << " " << type->name;
248     if (type->color)
249       stream << " \"" << type->color << "\"";
250     print_row();
251   } else if (instr_fmt_type == instr_fmt_TI) {
252     /* Nothing to do */
253   } else {
254     THROW_IMPOSSIBLE;
255   }
256 }
257
258
259 void LogStateTypeDefinition(type_t type)
260 {
261   //print it
262 if (instr_fmt_type == instr_fmt_paje) {
263     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineStateType, TRACE_precision(), 0.);
264     stream << std::fixed << std::setprecision(TRACE_precision());
265     stream << PAJE_DefineStateType;
266     stream << " " << type->id << " " << type->father->id << " " << type->name;
267     print_row();
268   } else if (instr_fmt_type == instr_fmt_TI) {
269     /* Nothing to do */
270   } else {
271     THROW_IMPOSSIBLE;
272   }
273 }
274
275
276 void LogDefineEventType(type_t type)
277 {
278   //print it
279   if (instr_fmt_type == instr_fmt_paje) {
280     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineEventType, TRACE_precision(), 0.);
281     stream << std::fixed << std::setprecision(TRACE_precision());
282     stream << PAJE_DefineEventType;
283     stream << " " << type->id << " " << type->father->id << " " << type->name;
284     print_row();
285   } else if (instr_fmt_type == instr_fmt_TI) {
286     /* Nothing to do */
287   } else {
288     THROW_IMPOSSIBLE;
289   }
290 }
291
292 void LogLinkTypeDefinition(type_t type, type_t source, type_t dest)
293 {
294   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineLinkType);
295   //print it
296 if (instr_fmt_type == instr_fmt_paje) {
297     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineLinkType, TRACE_precision(), 0.);
298     stream << std::fixed << std::setprecision(TRACE_precision());
299     stream << PAJE_DefineLinkType;
300     stream << " " << type->id << " " << type->father->id << " " << source->id << " " << dest->id << " " << type->name;
301     print_row();
302   } else if (instr_fmt_type == instr_fmt_TI) {
303     /* Nothing to do */
304   } else {
305     THROW_IMPOSSIBLE;
306   }
307 }
308
309 void LogEntityValue (val_t value)
310 {
311   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineEntityValue);
312   //print it
313 if (instr_fmt_type == instr_fmt_paje) {
314     stream << std::fixed << std::setprecision(TRACE_precision());
315     stream << PAJE_DefineEntityValue;
316     stream << " " << value->id << " " << value->father->id << " " << value->name;
317     if (value->color)
318       stream << " \"" << value->color << "\"";
319     print_row();
320   } else if (instr_fmt_type == instr_fmt_TI) {
321     /* Nothing to do */
322   } else {
323     THROW_IMPOSSIBLE;
324   }
325 }
326
327
328 void LogContainerCreation (container_t container)
329 {
330   double timestamp                              = SIMIX_get_clock();
331
332   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, PAJE_CreateContainer,timestamp);
333
334 if (instr_fmt_type == instr_fmt_paje) {
335     stream << std::fixed << std::setprecision(TRACE_precision());
336     stream << PAJE_CreateContainer;
337     stream << " ";
338   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
339      if (timestamp < 1e-12)
340          stream << 0;
341       else 
342          stream << timestamp;
343          stream << " " << container->id << " " << container->type->id << " " << container->father->id << " \""
344             << container->name << "\"";
345
346     print_row();
347   } else if (instr_fmt_type == instr_fmt_TI) {
348     // if we are in the mode with only one file
349     static FILE* ti_unique_file = nullptr;
350
351     if (tracing_files == nullptr) {
352       tracing_files = xbt_dict_new_homogeneous(nullptr);
353       // generate unique run id with time
354       prefix = xbt_os_time();
355     }
356
357     if (not xbt_cfg_get_boolean("tracing/smpi/format/ti-one-file") || ti_unique_file == nullptr) {
358       char* folder_name = bprintf("%s_files", TRACE_get_filename());
359       char* filename    = bprintf("%s/%f_%s.txt", folder_name, prefix, container->name);
360 #ifdef WIN32
361       _mkdir(folder_name);
362 #else
363       mkdir(folder_name, S_IRWXU | S_IRWXG | S_IRWXO);
364 #endif
365       ti_unique_file = fopen(filename, "w");
366       xbt_assert(ti_unique_file, "Tracefile %s could not be opened for writing: %s", filename, strerror(errno));
367       fprintf(tracing_file, "%s\n", filename);
368
369       xbt_free(folder_name);
370       xbt_free(filename);
371     }
372
373     xbt_dict_set(tracing_files, container->name, (void*)ti_unique_file, nullptr);
374   } else {
375     THROW_IMPOSSIBLE;
376   }
377 }
378
379 void LogContainerDestruction(container_t container)
380 {
381   double timestamp                               = SIMIX_get_clock();
382
383   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, PAJE_DestroyContainer, timestamp);
384
385 if (instr_fmt_type == instr_fmt_paje) {
386     stream << std::fixed << std::setprecision(TRACE_precision());
387     stream << PAJE_DestroyContainer;
388     stream << " ";
389   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
390     if (timestamp < 1e-12)
391         stream << 0;
392     else 
393         stream << timestamp;
394     stream << " " << container->type->id << " " << container->id;
395     print_row();
396   } else if (instr_fmt_type == instr_fmt_TI) {
397     if (not xbt_cfg_get_boolean("tracing/smpi/format/ti-one-file") || xbt_dict_length(tracing_files) == 1) {
398       FILE* f = (FILE*)xbt_dict_get_or_null(tracing_files, container->name);
399       fclose(f);
400     }
401     xbt_dict_remove(tracing_files, container->name);
402         } else {
403           THROW_IMPOSSIBLE;
404         }
405 }
406
407
408 SetVariableEvent::SetVariableEvent (double timestamp, container_t container, type_t type, double value)
409 {
410   this->event_type                         = PAJE_SetVariable;
411   this->timestamp                          = timestamp;
412   this->type      = type;
413   this->container = container;
414   this->value     = value;
415
416   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
417
418   insert_into_buffer (this);
419 }
420
421 void SetVariableEvent::print() {
422   if (instr_fmt_type == instr_fmt_paje) {
423     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
424     stream << std::fixed << std::setprecision(TRACE_precision());
425     stream << (int)this->event_type;
426     print_timestamp(this);
427     stream << " " << type->id << " " << container->id << " " << value;
428     print_row();
429   } else if (instr_fmt_type == instr_fmt_TI) {
430     /* Nothing to do */
431   } else {
432     THROW_IMPOSSIBLE;
433   }
434 }
435
436 AddVariableEvent::AddVariableEvent (double timestamp, container_t container, type_t type, double value)
437 {
438   this->event_type                         = PAJE_AddVariable;
439   this->timestamp                          = timestamp;
440   this->type      = type;
441   this->container = container;
442   this->value     = value;
443
444   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
445
446   insert_into_buffer (this);
447 }
448
449 void AddVariableEvent::print() {
450   if (instr_fmt_type == instr_fmt_paje) {
451     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
452     stream << std::fixed << std::setprecision(TRACE_precision());
453     stream << (int)this->event_type;
454     print_timestamp(this);
455     stream << " " << type->id << " " << container->id << " " << value;
456     print_row();
457   } else if (instr_fmt_type == instr_fmt_TI) {
458     /* Nothing to do */
459   } else {
460     THROW_IMPOSSIBLE;
461   }
462 }
463
464 SubVariableEvent::SubVariableEvent (double timestamp, container_t container, type_t type, double value)
465 {
466   this->event_type                         = PAJE_SubVariable;
467   this->timestamp                          = timestamp;
468   this->type      = type;
469   this->container = container;
470   this->value     = value;
471
472   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
473
474   insert_into_buffer (this);
475 }
476
477 void SubVariableEvent::print() {
478   if (instr_fmt_type == instr_fmt_paje) {
479     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
480     stream << std::fixed << std::setprecision(TRACE_precision());
481     stream << (int)this->event_type;
482     print_timestamp(this);
483     stream << " " << type->id << " " << container->id << " " << value;
484     print_row();
485   } else if (instr_fmt_type == instr_fmt_TI) {
486     /* Nothing to do */
487   } else {
488     THROW_IMPOSSIBLE;
489   }
490 }
491
492 SetStateEvent::SetStateEvent (double timestamp, container_t container, type_t type, val_t value)
493 {
494   this->event_type                      = PAJE_SetState;
495   this->timestamp                       = timestamp;
496   this->type      = type;
497   this->container = container;
498   this->value     = value;
499
500 #if HAVE_SMPI
501   if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
502     smpi_trace_call_location_t* loc = smpi_trace_get_call_location();
503     filename   = loc->filename;
504     linenumber = loc->linenumber;
505   }
506 #endif
507
508   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
509
510   insert_into_buffer (this);
511 }
512
513 void SetStateEvent::print() {
514   if (instr_fmt_type == instr_fmt_paje) {
515     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
516     stream << std::fixed << std::setprecision(TRACE_precision());
517     stream << (int)this->event_type;
518     print_timestamp(this);
519     stream << " " << type->id << " " << container->id;
520     stream << " " << value->id;
521 #if HAVE_SMPI
522     if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
523       stream << " \"" << filename << "\" " << linenumber;
524     }
525 #endif
526     print_row();
527   } else if (instr_fmt_type == instr_fmt_TI) {
528     /* Nothing to do */
529   } else {
530     THROW_IMPOSSIBLE;
531   }
532 }
533
534 PushStateEvent::PushStateEvent (double timestamp, container_t container, type_t type, val_t value, void* extra)
535 {
536   this->event_type                  = PAJE_PushState;
537   this->timestamp                   = timestamp;
538   this->type = type;
539   this->container = container;
540   this->value     = value;
541   this->extra_     = extra;
542
543 #if HAVE_SMPI
544   if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
545     smpi_trace_call_location_t* loc = smpi_trace_get_call_location();
546     filename   = loc->filename;
547     linenumber = loc->linenumber;
548   }
549 #endif
550
551   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
552
553   insert_into_buffer (this);
554 }
555
556 PushStateEvent::PushStateEvent (double timestamp, container_t container, type_t type, val_t value)
557  : PushStateEvent(timestamp, container, type, value, nullptr)
558 {}
559 void PushStateEvent::print() {
560   if (instr_fmt_type == instr_fmt_paje) {
561     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
562     stream << std::fixed << std::setprecision(TRACE_precision());
563     stream << (int)this->event_type;
564     print_timestamp(this);
565     stream << " " << type->id << " " << container->id;
566     stream << " " << value->id;
567
568     if (TRACE_display_sizes()) {
569       stream << " ";
570       if (extra_ != nullptr) {
571         stream << static_cast<instr_extra_data>(extra_)->send_size;
572       } else {
573         stream << 0;
574       }
575     }
576 #if HAVE_SMPI
577     if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
578       stream << " \"" << filename << "\" " << linenumber;
579     }
580 #endif
581     print_row();
582
583     if (extra_ != nullptr) {
584       if (static_cast<instr_extra_data>(extra_)->sendcounts != nullptr)
585         xbt_free(static_cast<instr_extra_data>(extra_)->sendcounts);
586       if (static_cast<instr_extra_data>(extra_)->recvcounts != nullptr)
587         xbt_free(static_cast<instr_extra_data>(extra_)->recvcounts);
588       xbt_free(extra_);
589     }
590   } else if (instr_fmt_type == instr_fmt_TI) {
591     if (extra_ == nullptr)
592       return;
593     instr_extra_data extra = (instr_extra_data)extra_;
594
595     char* process_id = nullptr;
596     // FIXME: dirty extract "rank-" from the name, as we want the bare process id here
597     if (strstr(container->name, "rank-") == nullptr)
598       process_id = xbt_strdup(container->name);
599     else
600       process_id = xbt_strdup(container->name + 5);
601
602     FILE* trace_file = (FILE*)xbt_dict_get(tracing_files, container->name);
603
604     switch (extra->type) {
605       case TRACING_INIT:
606         fprintf(trace_file, "%s init\n", process_id);
607         break;
608       case TRACING_FINALIZE:
609         fprintf(trace_file, "%s finalize\n", process_id);
610         break;
611       case TRACING_SEND:
612         fprintf(trace_file, "%s send %d %d %s\n", process_id, extra->dst, extra->send_size, extra->datatype1);
613         break;
614       case TRACING_ISEND:
615         fprintf(trace_file, "%s Isend %d %d %s\n", process_id, extra->dst, extra->send_size, extra->datatype1);
616         break;
617       case TRACING_RECV:
618         fprintf(trace_file, "%s recv %d %d %s\n", process_id, extra->src, extra->send_size, extra->datatype1);
619         break;
620       case TRACING_IRECV:
621         fprintf(trace_file, "%s Irecv %d %d %s\n", process_id, extra->src, extra->send_size, extra->datatype1);
622         break;
623       case TRACING_TEST:
624         fprintf(trace_file, "%s test\n", process_id);
625         break;
626       case TRACING_WAIT:
627         fprintf(trace_file, "%s wait\n", process_id);
628         break;
629       case TRACING_WAITALL:
630         fprintf(trace_file, "%s waitAll\n", process_id);
631         break;
632       case TRACING_BARRIER:
633         fprintf(trace_file, "%s barrier\n", process_id);
634         break;
635       case TRACING_BCAST: // rank bcast size (root) (datatype)
636         fprintf(trace_file, "%s bcast %d ", process_id, extra->send_size);
637         if (extra->root != 0 || (extra->datatype1 && strcmp(extra->datatype1, "")))
638           fprintf(trace_file, "%d %s", extra->root, extra->datatype1);
639         fprintf(trace_file, "\n");
640         break;
641       case TRACING_REDUCE: // rank reduce comm_size comp_size (root) (datatype)
642         fprintf(trace_file, "%s reduce %d %f ", process_id, extra->send_size, extra->comp_size);
643         if (extra->root != 0 || (extra->datatype1 && strcmp(extra->datatype1, "")))
644           fprintf(trace_file, "%d %s", extra->root, extra->datatype1);
645         fprintf(trace_file, "\n");
646         break;
647       case TRACING_ALLREDUCE: // rank allreduce comm_size comp_size (datatype)
648         fprintf(trace_file, "%s allReduce %d %f %s\n", process_id, extra->send_size, extra->comp_size,
649                 extra->datatype1);
650         break;
651       case TRACING_ALLTOALL: // rank alltoall send_size recv_size (sendtype) (recvtype)
652         fprintf(trace_file, "%s allToAll %d %d %s %s\n", process_id, extra->send_size, extra->recv_size,
653                 extra->datatype1, extra->datatype2);
654         break;
655       case TRACING_ALLTOALLV: // rank alltoallv send_size [sendcounts] recv_size [recvcounts] (sendtype) (recvtype)
656         fprintf(trace_file, "%s allToAllV %d ", process_id, extra->send_size);
657         for (int i = 0; i < extra->num_processes; i++)
658           fprintf(trace_file, "%d ", extra->sendcounts[i]);
659         fprintf(trace_file, "%d ", extra->recv_size);
660         for (int i = 0; i < extra->num_processes; i++)
661           fprintf(trace_file, "%d ", extra->recvcounts[i]);
662         fprintf(trace_file, "%s %s \n", extra->datatype1, extra->datatype2);
663         break;
664       case TRACING_GATHER: // rank gather send_size recv_size root (sendtype) (recvtype)
665         fprintf(trace_file, "%s gather %d %d %d %s %s\n", process_id, extra->send_size, extra->recv_size, extra->root,
666                 extra->datatype1, extra->datatype2);
667         break;
668       case TRACING_ALLGATHERV: // rank allgatherv send_size [recvcounts] (sendtype) (recvtype)
669         fprintf(trace_file, "%s allGatherV %d ", process_id, extra->send_size);
670         for (int i = 0; i < extra->num_processes; i++)
671           fprintf(trace_file, "%d ", extra->recvcounts[i]);
672         fprintf(trace_file, "%s %s \n", extra->datatype1, extra->datatype2);
673         break;
674       case TRACING_REDUCE_SCATTER: // rank reducescatter [recvcounts] comp_size (sendtype)
675         fprintf(trace_file, "%s reduceScatter ", process_id);
676         for (int i = 0; i < extra->num_processes; i++)
677           fprintf(trace_file, "%d ", extra->recvcounts[i]);
678         fprintf(trace_file, "%f %s\n", extra->comp_size, extra->datatype1);
679         break;
680       case TRACING_COMPUTING:
681         fprintf(trace_file, "%s compute %f\n", process_id, extra->comp_size);
682         break;
683       case TRACING_SLEEPING:
684         fprintf(trace_file, "%s sleep %f\n", process_id, extra->sleep_duration);
685         break;
686       case TRACING_GATHERV: // rank gatherv send_size [recvcounts] root (sendtype) (recvtype)
687         fprintf(trace_file, "%s gatherV %d ", process_id, extra->send_size);
688         for (int i = 0; i < extra->num_processes; i++)
689           fprintf(trace_file, "%d ", extra->recvcounts[i]);
690         fprintf(trace_file, "%d %s %s\n", extra->root, extra->datatype1, extra->datatype2);
691         break;
692       case TRACING_WAITANY:
693       case TRACING_SENDRECV:
694       case TRACING_SCATTER:
695       case TRACING_SCATTERV:
696       case TRACING_ALLGATHER:
697       case TRACING_SCAN:
698       case TRACING_EXSCAN:
699       case TRACING_COMM_SIZE:
700       case TRACING_COMM_SPLIT:
701       case TRACING_COMM_DUP:
702       case TRACING_SSEND:
703       case TRACING_ISSEND:
704       default:
705         XBT_WARN("Call from %s impossible to translate into replay command : Not implemented (yet)", value->name);
706         break;
707     }
708
709     if (extra->recvcounts != nullptr)
710       xbt_free(extra->recvcounts);
711     if (extra->sendcounts != nullptr)
712       xbt_free(extra->sendcounts);
713     xbt_free(process_id);
714     xbt_free(extra);
715
716   } else {
717     THROW_IMPOSSIBLE;
718   }
719 }
720
721
722 PopStateEvent::PopStateEvent (double timestamp, container_t container, type_t type)
723 {
724   this->event_type                      = PAJE_PopState;
725   this->timestamp                       = timestamp;
726   this->type      = type;
727   this->container = container;
728
729   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
730
731   insert_into_buffer (this);
732 }
733
734 void PopStateEvent::print() {
735   if (instr_fmt_type == instr_fmt_paje) {
736     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
737     stream << std::fixed << std::setprecision(TRACE_precision());
738     stream << (int)this->event_type;
739     print_timestamp(this);
740     stream << " " << type->id << " " << container->id;
741     print_row();
742   } else if (instr_fmt_type == instr_fmt_TI) {
743     /* Nothing to do */
744   } else {
745     THROW_IMPOSSIBLE;
746   }
747 }
748
749 ResetStateEvent::ResetStateEvent (double timestamp, container_t container, type_t type)
750 {
751   this->event_type                        = PAJE_ResetState;
752   this->timestamp                         = timestamp;
753   this->type      = type;
754   this->container = container;
755
756   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
757
758   insert_into_buffer (this);
759         delete [] this;
760 }
761
762 void ResetStateEvent::print() {
763   if (instr_fmt_type == instr_fmt_paje) {
764     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
765     stream << std::fixed << std::setprecision(TRACE_precision());
766     stream << (int)this->event_type;
767     print_timestamp(this);
768     stream << " " << type->id << " " << container->id;
769     print_row();
770   } else if (instr_fmt_type == instr_fmt_TI) {
771     /* Nothing to do */
772   } else {
773     THROW_IMPOSSIBLE;
774   }
775 }
776
777 StartLinkEvent::~StartLinkEvent()
778 {
779   free(value);
780   free(key);
781 }
782 StartLinkEvent::StartLinkEvent (double timestamp, container_t container,
783     type_t type, container_t sourceContainer, const char *value, const char *key)
784   : StartLinkEvent(timestamp, container, type, sourceContainer, value, key, -1)
785 {}
786
787 StartLinkEvent::StartLinkEvent (double timestamp, container_t container, type_t type, container_t sourceContainer,
788                                 const char *value, const char *key, int size)
789 {
790   event_type                             = PAJE_StartLink;
791   this->timestamp       = timestamp;
792   this->type            = type;
793   this->container       = container;
794   this->sourceContainer = sourceContainer;
795   this->value           = xbt_strdup(value);
796   this->key             = xbt_strdup(key);
797   this->size            = size;
798
799   XBT_DEBUG("%s: event_type=%d, timestamp=%f, value:%s", __FUNCTION__,
800       (int)event_type, this->timestamp, this->value);
801
802   insert_into_buffer (this);
803 }
804
805 void StartLinkEvent::print() {
806   if (instr_fmt_type == instr_fmt_paje) {
807     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
808     stream << std::fixed << std::setprecision(TRACE_precision());
809     stream << (int)this->event_type;
810     print_timestamp(this);
811     stream << " " << type->id << " " << container->id << " " << value;
812     stream << " " << sourceContainer->id << " " << key;
813
814     if (TRACE_display_sizes()) {
815       stream << " " << size;
816     }
817     print_row();
818   } else if (instr_fmt_type == instr_fmt_TI) {
819     /* Nothing to do */
820   } else {
821     THROW_IMPOSSIBLE;
822   }
823 }
824
825 EndLinkEvent::EndLinkEvent (double timestamp, container_t container, type_t type, container_t destContainer,
826                       const char *value, const char *key)
827 {
828   this->event_type                         = PAJE_EndLink;
829   this->timestamp                          = timestamp;
830   this->type          = type;
831   this->container     = container;
832   this->destContainer = destContainer;
833   this->value         = xbt_strdup(value);
834   this->key           = xbt_strdup(key);
835
836   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
837
838   insert_into_buffer (this);
839 }
840
841 EndLinkEvent::~EndLinkEvent()
842 {
843   free(value);
844   free(key);
845 }
846 void EndLinkEvent::print() {
847   if (instr_fmt_type == instr_fmt_paje) {
848     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
849     stream << std::fixed << std::setprecision(TRACE_precision());
850     stream << (int)this->event_type;
851     print_timestamp(this);
852     stream << " " << type->id << " " << container->id << " " << value;
853     stream << " " << destContainer->id << " " << key;
854     print_row();
855   } else if (instr_fmt_type == instr_fmt_TI) {
856     /* Nothing to do */
857   } else {
858     THROW_IMPOSSIBLE;
859   }
860 }
861
862 NewEvent::NewEvent (double timestamp, container_t container, type_t type, val_t value)
863 {
864   this->event_type                      = PAJE_NewEvent;
865   this->timestamp                       = timestamp;
866   this->type      = type;
867   this->container = container;
868   this->value     = value;
869
870   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
871
872   insert_into_buffer (this);
873 }
874
875 void NewEvent::print () {
876   if (instr_fmt_type == instr_fmt_paje) {
877     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
878     stream << std::fixed << std::setprecision(TRACE_precision());
879     stream << (int)this->event_type;
880     print_timestamp(this);
881     stream << " " << type->id << " " << container->id << " " << value->id;
882     print_row();
883   } else if (instr_fmt_type == instr_fmt_TI) {
884     /* Nothing to do */
885   } else {
886     THROW_IMPOSSIBLE;
887   }
888 }
889
890
891 void TRACE_TI_start()
892 {
893   char *filename = TRACE_get_filename();
894   tracing_file = fopen(filename, "w");
895   if (tracing_file == nullptr)
896     THROWF(system_error, 1, "Tracefile %s could not be opened for writing.", filename);
897
898   XBT_DEBUG("Filename %s is open for writing", filename);
899
900   /* output one line comment */
901   dump_comment(TRACE_get_comment());
902
903   /* output comment file */
904   dump_comment_file(TRACE_get_comment_file());
905 }
906
907 void TRACE_TI_end()
908 {
909   xbt_dict_free(&tracing_files);
910   fclose(tracing_file);
911   char *filename = TRACE_get_filename();
912   XBT_DEBUG("Filename %s is closed", filename);
913 }
914