Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
651368514d54af155635ccaa6e11ba4ed6c2de14
[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 << " " << type->father->id << " " << type->name;
224     print_row();
225   } else if (instr_fmt_type == instr_fmt_TI) {
226     /* Nothing to do */
227   } else {
228     THROW_IMPOSSIBLE;
229   }
230   //--
231 }
232
233
234
235 void LogVariableTypeDefinition(type_t type)
236 {
237
238   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineVariableType);
239
240   //print it
241 if (instr_fmt_type == instr_fmt_paje) {
242     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineVariableType, TRACE_precision(), 0.);
243     stream << std::fixed << std::setprecision(TRACE_precision());
244     stream << PAJE_DefineVariableType;
245     stream << " " << type->id << " " << type->father->id << " " << type->name;
246     if (type->color)
247       stream << " \"" << type->color << "\"";
248     print_row();
249   } else if (instr_fmt_type == instr_fmt_TI) {
250     /* Nothing to do */
251   } else {
252     THROW_IMPOSSIBLE;
253   }
254 }
255
256
257 void LogStateTypeDefinition(type_t type)
258 {
259   //print it
260 if (instr_fmt_type == instr_fmt_paje) {
261     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineStateType, TRACE_precision(), 0.);
262     stream << std::fixed << std::setprecision(TRACE_precision());
263     stream << PAJE_DefineStateType;
264     stream << " " << type->id << " " << type->father->id << " " << type->name;
265     print_row();
266   } else if (instr_fmt_type == instr_fmt_TI) {
267     /* Nothing to do */
268   } else {
269     THROW_IMPOSSIBLE;
270   }
271 }
272
273
274 void LogDefineEventType(type_t type)
275 {
276   //print it
277   if (instr_fmt_type == instr_fmt_paje) {
278     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineEventType, TRACE_precision(), 0.);
279     stream << std::fixed << std::setprecision(TRACE_precision());
280     stream << PAJE_DefineEventType;
281     stream << " " << type->id << " " << type->father->id << " " << type->name;
282     print_row();
283   } else if (instr_fmt_type == instr_fmt_TI) {
284     /* Nothing to do */
285   } else {
286     THROW_IMPOSSIBLE;
287   }
288 }
289
290 void LogLinkTypeDefinition(type_t type, type_t source, type_t dest)
291 {
292   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineLinkType);
293   //print it
294 if (instr_fmt_type == instr_fmt_paje) {
295     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, PAJE_DefineLinkType, TRACE_precision(), 0.);
296     stream << std::fixed << std::setprecision(TRACE_precision());
297     stream << PAJE_DefineLinkType;
298     stream << " " << type->id << " " << type->father->id << " " << source->id << " " << dest->id << " " << type->name;
299     print_row();
300   } else if (instr_fmt_type == instr_fmt_TI) {
301     /* Nothing to do */
302   } else {
303     THROW_IMPOSSIBLE;
304   }
305 }
306
307 void LogEntityValue (val_t value)
308 {
309   XBT_DEBUG("%s: event_type=%d", __FUNCTION__, PAJE_DefineEntityValue);
310   //print it
311 if (instr_fmt_type == instr_fmt_paje) {
312     stream << std::fixed << std::setprecision(TRACE_precision());
313     stream << PAJE_DefineEntityValue;
314     stream << " " << value->id << " " << value->father->id << " " << value->name;
315     if (value->color)
316       stream << " \"" << value->color << "\"";
317     print_row();
318   } else if (instr_fmt_type == instr_fmt_TI) {
319     /* Nothing to do */
320   } else {
321     THROW_IMPOSSIBLE;
322   }
323 }
324
325
326 void LogContainerCreation (container_t container)
327 {
328   double timestamp                              = SIMIX_get_clock();
329
330   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, PAJE_CreateContainer,timestamp);
331
332 if (instr_fmt_type == instr_fmt_paje) {
333     stream << std::fixed << std::setprecision(TRACE_precision());
334     stream << PAJE_CreateContainer;
335     stream << " ";
336   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
337     if (timestamp < 1e-12)
338       stream << 0;
339     else
340       stream << timestamp;
341     stream << " " << container->id << " " << container->type->id << " " << container->father->id << " \""
342            << container->name << "\"";
343
344     print_row();
345   } else if (instr_fmt_type == instr_fmt_TI) {
346     // if we are in the mode with only one file
347     static FILE* ti_unique_file = nullptr;
348
349     if (tracing_files == nullptr) {
350       tracing_files = xbt_dict_new_homogeneous(nullptr);
351       // generate unique run id with time
352       prefix = xbt_os_time();
353     }
354
355     if (not xbt_cfg_get_boolean("tracing/smpi/format/ti-one-file") || ti_unique_file == nullptr) {
356       char* folder_name = bprintf("%s_files", TRACE_get_filename());
357       char* filename    = bprintf("%s/%f_%s.txt", folder_name, prefix, container->name);
358 #ifdef WIN32
359       _mkdir(folder_name);
360 #else
361       mkdir(folder_name, S_IRWXU | S_IRWXG | S_IRWXO);
362 #endif
363       ti_unique_file = fopen(filename, "w");
364       xbt_assert(ti_unique_file, "Tracefile %s could not be opened for writing: %s", filename, strerror(errno));
365       fprintf(tracing_file, "%s\n", filename);
366
367       xbt_free(folder_name);
368       xbt_free(filename);
369     }
370
371     xbt_dict_set(tracing_files, container->name, (void*)ti_unique_file, nullptr);
372   } else {
373     THROW_IMPOSSIBLE;
374   }
375 }
376
377 void LogContainerDestruction(container_t container)
378 {
379   double timestamp                               = SIMIX_get_clock();
380
381   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, PAJE_DestroyContainer, timestamp);
382
383 if (instr_fmt_type == instr_fmt_paje) {
384     stream << std::fixed << std::setprecision(TRACE_precision());
385     stream << PAJE_DestroyContainer;
386     stream << " ";
387   /* prevent 0.0000 in the trace - this was the behavior before the transition to c++ */
388     if (timestamp < 1e-12)
389         stream << 0;
390     else 
391         stream << timestamp;
392     stream << " " << container->type->id << " " << container->id;
393     print_row();
394   } else if (instr_fmt_type == instr_fmt_TI) {
395     if (not xbt_cfg_get_boolean("tracing/smpi/format/ti-one-file") || xbt_dict_length(tracing_files) == 1) {
396       FILE* f = (FILE*)xbt_dict_get_or_null(tracing_files, container->name);
397       fclose(f);
398     }
399     xbt_dict_remove(tracing_files, container->name);
400         } else {
401           THROW_IMPOSSIBLE;
402         }
403 }
404
405
406 SetVariableEvent::SetVariableEvent (double timestamp, container_t container, type_t type, double value)
407 {
408   this->event_type                         = PAJE_SetVariable;
409   this->timestamp                          = timestamp;
410   this->type      = type;
411   this->container = container;
412   this->value     = value;
413
414   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
415
416   insert_into_buffer (this);
417 }
418
419 void SetVariableEvent::print() {
420   if (instr_fmt_type == instr_fmt_paje) {
421     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
422     stream << std::fixed << std::setprecision(TRACE_precision());
423     stream << (int)this->event_type;
424     print_timestamp(this);
425     stream << " " << type->id << " " << container->id << " " << value;
426     print_row();
427   } else if (instr_fmt_type == instr_fmt_TI) {
428     /* Nothing to do */
429   } else {
430     THROW_IMPOSSIBLE;
431   }
432 }
433
434 AddVariableEvent::AddVariableEvent (double timestamp, container_t container, type_t type, double value)
435 {
436   this->event_type                         = PAJE_AddVariable;
437   this->timestamp                          = timestamp;
438   this->type      = type;
439   this->container = container;
440   this->value     = value;
441
442   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
443
444   insert_into_buffer (this);
445 }
446
447 void AddVariableEvent::print() {
448   if (instr_fmt_type == instr_fmt_paje) {
449     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
450     stream << std::fixed << std::setprecision(TRACE_precision());
451     stream << (int)this->event_type;
452     print_timestamp(this);
453     stream << " " << type->id << " " << container->id << " " << value;
454     print_row();
455   } else if (instr_fmt_type == instr_fmt_TI) {
456     /* Nothing to do */
457   } else {
458     THROW_IMPOSSIBLE;
459   }
460 }
461
462 SubVariableEvent::SubVariableEvent (double timestamp, container_t container, type_t type, double value)
463 {
464   this->event_type                         = PAJE_SubVariable;
465   this->timestamp                          = timestamp;
466   this->type      = type;
467   this->container = container;
468   this->value     = value;
469
470   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
471
472   insert_into_buffer (this);
473 }
474
475 void SubVariableEvent::print() {
476   if (instr_fmt_type == instr_fmt_paje) {
477     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
478     stream << std::fixed << std::setprecision(TRACE_precision());
479     stream << (int)this->event_type;
480     print_timestamp(this);
481     stream << " " << type->id << " " << container->id << " " << value;
482     print_row();
483   } else if (instr_fmt_type == instr_fmt_TI) {
484     /* Nothing to do */
485   } else {
486     THROW_IMPOSSIBLE;
487   }
488 }
489
490 SetStateEvent::SetStateEvent (double timestamp, container_t container, type_t type, val_t value)
491 {
492   this->event_type                      = PAJE_SetState;
493   this->timestamp                       = timestamp;
494   this->type      = type;
495   this->container = container;
496   this->value     = value;
497
498 #if HAVE_SMPI
499   if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
500     smpi_trace_call_location_t* loc = smpi_trace_get_call_location();
501     filename   = loc->filename;
502     linenumber = loc->linenumber;
503   }
504 #endif
505
506   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
507
508   insert_into_buffer (this);
509 }
510
511 void SetStateEvent::print() {
512   if (instr_fmt_type == instr_fmt_paje) {
513     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
514     stream << std::fixed << std::setprecision(TRACE_precision());
515     stream << (int)this->event_type;
516     print_timestamp(this);
517     stream << " " << type->id << " " << container->id;
518     stream << " " << value->id;
519 #if HAVE_SMPI
520     if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
521       stream << " \"" << filename << "\" " << linenumber;
522     }
523 #endif
524     print_row();
525   } else if (instr_fmt_type == instr_fmt_TI) {
526     /* Nothing to do */
527   } else {
528     THROW_IMPOSSIBLE;
529   }
530 }
531
532 PushStateEvent::PushStateEvent (double timestamp, container_t container, type_t type, val_t value, void* extra)
533 {
534   this->event_type                  = PAJE_PushState;
535   this->timestamp                   = timestamp;
536   this->type = type;
537   this->container = container;
538   this->value     = value;
539   this->extra_     = extra;
540
541 #if HAVE_SMPI
542   if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
543     smpi_trace_call_location_t* loc = smpi_trace_get_call_location();
544     filename   = loc->filename;
545     linenumber = loc->linenumber;
546   }
547 #endif
548
549   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
550
551   insert_into_buffer (this);
552 }
553
554 PushStateEvent::PushStateEvent (double timestamp, container_t container, type_t type, val_t value)
555  : PushStateEvent(timestamp, container, type, value, nullptr)
556 {}
557 void PushStateEvent::print() {
558   if (instr_fmt_type == instr_fmt_paje) {
559     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
560     stream << std::fixed << std::setprecision(TRACE_precision());
561     stream << (int)this->event_type;
562     print_timestamp(this);
563     stream << " " << type->id << " " << container->id;
564     stream << " " << value->id;
565
566     if (TRACE_display_sizes()) {
567       stream << " ";
568       if (extra_ != nullptr) {
569         stream << static_cast<instr_extra_data>(extra_)->send_size;
570       } else {
571         stream << 0;
572       }
573     }
574 #if HAVE_SMPI
575     if (xbt_cfg_get_boolean("smpi/trace-call-location")) {
576       stream << " \"" << filename << "\" " << linenumber;
577     }
578 #endif
579     print_row();
580
581     if (extra_ != nullptr) {
582       if (static_cast<instr_extra_data>(extra_)->sendcounts != nullptr)
583         xbt_free(static_cast<instr_extra_data>(extra_)->sendcounts);
584       if (static_cast<instr_extra_data>(extra_)->recvcounts != nullptr)
585         xbt_free(static_cast<instr_extra_data>(extra_)->recvcounts);
586       xbt_free(extra_);
587     }
588   } else if (instr_fmt_type == instr_fmt_TI) {
589     if (extra_ == nullptr)
590       return;
591     instr_extra_data extra = (instr_extra_data)extra_;
592
593     char* process_id = nullptr;
594     // FIXME: dirty extract "rank-" from the name, as we want the bare process id here
595     if (strstr(container->name, "rank-") == nullptr)
596       process_id = xbt_strdup(container->name);
597     else
598       process_id = xbt_strdup(container->name + 5);
599
600     FILE* trace_file = (FILE*)xbt_dict_get(tracing_files, container->name);
601
602     switch (extra->type) {
603       case TRACING_INIT:
604         fprintf(trace_file, "%s init\n", process_id);
605         break;
606       case TRACING_FINALIZE:
607         fprintf(trace_file, "%s finalize\n", process_id);
608         break;
609       case TRACING_SEND:
610         fprintf(trace_file, "%s send %d %d %s\n", process_id, extra->dst, extra->send_size, extra->datatype1);
611         break;
612       case TRACING_ISEND:
613         fprintf(trace_file, "%s Isend %d %d %s\n", process_id, extra->dst, extra->send_size, extra->datatype1);
614         break;
615       case TRACING_RECV:
616         fprintf(trace_file, "%s recv %d %d %s\n", process_id, extra->src, extra->send_size, extra->datatype1);
617         break;
618       case TRACING_IRECV:
619         fprintf(trace_file, "%s Irecv %d %d %s\n", process_id, extra->src, extra->send_size, extra->datatype1);
620         break;
621       case TRACING_TEST:
622         fprintf(trace_file, "%s test\n", process_id);
623         break;
624       case TRACING_WAIT:
625         fprintf(trace_file, "%s wait\n", process_id);
626         break;
627       case TRACING_WAITALL:
628         fprintf(trace_file, "%s waitAll\n", process_id);
629         break;
630       case TRACING_BARRIER:
631         fprintf(trace_file, "%s barrier\n", process_id);
632         break;
633       case TRACING_BCAST: // rank bcast size (root) (datatype)
634         fprintf(trace_file, "%s bcast %d ", process_id, extra->send_size);
635         if (extra->root != 0 || (extra->datatype1 && strcmp(extra->datatype1, "")))
636           fprintf(trace_file, "%d %s", extra->root, extra->datatype1);
637         fprintf(trace_file, "\n");
638         break;
639       case TRACING_REDUCE: // rank reduce comm_size comp_size (root) (datatype)
640         fprintf(trace_file, "%s reduce %d %f ", process_id, extra->send_size, extra->comp_size);
641         if (extra->root != 0 || (extra->datatype1 && strcmp(extra->datatype1, "")))
642           fprintf(trace_file, "%d %s", extra->root, extra->datatype1);
643         fprintf(trace_file, "\n");
644         break;
645       case TRACING_ALLREDUCE: // rank allreduce comm_size comp_size (datatype)
646         fprintf(trace_file, "%s allReduce %d %f %s\n", process_id, extra->send_size, extra->comp_size,
647                 extra->datatype1);
648         break;
649       case TRACING_ALLTOALL: // rank alltoall send_size recv_size (sendtype) (recvtype)
650         fprintf(trace_file, "%s allToAll %d %d %s %s\n", process_id, extra->send_size, extra->recv_size,
651                 extra->datatype1, extra->datatype2);
652         break;
653       case TRACING_ALLTOALLV: // rank alltoallv send_size [sendcounts] recv_size [recvcounts] (sendtype) (recvtype)
654         fprintf(trace_file, "%s allToAllV %d ", process_id, extra->send_size);
655         for (int i = 0; i < extra->num_processes; i++)
656           fprintf(trace_file, "%d ", extra->sendcounts[i]);
657         fprintf(trace_file, "%d ", extra->recv_size);
658         for (int i = 0; i < extra->num_processes; i++)
659           fprintf(trace_file, "%d ", extra->recvcounts[i]);
660         fprintf(trace_file, "%s %s \n", extra->datatype1, extra->datatype2);
661         break;
662       case TRACING_GATHER: // rank gather send_size recv_size root (sendtype) (recvtype)
663         fprintf(trace_file, "%s gather %d %d %d %s %s\n", process_id, extra->send_size, extra->recv_size, extra->root,
664                 extra->datatype1, extra->datatype2);
665         break;
666       case TRACING_ALLGATHERV: // rank allgatherv send_size [recvcounts] (sendtype) (recvtype)
667         fprintf(trace_file, "%s allGatherV %d ", process_id, extra->send_size);
668         for (int i = 0; i < extra->num_processes; i++)
669           fprintf(trace_file, "%d ", extra->recvcounts[i]);
670         fprintf(trace_file, "%s %s \n", extra->datatype1, extra->datatype2);
671         break;
672       case TRACING_REDUCE_SCATTER: // rank reducescatter [recvcounts] comp_size (sendtype)
673         fprintf(trace_file, "%s reduceScatter ", process_id);
674         for (int i = 0; i < extra->num_processes; i++)
675           fprintf(trace_file, "%d ", extra->recvcounts[i]);
676         fprintf(trace_file, "%f %s\n", extra->comp_size, extra->datatype1);
677         break;
678       case TRACING_COMPUTING:
679         fprintf(trace_file, "%s compute %f\n", process_id, extra->comp_size);
680         break;
681       case TRACING_SLEEPING:
682         fprintf(trace_file, "%s sleep %f\n", process_id, extra->sleep_duration);
683         break;
684       case TRACING_GATHERV: // rank gatherv send_size [recvcounts] root (sendtype) (recvtype)
685         fprintf(trace_file, "%s gatherV %d ", process_id, extra->send_size);
686         for (int i = 0; i < extra->num_processes; i++)
687           fprintf(trace_file, "%d ", extra->recvcounts[i]);
688         fprintf(trace_file, "%d %s %s\n", extra->root, extra->datatype1, extra->datatype2);
689         break;
690       case TRACING_WAITANY:
691       case TRACING_SENDRECV:
692       case TRACING_SCATTER:
693       case TRACING_SCATTERV:
694       case TRACING_ALLGATHER:
695       case TRACING_SCAN:
696       case TRACING_EXSCAN:
697       case TRACING_COMM_SIZE:
698       case TRACING_COMM_SPLIT:
699       case TRACING_COMM_DUP:
700       case TRACING_SSEND:
701       case TRACING_ISSEND:
702       default:
703         XBT_WARN("Call from %s impossible to translate into replay command : Not implemented (yet)", value->name);
704         break;
705     }
706
707     if (extra->recvcounts != nullptr)
708       xbt_free(extra->recvcounts);
709     if (extra->sendcounts != nullptr)
710       xbt_free(extra->sendcounts);
711     xbt_free(process_id);
712     xbt_free(extra);
713
714   } else {
715     THROW_IMPOSSIBLE;
716   }
717 }
718
719
720 PopStateEvent::PopStateEvent (double timestamp, container_t container, type_t type)
721 {
722   this->event_type                      = PAJE_PopState;
723   this->timestamp                       = timestamp;
724   this->type      = type;
725   this->container = container;
726
727   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
728
729   insert_into_buffer (this);
730 }
731
732 void PopStateEvent::print() {
733   if (instr_fmt_type == instr_fmt_paje) {
734     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
735     stream << std::fixed << std::setprecision(TRACE_precision());
736     stream << (int)this->event_type;
737     print_timestamp(this);
738     stream << " " << type->id << " " << container->id;
739     print_row();
740   } else if (instr_fmt_type == instr_fmt_TI) {
741     /* Nothing to do */
742   } else {
743     THROW_IMPOSSIBLE;
744   }
745 }
746
747 ResetStateEvent::ResetStateEvent (double timestamp, container_t container, type_t type)
748 {
749   this->event_type                        = PAJE_ResetState;
750   this->timestamp                         = timestamp;
751   this->type      = type;
752   this->container = container;
753
754   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
755
756   insert_into_buffer (this);
757   delete[] this;
758 }
759
760 void ResetStateEvent::print() {
761   if (instr_fmt_type == instr_fmt_paje) {
762     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
763     stream << std::fixed << std::setprecision(TRACE_precision());
764     stream << (int)this->event_type;
765     print_timestamp(this);
766     stream << " " << type->id << " " << container->id;
767     print_row();
768   } else if (instr_fmt_type == instr_fmt_TI) {
769     /* Nothing to do */
770   } else {
771     THROW_IMPOSSIBLE;
772   }
773 }
774
775 StartLinkEvent::~StartLinkEvent()
776 {
777   free(value);
778   free(key);
779 }
780 StartLinkEvent::StartLinkEvent (double timestamp, container_t container,
781     type_t type, container_t sourceContainer, const char *value, const char *key)
782   : StartLinkEvent(timestamp, container, type, sourceContainer, value, key, -1)
783 {}
784
785 StartLinkEvent::StartLinkEvent (double timestamp, container_t container, type_t type, container_t sourceContainer,
786                                 const char *value, const char *key, int size)
787 {
788   event_type                             = PAJE_StartLink;
789   this->timestamp       = timestamp;
790   this->type            = type;
791   this->container       = container;
792   this->sourceContainer = sourceContainer;
793   this->value           = xbt_strdup(value);
794   this->key             = xbt_strdup(key);
795   this->size            = size;
796
797   XBT_DEBUG("%s: event_type=%d, timestamp=%f, value:%s", __FUNCTION__,
798       (int)event_type, this->timestamp, this->value);
799
800   insert_into_buffer (this);
801 }
802
803 void StartLinkEvent::print() {
804   if (instr_fmt_type == instr_fmt_paje) {
805     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
806     stream << std::fixed << std::setprecision(TRACE_precision());
807     stream << (int)this->event_type;
808     print_timestamp(this);
809     stream << " " << type->id << " " << container->id << " " << value;
810     stream << " " << sourceContainer->id << " " << key;
811
812     if (TRACE_display_sizes()) {
813       stream << " " << size;
814     }
815     print_row();
816   } else if (instr_fmt_type == instr_fmt_TI) {
817     /* Nothing to do */
818   } else {
819     THROW_IMPOSSIBLE;
820   }
821 }
822
823 EndLinkEvent::EndLinkEvent (double timestamp, container_t container, type_t type, container_t destContainer,
824                       const char *value, const char *key)
825 {
826   this->event_type                         = PAJE_EndLink;
827   this->timestamp                          = timestamp;
828   this->type          = type;
829   this->container     = container;
830   this->destContainer = destContainer;
831   this->value         = xbt_strdup(value);
832   this->key           = xbt_strdup(key);
833
834   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
835
836   insert_into_buffer (this);
837 }
838
839 EndLinkEvent::~EndLinkEvent()
840 {
841   free(value);
842   free(key);
843 }
844 void EndLinkEvent::print() {
845   if (instr_fmt_type == instr_fmt_paje) {
846     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
847     stream << std::fixed << std::setprecision(TRACE_precision());
848     stream << (int)this->event_type;
849     print_timestamp(this);
850     stream << " " << type->id << " " << container->id << " " << value;
851     stream << " " << destContainer->id << " " << key;
852     print_row();
853   } else if (instr_fmt_type == instr_fmt_TI) {
854     /* Nothing to do */
855   } else {
856     THROW_IMPOSSIBLE;
857   }
858 }
859
860 NewEvent::NewEvent (double timestamp, container_t container, type_t type, val_t value)
861 {
862   this->event_type                      = PAJE_NewEvent;
863   this->timestamp                       = timestamp;
864   this->type      = type;
865   this->container = container;
866   this->value     = value;
867
868   XBT_DEBUG("%s: event_type=%d, timestamp=%f", __FUNCTION__, (int)event_type, this->timestamp);
869
870   insert_into_buffer (this);
871 }
872
873 void NewEvent::print () {
874   if (instr_fmt_type == instr_fmt_paje) {
875     XBT_DEBUG("%s: event_type=%d, timestamp=%.*f", __FUNCTION__, (int)event_type, TRACE_precision(), timestamp);
876     stream << std::fixed << std::setprecision(TRACE_precision());
877     stream << (int)this->event_type;
878     print_timestamp(this);
879     stream << " " << type->id << " " << container->id << " " << value->id;
880     print_row();
881   } else if (instr_fmt_type == instr_fmt_TI) {
882     /* Nothing to do */
883   } else {
884     THROW_IMPOSSIBLE;
885   }
886 }
887
888
889 void TRACE_TI_start()
890 {
891   char *filename = TRACE_get_filename();
892   tracing_file = fopen(filename, "w");
893   if (tracing_file == nullptr)
894     THROWF(system_error, 1, "Tracefile %s could not be opened for writing.", filename);
895
896   XBT_DEBUG("Filename %s is open for writing", filename);
897
898   /* output one line comment */
899   dump_comment(TRACE_get_comment());
900
901   /* output comment file */
902   dump_comment_file(TRACE_get_comment_file());
903 }
904
905 void TRACE_TI_end()
906 {
907   xbt_dict_free(&tracing_files);
908   fclose(tracing_file);
909   char *filename = TRACE_get_filename();
910   XBT_DEBUG("Filename %s is closed", filename);
911 }
912