Logo AND Algorithmique Numérique Distribuée

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