Logo AND Algorithmique Numérique Distribuée

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