Logo AND Algorithmique Numérique Distribuée

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