Logo AND Algorithmique Numérique Distribuée

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