diff --git a/configure b/configure index 52fa94dc37c04bc00f1c051870673a9eb3275330..a3b54d7c60401f7d20df389ed1450c660784f9d6 100755 --- a/configure +++ b/configure @@ -283,8 +283,8 @@ if [ $with_otf -ge 1 ]; then exit; else defines="$defines WITH_OTF" - sources="$sources parser/ParserOTF.cpp parser/ParserEventOTF.cpp parser/ParserDefinitionOTF.cpp" - headers="$headers parser/ParserOTF.hpp parser/ParserEventOTF.hpp parser/ParserDefinitionOTF.hpp" + sources="$sources parser/ParserOTF.cpp parser/ParserEventOTF.cpp parser/OTFTraceBuilderThread.cpp parser/ParserDefinitionOTF.cpp parser/mt_ParserOTF.cpp parser/mt_ParserEventOTF.cpp" + headers="$headers parser/ParserOTF.hpp parser/ParserEventOTF.hpp parser/OTFTraceBuilderThread.hpp parser/ParserDefinitionOTF.hpp parser/mt_ParserOTF.hpp parser/mt_ParserEventOTF.hpp" includepath="$includepath $otfincdir" libs="$libs -L$otflibdir $otflibdir/libotf.a" fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e498fdf4d39c6c735a164597ed4bb7761bdc19f6..1c6af9d0880a0cbe15da91b75c4176ac1ad7708b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -282,6 +282,8 @@ IF(VITE_ENABLE_OTF) parser/ParserDefinitionOTF.hpp parser/ParserEventOTF.hpp parser/ParserOTF.hpp + parser/mt_ParserEventOTF.hpp + parser/mt_ParserOTF.hpp ) SET(VITE_SRCS @@ -289,6 +291,8 @@ IF(VITE_ENABLE_OTF) parser/ParserDefinitionOTF.cpp parser/ParserEventOTF.cpp parser/ParserOTF.cpp + parser/mt_ParserEventOTF.cpp + parser/mt_ParserOTF.cpp ) INCLUDE_DIRECTORIES(${OTF_INCLUDE_DIR}) diff --git a/src/common/Info.cpp b/src/common/Info.cpp index cf5593df2af5d656f5faf655bbfaaf8b1456571c..6bccab2fa7791747278b85b53a60e339551ae824 100644 --- a/src/common/Info.cpp +++ b/src/common/Info.cpp @@ -86,6 +86,7 @@ bool Info::Splitter::load_splitted = false; bool Info::Splitter::preview = false; std::string Info::Splitter::path ; std::string Info::Splitter::filename ; +std::string Info::Splitter::xml_filename ; Element_pos Info::Splitter::_x_min = 0.0; Element_pos Info::Splitter::_x_max = 0.0; diff --git a/src/common/Info.hpp b/src/common/Info.hpp index c50374c438f50681b3fc622d061ca39cc613af11..a77d50d53eb2d59670becfd750cb10f587386e5f 100644 --- a/src/common/Info.hpp +++ b/src/common/Info.hpp @@ -305,6 +305,10 @@ public: */ static std::string filename; /*! + * \brief filename of the node selection file, used to select nodes to display in PArserSplitted + */ + static std::string xml_filename; + /*! * \brief min time we want to load */ static Element_pos _x_min; diff --git a/src/core/Core.cpp b/src/core/Core.cpp index a5a0a1e981c2cec1a8c66dfab4ac2f57f444e2cd..ed45539dc07a70b6b8f0e7fc909247fbb4149fcb 100644 --- a/src/core/Core.cpp +++ b/src/core/Core.cpp @@ -131,6 +131,11 @@ #endif +#ifdef USE_MPI +#include <boost/mpi/environment.hpp> +#include <boost/mpi/communicator.hpp> +#endif + using namespace std; #define message *Message::get_instance() << "(" << __FILE__ << " l." << __LINE__ << "): " @@ -170,6 +175,10 @@ Core::Core(int &argc, char ** argv){ Message::set_interface(this);/* define which interface will receive messages */ _state = get_state(argc, argv); + + #ifdef USE_MPI + boost::mpi::environment env(argc, argv); + #endif if (_state!= _STATE_EXPORT_FILE) app = new QApplication(argc, argv);/* create the Qt application */ @@ -298,8 +307,10 @@ bool Core::draw_trace(const string & filename, const int format) { } #if defined(USE_ITC) && defined(BOOST_SERIALIZE) - Info::Splitter::path=QFileInfo(_file_opened.c_str()).dir().path().toStdString(); - Info::Splitter::filename=QFileInfo(_file_opened.c_str()).baseName().toStdString(); + if(Info::Splitter::path.empty())Info::Splitter::path=QFileInfo(_file_opened.c_str()).dir().path().toStdString(); + if(Info::Splitter::filename.empty())Info::Splitter::filename=QFileInfo(_file_opened.c_str()).baseName().toStdString(); + + if(Info::Splitter::xml_filename.empty() && !_xml_config_file.empty())Info::Splitter::xml_filename=_xml_config_file; if(Info::Splitter::split==true){ std::stringstream str; str<<Info::Splitter::path<<"/"<<Info::Splitter::filename; @@ -310,13 +321,56 @@ bool Core::draw_trace(const string & filename, const int format) { #endif } - Info::Splitter::_x_min = _time_start; + if((Info::Splitter::_x_max==0.0)&&(Info::Splitter::_x_min==0.0)){ + + #ifdef USE_MPI + + if (_world.rank() == 0) { + + double min = _time_start; + double max = 0; + if(_time_end == 0.) { + max = _trace->get_max_date().get_value(); + } + else { + max =_time_end; + } + + double interval = (max-min)/ _world.size(); + for(int i=1;i<_world.size(); i++){ + //send the new working interval for each node + // double out_msg[2]={min+i*interval,min+(i+1)*interval}; + _world.send(i, 0,min+i*interval ); + _world.send(i, 1,min+(i+1)*interval ); + + } + //0 displays the first interval + _time_start=min; + _time_end=min+interval; - if(_time_end == 0.) { - Info::Splitter::_x_max = _trace->get_max_date().get_value(); - } - else { - Info::Splitter::_x_max =_time_end; + } else { + double msg[2]; + _world.recv(0, 0, msg[0]); + _world.recv(0, 1, msg[1]); + _time_start=msg[0]; + _time_end=msg[1]; + } + + + #endif + + + + Info::Splitter::_x_min = _time_start; + + if(_time_end == 0.) { + Info::Splitter::_x_max = _trace->get_max_date().get_value(); + } + else { + Info::Splitter::_x_max =_time_end; + } + + } #endif @@ -353,16 +407,7 @@ bool Core::draw_trace(const string & filename, const int format) { // if(finish_trace_after_parse) { // unsigned long long before = getCurrentTime(); - #if defined(USE_ITC) && defined(BOOST_SERIALIZE) - if(Info::Splitter::load_splitted==true){ - if(Info::Splitter::_x_max == 0)Info::Splitter::preview = true; //we are in the preview mode - if(Info::Splitter::preview==true)_trace->loadPreview(); - else { - Interval* i= new Interval(Info::Splitter::_x_min,Info::Splitter::_x_max); - _trace->updateTrace(i); - } - }else{ - #endif + @@ -387,12 +432,12 @@ bool Core::draw_trace(const string & filename, const int format) { *Message::get_instance() << QObject::tr("Splitting was asked but neither USE_ITC nor BOOST_SERIALIZE flags were set ").toStdString() << Message::ende; #endif } - #if defined(USE_ITC) && defined(BOOST_SERIALIZE) + //#if defined(USE_ITC) && defined(BOOST_SERIALIZE) finished.wait(&mutex); - } - #endif + // } + // #endif parsing_finished=true; } cout << QObject::tr("Loading of the trace : ").toStdString() << loaded << "%" ; diff --git a/src/core/Core.hpp b/src/core/Core.hpp index 7cd23011c9b55ca2df728476a63d25fbfe5aec55..50f139f2a21ef653a26bf20e8c0c95e34bfa7a53 100644 --- a/src/core/Core.hpp +++ b/src/core/Core.hpp @@ -67,6 +67,10 @@ class QCoreApplication; class QString; #include <interface/Interface_graphic.hpp> #include <QObject> +#ifdef USE_MPI +#include <boost/mpi/environment.hpp> +#include <boost/mpi/communicator.hpp> +#endif //#include "render/Render.hpp" //#include "interface/Interface.hpp" @@ -286,6 +290,11 @@ protected: #endif //Render<Render_opengl>* _render_opengl; + + #ifdef USE_MPI + + boost::mpi::communicator _world; + #endif /*! * \brief Contains the SVG render instance. */ diff --git a/src/interface/Interface_graphic.cpp b/src/interface/Interface_graphic.cpp index b4c1845dd8524616087a63537f4cc9344214e6cb..19c77aae0d7b7b1833ff07f2a8c53c84cdbee01a 100644 --- a/src/interface/Interface_graphic.cpp +++ b/src/interface/Interface_graphic.cpp @@ -616,9 +616,15 @@ void Interface_graphic::on_export_file_triggered(){ void Interface_graphic::on_reload_triggered() { if(_is_rendering_trace) { + Element_pos zoom[2]={Info::Splitter::_x_min,Info::Splitter::_x_max}; _core->launch_action(Core::_STATE_RELEASE_RENDER_AREA); _core->draw_trace(_trace_path, Core::_DRAW_OPENGL); + + + if(Info::Splitter::_x_max!=0.0)_core->launch_action(Core:: _STATE_ZOOM_IN_AN_INTERVAL, &zoom); + _core->launch_action(Core:: _STATE_RENDER_UPDATE); + //update the interval selection display if(_ui_interval_selection!=NULL)_ui_interval_selection->update_values(); } diff --git a/src/parser/OTFTraceBuilderThread.cpp b/src/parser/OTFTraceBuilderThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd4e6959b84dc7e5a0aba22d69a2effb78fb4de4 --- /dev/null +++ b/src/parser/OTFTraceBuilderThread.cpp @@ -0,0 +1,631 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ + +#include <sstream> +#include <string> +#include <map> +#include <queue> +#include <list> +/* -- */ +#include <otf.h> +/* -- */ +#include "common/Errors.hpp" +/* -- */ +#include "trace/values/Values.hpp" +#include "trace/EntityValue.hpp" +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/Trace.hpp" +#include <QWaitCondition> +#include <QSemaphore> +#include <QObject> +#include <QMutex> +/* -- */ +#include "parser/ParserDefinitionOTF.hpp" +#include "parser/mt_ParserEventOTF.hpp" +#include "parser/OTFTraceBuilderThread.hpp" +/* -- */ +using namespace std; + + +map <const String, Container *, String::less_than> OTFTraceBuilderThread::_containers; +std::map<uint32_t, Marker > OTFTraceBuilderThread::_marker; + + +OTFTraceBuilderThread::OTFTraceBuilderThread(QWaitCondition* cond, QSemaphore * freeSlots, QMutex* mutex):_cond(cond), _freeSlots(freeSlots), _mutex(mutex){ +} + + +OTFTraceBuilderThread::~OTFTraceBuilderThread() { + _containers.clear(); +} + + void OTFTraceBuilderThread::build_trace(int n_structs, OTF_Trace_builder_struct* tb_struct){ + for(int i=0; i<n_structs; i++){ + tb_struct[i].func(&tb_struct[i]); + } + _freeSlots->release(); + delete[] tb_struct; + + + + } + + +void OTFTraceBuilderThread::build_finished(){ + //locks the mutex and automatically unlocks it when going out of scope + QMutexLocker locker(_mutex); + _is_finished=true; + _cond->wakeAll(); +} + +int OTFTraceBuilderThread::handler_begin_process(OTF_Trace_builder_struct* tb_struct) { + Trace *t = (Trace *)tb_struct->trace; + + Process current_process = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + Process process_parent = ParserDefinitionOTF::get_process_by_id(current_process._parent); + ProcessGroup process_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + + map<string, Value *> extra_fields; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + Name n = Name(current_process._name, ""); + + ContainerType *process_container_type = t->search_container_type(String(process_group._name)); + Container *parent_container = t->search_container(String(process_parent._name)); + + if(t->search_container(String(current_process._name))) { + return OTF_RETURN_OK; // Already created so we quit the function + } + + if(process_container_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + process_group._name, Error::_ERROR); + } + if(parent_container == 0 && process_parent._name != "0") { + // Create the parent process + tb_struct->process=current_process._parent; + handler_begin_process(tb_struct); + parent_container = t->search_container(String(process_parent._name)); + } + + t->create_container(d, n, process_container_type, parent_container, extra_fields); + + // We store the container in the map + _containers[n.to_string()] = t->search_container(n.to_string()); + + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_end_process (OTF_Trace_builder_struct* tb_struct) { + Trace *t = (Trace *)tb_struct->trace; + + Process process = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + ProcessGroup process_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + + map<string, Value *> extra_fields; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Container *temp_container = NULL; + ContainerType *temp_container_type = t->search_container_type(String(process_group._name)); + + const String process_name = String(process._name); + if(_containers.find(process_name) != _containers.end()) { + temp_container = _containers[process_name]; + } + else { + temp_container = t->search_container(process_name); + _containers[process_name] = temp_container; + } + + if(temp_container_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + process_group._name, Error::_ERROR); + } + else if(temp_container == 0 && process._name != "0") { + Error::set(Error::_UNKNOWN_CONTAINER + process._name, Error::_ERROR); + } + + t->destroy_container(d, temp_container, temp_container_type, extra_fields); + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_enter (OTF_Trace_builder_struct* tb_struct) { + Trace *t = (Trace *)tb_struct->trace; + + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Function &temp_function = ParserDefinitionOTF::get_function_by_id(tb_struct->process); + const FunctionGroup temp_function_group = ParserDefinitionOTF::get_function_group_by_id(temp_function._func_group); + Process temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process2); + const ProcessGroup process_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process2); + + const String function_name = String(temp_function._name); + const String function_group_name = String(temp_function_group._name); + const String proc_name = String(temp_proc._name); + + Container *temp_container = NULL; + ContainerType *temp_container_type = t->search_container_type(String(process_group._name)); + + StateType *temp_state_type = t->search_state_type(function_group_name); + EntityValue *temp_value = NULL; + map<string, Value *> extra_fields; + + if(_containers.find(proc_name) != _containers.end()) { + temp_container = _containers[proc_name]; + } + else { + temp_container = t->search_container(proc_name); + _containers[proc_name] = temp_container; + } + + if(temp_state_type == 0) { + Name name_temp(temp_function_group._name, ""); + t->define_state_type(name_temp, temp_container_type, extra_fields); + temp_state_type = t->search_state_type(function_group_name); + } + + if(!temp_function._is_defined) { + temp_function._is_defined = true; + + Name name_temp(temp_function._name, ""); + map<string, Value *> opt; + + /* Optional fields */ + FileLine source_file_locator; + FileSource source_file; + + if(temp_function._file_source != 0) { + source_file_locator = ParserDefinitionOTF::get_fileline_by_id(temp_function._file_source); + source_file = ParserDefinitionOTF::get_filesource_by_id(source_file_locator._file_id); + } + + if(source_file._name != "") { + opt["File name"] = new String(source_file._name); + opt["Line"] = new Integer(source_file_locator._line_number); + } + + opt["Color"] = ParserDefinitionOTF::get_color(tb_struct->process); + + t->define_entity_value(name_temp, t->search_entity_type(function_group_name), opt); + } + + temp_value = t->search_entity_value(function_name, temp_state_type); + + + if(temp_container == NULL && temp_proc._name != "0") { + // Creation of the container if not already done with beginProcess + + tb_struct->process=tb_struct->process2; + handler_begin_process(tb_struct); + temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process2); + temp_container = t->search_container(proc_name); + temp_container_type = t->search_container_type(proc_name); + } + + // Check if nothing is empty + if(temp_state_type == 0 && temp_function_group._name != "0") { + Error::set(Error::_UNKNOWN_STATE_TYPE + temp_function_group._name, Error::_ERROR); + } + if(temp_container == 0 && temp_proc._name != "0") { + Error::set(Error::_UNKNOWN_CONTAINER + temp_function_group._name, Error::_ERROR); + } + if(temp_value == 0 && temp_proc._name != "0") { + Error::set(Error::_UNKNOWN_ENTITY_VALUE + temp_proc._name, Error::_ERROR); + } + + t->set_state(d, temp_state_type, temp_container, temp_value, extra_fields); + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_leave (OTF_Trace_builder_struct*) { + //Trace *t = (Trace *)trace; + + //Date d = (double)time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + //Function temp_function = ParserDefinitionOTF::get_function_by_id(func_id); + //Process temp_proc = ParserDefinitionOTF::get_process_by_id(proc_id); + + //StateType *temp_type = t->search_state_type(String(temp_function._name)); + //Container *temp_container = t->search_container(String(temp_proc._name)); + //EventType *temp_event_type = t->search_event_type(String(temp_function._name)); + //EntityValue *temp_value = t->search_entity_value(String(temp_function._name), temp_event_type); + //map<string, Value *> extra_fields; + + //t->set_state(d, temp_type, temp_container, temp_value, extra_fields); + //t->pop_state(d, temp_type, temp_container, extra_fields); + + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_counter(OTF_Trace_builder_struct* tb_struct) { + Trace *t = (Trace *)tb_struct->trace; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Counter temp_counter = ParserDefinitionOTF::get_counter_by_id(tb_struct->process2); + Process temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + CounterGroup temp_counter_group = ParserDefinitionOTF::get_counter_group_by_id(temp_counter._counter_group); + Container *temp_container = NULL; + map<string, Value *> extra_fields; + + String counter_group_name = String(temp_counter_group._name); + + VariableType *temp_variable_type = t->search_variable_type(counter_group_name); + ProcessGroup process_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + ContainerType *temp_container_type = t->search_container_type(String(process_group._name)); + + const String temp_proc_name = String(temp_proc._name); + + if(_containers.find(temp_proc_name) != _containers.end()) { + temp_container = _containers[temp_proc_name]; + } + else { + temp_container = t->search_container(temp_proc_name); + _containers[temp_proc_name] = temp_container; + } + + if(temp_variable_type == 0) { + Name name_temp(temp_counter_group._name, ""); + t->define_variable_type(name_temp, temp_container_type, extra_fields); + temp_variable_type = t->search_variable_type(counter_group_name); + } + + if(temp_container == NULL && temp_proc._name != "0") { + // Creation of the container if not already done with beginProcess + + handler_begin_process(tb_struct); + temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + temp_container = t->search_container(temp_proc_name); + } + + // Check if nothing is empty + if(temp_variable_type == 0 && temp_counter_group._name != "0") { + Error::set(Error::_UNKNOWN_VARIABLE_TYPE + temp_counter_group._name, Error::_ERROR); + } + if(temp_container == 0 && temp_proc._name != "0") { + Error::set(Error::_UNKNOWN_CONTAINER + temp_counter_group._name, Error::_ERROR); + } + + t->set_variable(d, temp_variable_type, temp_container, tb_struct->value, extra_fields); + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_defmarker(OTF_Trace_builder_struct* tb_struct) { + Marker temp = {tb_struct->text, tb_struct->process, tb_struct->type}; + OTFTraceBuilderThread::_marker[tb_struct->process2] = temp; + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_marker(OTF_Trace_builder_struct* tb_struct) { + Trace *t = (Trace *)tb_struct->trace; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Marker temp_marker = _marker[tb_struct->process2]; + Process temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + Container *temp_container = NULL; + map<string, Value *> extra_fields; + + String str_eventType(temp_marker._name); + String str_event(tb_struct->text); + Name n(tb_struct->text, ""); + EventType *event_type = t->search_event_type(str_eventType); + + ProcessGroup process_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + ContainerType *temp_container_type = t->search_container_type(String(process_group._name)); + EntityValue *value = NULL; + + const String temp_proc_name = String(temp_proc._name); + + if(_containers.find(temp_proc_name) != _containers.end()) { + temp_container = _containers[temp_proc_name]; + } + else { + temp_container = t->search_container(temp_proc_name); + _containers[temp_proc_name] = temp_container; + } + + if(event_type == 0) { + Name name_temp(temp_marker._name, ""); + t->define_event_type(name_temp, temp_container_type, extra_fields); + event_type = t->search_event_type(str_eventType); + } + + value = t->search_entity_value(str_event, event_type); + + if(temp_container == NULL && temp_proc._name != "0") { + // Creation of the container if not already done with beginProcess + handler_begin_process(tb_struct); + temp_proc = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + temp_container = t->search_container(temp_proc_name); + } + + // Check if nothing is empty + if(event_type == 0) { + Error::set(Error::_UNKNOWN_EVENT_TYPE + n.to_string(), Error::_ERROR); + } + if(temp_container == 0 && temp_proc._name != "0") { + //Error::set(Error::_UNKNOWN_CONTAINER + temp_counter_group._name, Error::_ERROR); + } + + t->new_event(d, event_type, temp_container, value, extra_fields); + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_send_message (OTF_Trace_builder_struct* tb_struct ) { + // We define the LinkType if not exist and we store the time and other fields + Trace *t = (Trace *)tb_struct->trace; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Process temp_sender = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + Process temp_receiver = ParserDefinitionOTF::get_process_by_id(tb_struct->process2); + // The sender process may have no ancestor, so let's say that his ancestor is himself + Process temp_ancestor = temp_sender; + ProcessGroup sender_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + ProcessGroup receiver_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process2); + ProcessGroup ancestor_group = ParserDefinitionOTF::get_processgroup_by_process(temp_sender._parent); + + String sender_string = String(temp_sender._name); + String ancestor_string = String(temp_ancestor._name); + String receiver_string = String(temp_receiver._name); + + String sender_group_string = String(sender_group._name); + String ancestor_group_string = String(ancestor_group._name); + String receiver_group_string = String(receiver_group._name); + + /* Value */ + string name = temp_sender._name + " to " + temp_receiver._name; + String name_string = String(name); + + ostringstream link_type_oss; + link_type_oss << tb_struct->type; + String link_type_string = String(link_type_oss.str()); + + Name name_temp = Name(name, ""); + LinkType *link_type = t->search_link_type(link_type_string); + + Container *source_container = NULL; + Container *ancestor_container = NULL; + + ContainerType *source_type = t->search_container_type(sender_group_string); + ContainerType *destination_type = t->search_container_type(receiver_group_string); + ContainerType *ancestor_type = t->search_container_type(ancestor_group_string); + + EntityValue *value; + + map<string, Value *> opt; + + if(_containers.find(sender_string) != _containers.end()) { + source_container = _containers[sender_string]; + } + else { + source_container = t->search_container(sender_string); + _containers[sender_string] = source_container; + } + + if(_containers.find(ancestor_string) != _containers.end() && !_containers.empty()) { + // found + ancestor_container = _containers[ancestor_string]; + } + else { + // receiver not found + ancestor_container = t->search_container(ancestor_string); + if(ancestor_container) { + _containers[ancestor_string] = ancestor_container; + } + } + + if(ancestor_type == 0) { + // No ancestor + ancestor_type = source_type; + } + + if(ancestor_container == 0) { + // No ancestor + ancestor_container = source_container; + } + + if(link_type == 0) { + Name link_name = Name(link_type_oss.str(), ""); + t->define_link_type(link_name, ancestor_type, destination_type, destination_type, opt); + link_type = t->search_link_type(link_type_string); + } + + value = t->search_entity_value(name_string, link_type); + + // Check if nothing is empty + if(source_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + temp_sender._name, Error::_ERROR); + } + if(destination_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + temp_receiver._name, Error::_ERROR); + } + if(ancestor_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + temp_ancestor._name, Error::_ERROR); + } + if(link_type == 0) { + Error::set(Error::_UNKNOWN_LINK_TYPE + link_type_oss.str(), Error::_ERROR); + } + + /* Creation of the optional fields */ + if(tb_struct->group != 0) { + ProcessGroup proc_group = ParserDefinitionOTF::get_processgroup_by_id(tb_struct->group); + String *proc_group_string = new String(proc_group._name); + opt["ProcessGroup"] = proc_group_string; + } + + if(tb_struct->length != 0) { + Integer *length_int = new Integer(tb_struct->length); + opt["Length"] = length_int; + } + + if(tb_struct->source != 0) { + FileLine source_file_locator; + FileSource source_file; + source_file_locator = ParserDefinitionOTF::get_fileline_by_id(tb_struct->source); + source_file = ParserDefinitionOTF::get_filesource_by_id(source_file_locator._file_id); + if(source_file._name != "") { + opt["File name"] = new String(source_file._name); + opt["Line"] = new Integer(source_file_locator._line_number); + } + } + + t->start_link(d, link_type, ancestor_container, source_container, value, name_string, opt); + + return OTF_RETURN_OK; +} + +int OTFTraceBuilderThread::handler_receive_message (OTF_Trace_builder_struct* tb_struct) { + + Trace *t = (Trace *)tb_struct->trace; + Date d = (double)tb_struct->time/(double)ParserDefinitionOTF::get_ticks_per_second(); + + Process temp_sender = ParserDefinitionOTF::get_process_by_id(tb_struct->process2); + Process temp_receiver = ParserDefinitionOTF::get_process_by_id(tb_struct->process); + // The sender process may have no ancestor, so let's say that his ancestor is himself + Process temp_ancestor = temp_sender; + String sender_string = String(temp_sender._name); + String ancestor_string = String(temp_ancestor._name); + String receiver_string = String(temp_receiver._name); + + ProcessGroup sender_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process2); + ProcessGroup receiver_group = ParserDefinitionOTF::get_processgroup_by_process(tb_struct->process); + ProcessGroup ancestor_group = ParserDefinitionOTF::get_processgroup_by_process(temp_sender._parent); + + String sender_group_string = String(sender_group._name); + String ancestor_group_string = String(ancestor_group._name); + String receiver_group_string = String(receiver_group._name); + + /* Value */ + string name = temp_sender._name + " to " + temp_receiver._name; + + String name_string = String(name); + + ostringstream link_type_oss; + link_type_oss << tb_struct->type; + String link_type_string = String(link_type_oss.str()); + + Name name_temp = Name(name, ""); + LinkType *link_type = t->search_link_type(link_type_string); + + Container *destination_cont = NULL; + Container *ancestor_cont = NULL; + Container *sender_cont = NULL; + + ContainerType *destination_type = t->search_container_type(receiver_group_string); + ContainerType *ancestor_type = t->search_container_type(ancestor_group_string); + ContainerType *sender_type = t->search_container_type(sender_group_string); + + EntityValue *value; + + map<string, Value *> opt; + + if(_containers.find(receiver_string) != _containers.end()) { + destination_cont = _containers[receiver_string]; + } + else { + destination_cont = t->search_container(receiver_string); + _containers[receiver_string] = destination_cont; + } + + if(_containers.find(ancestor_string) != _containers.end() && !_containers.empty()) { + ancestor_cont = _containers[ancestor_string]; + } + else { + ancestor_cont = t->search_container(ancestor_string); + if(ancestor_cont) + _containers[ancestor_string] = ancestor_cont; + } + + if(ancestor_type == 0) { + // No ancestor + ancestor_type = sender_type; + } + + if(ancestor_cont == 0) { + // No ancestor + ancestor_cont = sender_cont; + } + + if(link_type == 0) { + Name link_name = Name(link_type_oss.str(), ""); + t->define_link_type(link_name, ancestor_type, destination_type, destination_type, opt); + link_type = t->search_link_type(link_type_string); + } + + value = t->search_entity_value(name_string, link_type); + + // Check if nothing is empty + if(destination_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + temp_receiver._name, Error::_ERROR); + } + if(ancestor_type == 0) { + Error::set(Error::_UNKNOWN_CONTAINER_TYPE + temp_ancestor._name, Error::_ERROR); + } + if(link_type == 0) { + Error::set(Error::_UNKNOWN_LINK_TYPE + link_type_oss.str(), Error::_ERROR); + } + + /* Creation of the optional fields */ + if(tb_struct->group != 0) { + ProcessGroup proc_group = ParserDefinitionOTF::get_processgroup_by_id(tb_struct->group); + String *proc_group_string = new String(proc_group._name); + opt["ProcessGroup"] = proc_group_string; + } + + if(tb_struct->length != 0) { + Integer *length_int = new Integer(tb_struct->length); + opt["Length"] = length_int; + } + + if(tb_struct->source != 0) { + FileLine source_file_locator; + FileSource source_file; + source_file_locator = ParserDefinitionOTF::get_fileline_by_id(tb_struct->source); + source_file = ParserDefinitionOTF::get_filesource_by_id(source_file_locator._file_id); + if(source_file._name != "") { + opt["File name"] = new String(source_file._name); + opt["Line"] = new Integer(source_file_locator._line_number); + } + } + + t->end_link(d, link_type, ancestor_cont, destination_cont, value, name_string, opt); + return OTF_RETURN_OK; +} + diff --git a/src/parser/OTFTraceBuilderThread.hpp b/src/parser/OTFTraceBuilderThread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..457321b6be80c221bf20d7cbb6b6254f600ee075 --- /dev/null +++ b/src/parser/OTFTraceBuilderThread.hpp @@ -0,0 +1,187 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ +/*! + *\file ParserEventOTF.hpp + *\brief This file contains the event parser used by the ParserOTF. + */ + +#ifndef OTFTraceBuilderThread_HPP +#define OTFTraceBuilderThread_HPP +#include <sstream> +#include <string> +#include <map> +#include <queue> +#include <list> +/* -- */ +#include <otf.h> +/* -- */ +#include "common/Errors.hpp" +/* -- */ +#include "trace/values/Values.hpp" +#include "trace/EntityValue.hpp" +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/Trace.hpp" +/* -- */ +#include "parser/ParserDefinitionOTF.hpp" + +#include <QWaitCondition> +#include <QSemaphore> +#include <QObject> +#include <QMutex> +#include <QThread> + +/*! + * \struct Marker + * \brief Contains the definition of a marker + */ +struct Marker { + /*! + * \brief Name of the marker + */ + std::string _name; + /*! + * \brief stream where is defined this marker + */ + uint32_t _stream; + /*! + * \brief type of the marker + */ + uint32_t _type; +}; + + +typedef struct OTF_Trace_builder_struct{ + int _id; + int (*func)(OTF_Trace_builder_struct*); + void *trace; + uint64_t time; + uint32_t process; + uint32_t process2; + uint64_t value; + const char *text; + uint32_t group; + uint32_t type; + uint32_t length; + uint32_t source; + OTF_Trace_builder_struct(){ } + +}OTF_Trace_builder_struct; + + +//class to handle the real work in a second thread +class OTFTraceBuilderThread: public QObject{ +Q_OBJECT +private: + + QWaitCondition* _cond; + bool _is_finished; + QSemaphore * _freeSlots; + QMutex* _mutex; + + static std::map <const String, Container *, String::less_than> _containers; + + static std::map<uint32_t, Marker > _marker; + + public: + /* static int handler_begin_process(void *trace, uint64_t time, uint32_t process); + + static int handler_end_process (void *trace, uint64_t time, uint32_t process); + + static int handler_enter (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t process2); + + static int handler_leave (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t process2); + + static int handler_counter(void *trace, uint64_t time, uint32_t process, uint32_t process2, uint64_t value); + + static int handler_defmarker(void *trace, uint32_t process, uint32_t token, const char *name, uint32_t type); + + static int handler_marker(void *trace, uint64_t time, uint32_t process, uint32_t token, const char *text); + + static int handler_send_message (void *trace, uint64_t time, uint32_t process, uint32_t receiver, uint32_t group, uint32_t type, uint32_t length, uint32_t source); + + static int handler_receive_message (void *trace, uint64_t time, uint32_t process, uint32_t sendProc, uint32_t group, uint32_t type, uint32_t length, uint32_t source); + */ + static int handler_begin_process(OTF_Trace_builder_struct* tb_struct); + + static int handler_end_process (OTF_Trace_builder_struct* tb_struct); + + static int handler_enter (OTF_Trace_builder_struct* tb_struct); + + static int handler_leave (OTF_Trace_builder_struct* tb_struct); + + static int handler_counter(OTF_Trace_builder_struct* tb_struct); + + static int handler_defmarker(OTF_Trace_builder_struct* tb_struct); + + static int handler_marker(OTF_Trace_builder_struct* tb_struct); + + static int handler_send_message (OTF_Trace_builder_struct* tb_struct); + + static int handler_receive_message (OTF_Trace_builder_struct* tb_struct); + + + +public slots: + + void build_trace(int n, OTF_Trace_builder_struct* tb_struct); + void build_finished(); + + +public: + /*! + * \fn ParserEventOTF() + * \brief constructor + */ + OTFTraceBuilderThread(QWaitCondition* cond, QSemaphore * freeSlots, QMutex* mutex); + + /*! + * \fn ~ParserEventOTF() + * \brief constructor + */ + ~OTFTraceBuilderThread(); + + +}; + +#endif diff --git a/src/parser/ParserFactory.cpp b/src/parser/ParserFactory.cpp index 529f5247bc6e8000cf30e66929ebbfdd5d1f6a87..bd8cad834dff40398d6a73d98291eaceb7bc5cd7 100644 --- a/src/parser/ParserFactory.cpp +++ b/src/parser/ParserFactory.cpp @@ -55,14 +55,21 @@ #include "common/Message.hpp" /* -- */ #include "parser/Parser.hpp" -#include "parser/ParserPaje.hpp" + #ifdef MT_PARSING #include "parser/mt_ParserPaje.hpp" +#else +#include "parser/ParserPaje.hpp" #endif + #include "parser/ParserVite.hpp" #ifdef WITH_OTF -#include <otf.h> -#include "parser/ParserOTF.hpp" + #include <otf.h> + #ifdef MT_PARSING + #include "parser/mt_ParserOTF.hpp" + #else + #include "parser/ParserOTF.hpp" + #endif #endif //WITH_OTF #ifdef WITH_TAU @@ -100,7 +107,11 @@ bool ParserFactory::create(Parser **parser, } else if(ext == ".otf") { #ifdef WITH_OTF + #ifdef MT_PARSING + *parser = new mt_ParserOTF(filename); + #else *parser = new ParserOTF(filename); + #endif #else *Message::get_instance() << "OTF parser was not compiled. Use parser Paje by default" << Message::endw; return false; @@ -124,7 +135,11 @@ bool ParserFactory::create(Parser **parser, } if(*parser == NULL) { - *parser = new ParserPaje(filename); + #ifdef MT_PARSING + *parser = new mt_ParserPaje(filename); + #else + *parser = new ParserPaje(filename); + #endif } return true; diff --git a/src/parser/ParserSplitted.cpp b/src/parser/ParserSplitted.cpp index 6253068b6fc5d5aee16065e35b08914fcc366d0f..97a9f9d5dd39ba8bf24c146245a56a35a80522b8 100644 --- a/src/parser/ParserSplitted.cpp +++ b/src/parser/ParserSplitted.cpp @@ -11,6 +11,7 @@ #include "common/common.hpp" #include "common/Errors.hpp" #include "common/Info.hpp" +#include "common/Message.hpp" /* -- */ #if defined(USE_ITC) && defined(BOOST_SERIALIZE) /* -- */ @@ -29,6 +30,7 @@ #include "trace/Serializer_types.hpp" #include "trace/Serializer_structs.hpp" #include "trace/Serializer_container.hpp" +#include "trace/SerializerDispatcher.hpp" #include "trace/values/Values.hpp" #include "trace/tree/Interval.hpp" @@ -40,12 +42,13 @@ #include "parser/ParserSplitted.hpp" +#define message *Message::get_instance() << "(" << __FILE__ << " l." << __LINE__ << "): " using namespace std; -ParserSplitted::ParserSplitted(){} +ParserSplitted::ParserSplitted(): _loaded_itc(0), _nb_itc(0){} -ParserSplitted::ParserSplitted(const string &filename): Parser(filename){ +ParserSplitted::ParserSplitted(const string &filename): Parser(filename), _loaded_itc(0), _nb_itc(0){ } @@ -63,7 +66,9 @@ Info::Splitter::load_splitted=true; //dump containers // char* filename=(char*)malloc(128*sizeof(char)); // sprintf(filename,"%s/%s.vite", Info::Splitter::path, ); - +Serializer<Container>::Instance().clear(); +Serializer<ContainerType>::Instance().clear(); +Serializer<EntityType>::Instance().clear(); std::list<ContainerType*> conts_types; std::list<Container*> conts; @@ -88,9 +93,20 @@ Info::Splitter::load_splitted=true; //ia >> test; // restore the schedule from the archive ia >> conts; - // (trace.get_root_containers())->insert((trace.get_root_containers())->begin(), conts.begin(),conts.end() ); + + trace.set_root_containers(conts); + + + if(Info::Splitter::xml_filename.length()!=0)//we need to load a config from file + { + bool xml_success = trace.load_config_from_xml(QString(Info::Splitter::xml_filename.c_str())); + if(!xml_success){ + message << "Error while parsing" << Info::Splitter::xml_filename << Message::ende; + } + } + std::map<Name, StateType* > _state_types; std::map<Name, EventType* > _event_types; std::map<Name, LinkType* > _link_types; @@ -114,6 +130,76 @@ Info::Splitter::load_splitted=true; ia >>d; trace.set_max_date(d); + //we count the number of containers to load, in order to have a pseudo relevant loaded percentage to display_build + //we should do this with ITC, but that would mean to handle all of the loading here or to have a feedback from trace and containers + + { + stack<Container *> containers; + const Container::Vector* root_containers =trace.get_view_root_containers(); + if(root_containers->empty())root_containers=trace.get_root_containers(); + + Container::VectorIt i = root_containers->begin(); + Container::VectorIt const &end = root_containers->end(); + + for (; i != end; i++) + containers.push(*i); + + while (!containers.empty()) { + Container * c = containers.top(); + _nb_itc+=c->get_intervalsOfContainer()->size(); + containers.pop(); + { + const Container::Vector* children =c->get_view_children(); + if (children->empty())children=c->get_children(); + + Container::VectorIt it = children->begin(); + Container::VectorIt const &it_end = children->end(); + + for (; it != it_end; it++) + containers.push(*it); + } + } + } + + + if(Info::Splitter::load_splitted==true){ + if(Info::Splitter::_x_max == 0)Info::Splitter::preview = true; //we are in the preview mode + if(Info::Splitter::preview==true)trace.loadPreview(); + else { + Interval* interval= new Interval(Info::Splitter::_x_min,Info::Splitter::_x_max); + //trace.loadTraceInside(i); + //in order to manage the percentage of loading, do this inside parser and not in trace + + stack<Container *> containers; + const Container::Vector* root_containers =trace.get_view_root_containers(); + if(root_containers->empty())root_containers=trace.get_root_containers(); + + Container::VectorIt i = root_containers->begin(); + Container::VectorIt const &end = root_containers->end(); + + for (; i != end; i++) + containers.push(*i); + + while (!containers.empty()) { + Container * c = containers.top(); + c->loadItcInside(interval); + _loaded_itc+=c->get_intervalsOfContainer()->size();//just an approximation, based on the total number of itc, and not on the number of loaded itc (maybe heavy to parse) + containers.pop(); + { + const Container::Vector* children =c->get_view_children(); + if (children->empty())children=c->get_children(); + + Container::VectorIt it = children->begin(); + Container::VectorIt const &it_end = children->end(); + + for (; it != it_end; it++) + containers.push(*it); + } + } + + SerializerDispatcher::Instance().kill_all_threads(); + } + } if(finish_trace_after_parse) { //we need to build the display only if we are not splitting the trace @@ -131,6 +217,6 @@ void ParserSplitted::releasefile(){ } float ParserSplitted::get_percent_loaded() const { - return 0.0; + return (double)_loaded_itc/(double)_nb_itc; } #endif diff --git a/src/parser/ParserSplitted.hpp b/src/parser/ParserSplitted.hpp index cc916dd6959628bb070079957560cea135028113..adc6a97649b66017d695f462e6af1571ff99c85f 100644 --- a/src/parser/ParserSplitted.hpp +++ b/src/parser/ParserSplitted.hpp @@ -62,6 +62,9 @@ class PajeFileManager; * */ class ParserSplitted : public Parser{ + + int _loaded_itc; + int _nb_itc; public: diff --git a/src/parser/mt_ParserEventOTF.cpp b/src/parser/mt_ParserEventOTF.cpp new file mode 100644 index 0000000000000000000000000000000000000000..654ae8625e65845436c8430c56be33f7dd41d6c4 --- /dev/null +++ b/src/parser/mt_ParserEventOTF.cpp @@ -0,0 +1,258 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ + +#include <sstream> +#include <string> +#include <map> +#include <queue> +#include <list> +/* -- */ +#include <otf.h> +/* -- */ +#include "common/Errors.hpp" +/* -- */ +#include "trace/values/Values.hpp" +#include "trace/EntityValue.hpp" +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/Trace.hpp" +/* -- */ +#include "parser/ParserDefinitionOTF.hpp" +#include "parser/mt_ParserEventOTF.hpp" +#include "parser/OTFTraceBuilderThread.hpp" +/* -- */ +using namespace std; + +uint64_t mt_ParserEventOTF::_cur_time = 0; +uint64_t mt_ParserEventOTF::_min_time = 0; +uint64_t mt_ParserEventOTF::_max_time = 0; + +uint64_t mt_ParserEventOTF::_n_read=0; +OTF_Trace_builder_struct* mt_ParserEventOTF::_tb_struct=NULL; + + +static mt_ParserEventOTF* my_address=NULL; + +mt_ParserEventOTF::mt_ParserEventOTF() : _handlers(OTF_HandlerArray_open()) { +my_address=this; +} + +mt_ParserEventOTF::~mt_ParserEventOTF() { + OTF_HandlerArray_close(_handlers); + // _containers.clear(); +} + +void mt_ParserEventOTF::set_handlers(Trace *t) { + SET_HANDLER(_handlers, handler_enter, t, OTF_ENTER_RECORD); + SET_HANDLER(_handlers, handler_leave, t, OTF_LEAVE_RECORD); + SET_HANDLER(_handlers, handler_send_message, t, OTF_SEND_RECORD); + SET_HANDLER(_handlers, handler_receive_message, t, OTF_RECEIVE_RECORD); + SET_HANDLER(_handlers, handler_begin_process, t, OTF_BEGINPROCESS_RECORD); + SET_HANDLER(_handlers, handler_end_process, t, OTF_ENDPROCESS_RECORD); + SET_HANDLER(_handlers, handler_counter, t, OTF_COUNTER_RECORD); + SET_HANDLER(_handlers, handler_defmarker, t, OTF_DEFMARKER_RECORD); + SET_HANDLER(_handlers, handler_marker, t, OTF_MARKER_RECORD); +} + +int mt_ParserEventOTF::handler_begin_process(void *trace, uint64_t time, uint32_t process) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=process; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_begin_process; + _n_read++; + + //emit my_address->signal_handler_begin_process(trace,time,process); + + return OTF_RETURN_OK; +} +/*typedef struct OTF_Trace_builder_struct{ + int _id; + void (*func)(OTF_Trace_builder_struct*); + void *trace; + uint64_t time; + uint32_t process; + uint32_t process2; + uint64_t value; + const char *text; + uint32_t group; + uint32_t type; + uint32_t length; + uint32_t source; + OTF_Trace_builder_struct(){ } + +}OTF_Trace_builder_struct;*/ + + +int mt_ParserEventOTF::handler_end_process (void *trace, uint64_t time, uint32_t proc_id) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=proc_id; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_end_process; + _n_read++; + + //emit my_address->signal_handler_end_process (trace,time, proc_id); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_enter (void *trace, uint64_t time, uint32_t func_id, uint32_t proc_id, uint32_t /*source*/) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=func_id; + _tb_struct[_n_read].process2=proc_id; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_enter; + _n_read++; + // emit my_address->signal_handler_enter(trace, time, func_id,proc_id,0); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_leave (void */*trace*/, uint64_t /*time*/, uint32_t /*func_id*/, uint32_t /*proc_id*/, uint32_t /*source*/) { + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_leave; + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_counter(void *trace, uint64_t time, uint32_t proc_id, uint32_t counter_id, uint64_t value) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=proc_id; + _tb_struct[_n_read].process2=counter_id; + _tb_struct[_n_read].value=value; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_counter; + _n_read++; + // emit my_address->signal_handler_counter(trace, time, proc_id,counter_id,value); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_defmarker(void *, uint32_t stream, uint32_t id, const char *name, uint32_t type) { + _tb_struct[_n_read].process=stream; + _tb_struct[_n_read].process2=id; + _tb_struct[_n_read].text=name; + _tb_struct[_n_read].type=type; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_defmarker; + _n_read++; + //emit my_address->signal_handler_defmarker(NULL, stream, id,name,type); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_marker(void *trace, uint64_t time, uint32_t proc_id, uint32_t id, const char *text) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=proc_id; + _tb_struct[_n_read].process2=id; + _tb_struct[_n_read].text=text; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_marker; + _n_read++; + // emit my_address->signal_handler_marker(trace, time, proc_id,id,text); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_send_message (void *trace, uint64_t time, uint32_t sender, uint32_t receiver, uint32_t group, uint32_t type, uint32_t length, uint32_t source) { + // We define the LinkType if not exist and we store the time and other fields + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=sender; + _tb_struct[_n_read].process2=receiver; + _tb_struct[_n_read].group=group; + _tb_struct[_n_read].type=type; + _tb_struct[_n_read].length=length; + _tb_struct[_n_read].source=source; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_send_message; + _n_read++; +//emit my_address->signal_handler_send_message(trace, time, sender, receiver, group, type,length, source); + return OTF_RETURN_OK; +} + +int mt_ParserEventOTF::handler_receive_message (void *trace, uint64_t time, uint32_t receiver, uint32_t sender, uint32_t group, uint32_t type, uint32_t length, uint32_t source) { + _tb_struct[_n_read].trace=trace; + _tb_struct[_n_read].time=time; + _tb_struct[_n_read].process=receiver; + _tb_struct[_n_read].process2=sender; + _tb_struct[_n_read].group=group; + _tb_struct[_n_read].type=type; + _tb_struct[_n_read].length=length; + _tb_struct[_n_read].source=source; + _tb_struct[_n_read].func=OTFTraceBuilderThread::handler_receive_message; + _n_read++; +//emit my_address->signal_handler_receive_message(trace, time, receiver, sender, group, type,length, source); + return OTF_RETURN_OK; +} + + + + + + + + + + + + +int mt_ParserEventOTF::read_events(OTF_Reader *reader, OTF_Trace_builder_struct* tb_struct, int* n_read) { + _tb_struct=tb_struct; + _n_read=0; + int return_value = OTF_Reader_readEvents(reader, _handlers); + OTF_Reader_eventTimeProgress(reader, &mt_ParserEventOTF::_min_time, &mt_ParserEventOTF::_cur_time, &mt_ParserEventOTF::_max_time); + *n_read=_n_read; + return return_value; +} + +int mt_ParserEventOTF::read_markers(OTF_Reader *reader, OTF_Trace_builder_struct* tb_struct, int* n_read) { + _tb_struct=tb_struct; + _n_read=0; + int return_value = OTF_Reader_readMarkers(reader, _handlers); + *n_read=_n_read; + return return_value; +} + +void mt_ParserEventOTF::set_number_event_read_by_each_pass(OTF_Reader *reader, int number) { + OTF_Reader_setRecordLimit(reader, number); +} + +float mt_ParserEventOTF::get_percent_loaded() { + if(mt_ParserEventOTF::_max_time != mt_ParserEventOTF::_min_time) { + return (float)(mt_ParserEventOTF::_cur_time - mt_ParserEventOTF::_min_time)/(float)(mt_ParserEventOTF::_max_time-mt_ParserEventOTF::_min_time); + } + else { + return 0.0f; + } +} diff --git a/src/parser/mt_ParserEventOTF.hpp b/src/parser/mt_ParserEventOTF.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3a5dbe1d3cff16e30b31de760557db7ea0b32625 --- /dev/null +++ b/src/parser/mt_ParserEventOTF.hpp @@ -0,0 +1,175 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ +/*! + *\file mt_ParserEventOTF.hpp + *\brief This file contains the event parser used by the ParserOTF. + */ + +#ifndef mt_ParserEventOTF_HPP +#define mt_ParserEventOTF_HPP +#include <sstream> +#include <string> +#include <map> +#include <queue> +#include <list> +/* -- */ +#include <otf.h> +/* -- */ +#include "common/Errors.hpp" +/* -- */ +#include "trace/values/Values.hpp" +#include "trace/EntityValue.hpp" +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/Trace.hpp" +/* -- */ +#include "parser/ParserDefinitionOTF.hpp" +#include <QWaitCondition> +#include <QSemaphore> +#include <QObject> +#include <QMutex> +#include <QThread> + + + +/** + * \class mt_ParserEventOTF + * \brief Reads Use handlers in order to fill the data structure + * + */ +struct OTF_Trace_builder_struct; + +class mt_ParserEventOTF{ +private: + OTF_HandlerArray* _handlers; + +static uint64_t _n_read; +static OTF_Trace_builder_struct* _tb_struct; + + //static std::map <const String, Container *, String::less_than> _containers; + + static uint64_t _cur_time; + static uint64_t _min_time; + static uint64_t _max_time; + + // static std::map<uint32_t, Marker > _marker; + + static int handler_begin_process(void *trace, uint64_t time, uint32_t process); + + static int handler_end_process (void *trace, uint64_t time, uint32_t process); + + static int handler_enter (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t source); + + static int handler_leave (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t source); + + static int handler_counter(void *trace, uint64_t time, uint32_t process, uint32_t counter, uint64_t value); + + static int handler_defmarker(void *trace, uint32_t stream, uint32_t token, const char *name, uint32_t type); + + static int handler_marker(void *trace, uint64_t time, uint32_t process, uint32_t token, const char *text); + + static int handler_send_message (void *trace, uint64_t time, uint32_t sender, uint32_t receiver, uint32_t group, uint32_t type, uint32_t length, uint32_t source); + + static int handler_receive_message (void *trace, uint64_t time, uint32_t recvProc, uint32_t sendProc, uint32_t group, uint32_t type, uint32_t length, uint32_t source); + + static int handle_message(void *trace, uint64_t time, uint32_t receiver, uint32_t sender, uint32_t /*group*/, uint32_t /*type*/, uint32_t /*length*/, uint32_t source, bool is_sender_to_receiver); + + mt_ParserEventOTF(const mt_ParserEventOTF &); +public: + /*! + * \fn mt_ParserEventOTF() + * \brief constructor + */ + mt_ParserEventOTF(); + + /*! + * \fn ~mt_ParserEventOTF() + * \brief constructor + */ + ~mt_ParserEventOTF(); + + /*! + * \fn set_handlers(Trace *t) + * \brief Create and set the handlers for the event parsing. + * \param t The trace we want to store in. + */ + void set_handlers(Trace *t); + + /*! + * \fn read_events(OTF_Reader *reader) + * \brief Begin the reading of the events + * \param reader The main otf file we want to read in. + */ + int read_events(OTF_Reader *reader, OTF_Trace_builder_struct* tb_struct, int* n_read); + + /*! + * \fn read_markers(OTF_Reader *reader) + * \brief Begin the reading of the markers (corresponds to events in Paje) + * \param reader The main otf file we want to read in. + */ + int read_markers(OTF_Reader *reader, OTF_Trace_builder_struct* tb_struct, int* n_read); + + /*! + * \fn set_number_event_read_by_each_pass(OTF_Reader *reader, int number); + * \brief set the number of event we want to read by pass. + * Allow us to do a prevision for the remaining time. + * \param reader The main otf file we want to read in. + * \param number The number of events read. + */ + void set_number_event_read_by_each_pass(OTF_Reader *reader, int number); + + /*! + * \fn get_percent_loaded() + * \brief get the size already parsed. + * It is an approximation, we consider that parsing the definitions is done in a constant time. + * \return the scale of the size already parsed. (between 0 and 1) + */ + static float get_percent_loaded(); + + + +}; + + + +#endif // mt_ParserEventOTF_HPP diff --git a/src/parser/mt_ParserOTF.cpp b/src/parser/mt_ParserOTF.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f875186d5efffda5d8f6ed5bb4e1e2c434c59c7 --- /dev/null +++ b/src/parser/mt_ParserOTF.cpp @@ -0,0 +1,241 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ + +#include <iostream> +#include <fstream> +#include <string> +#include <map> +/* -- */ +#include <otf.h> +/* -- */ +#include <QMetaType> +#include <QThread> +#include <QObject> +/* -- */ +#include "trace/values/Values.hpp" +#include "trace/EntityTypes.hpp" +#include "trace/Entitys.hpp" +#include "trace/Trace.hpp" +/* -- */ +#include "parser/Parser.hpp" +#include "parser/mt_ParserOTF.hpp" +#include "parser/ParserDefinitionOTF.hpp" +#include "parser/mt_ParserEventOTF.hpp" +#include "parser/OTFTraceBuilderThread.hpp" +/* -- */ + +using namespace std; + +mt_ParserOTF::mt_ParserOTF() {}; +mt_ParserOTF::mt_ParserOTF(const string &filename) : Parser(filename) {} +mt_ParserOTF::~mt_ParserOTF() {}; + +void mt_ParserOTF::parse(Trace &trace, + bool finish_trace_after_parse) { + + ParserDefinitionOTF *parserdefinition = new ParserDefinitionOTF(); + mt_ParserEventOTF *parserevent = new mt_ParserEventOTF(); + QWaitCondition ended; + QMutex mutex; + QSemaphore freeSlots(5); + QSemaphore linesProduced(5); + OTFTraceBuilderThread *parserevent2 = new OTFTraceBuilderThread(&ended, &freeSlots, &mutex); + OTF_FileManager *manager = OTF_FileManager_open(100); + /* OTF_MasterControl* mc; + mc = OTF_MasterControl_new( manager ); + OTF_MasterControl_read( mc, _file_to_parse.c_str()); + + uint32_t streamcount = OTF_MasterControl_getCount( mc ); + + printf("nb of streams %d\n", streamcount);*/ + + OTF_Reader *reader; + int ret = 0; + + if(manager == NULL) { + cerr << QObject::tr("manager failed\n").toStdString() << endl; + delete parserdefinition; + delete parserevent; + return; + } + + /*int signal_handler_begin_process(void *trace, uint64_t time, uint32_t process); + + int signal_handler_end_process (void *trace, uint64_t time, uint32_t process); + + int signal_handler_enter (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t source); + + int signal_handler_leave (void *trace, uint64_t time, uint32_t function, uint32_t process, uint32_t source); + + int signal_handler_counter(void *trace, uint64_t time, uint32_t process, uint32_t counter, uint64_t value); + + int signal_handler_defmarker(void *trace, uint32_t stream, uint32_t token, const char *name, uint32_t type); + + int signal_handler_marker(void *trace, uint64_t time, uint32_t process, uint32_t token, const char *text); + + int signal_handler_send_message (void *trace, uint64_t time, uint32_t sender, uint32_t receiver, uint32_t group, uint32_t type, uint32_t length, uint32_t source); + + int signal_handler_receive_message (void *trace, uint64_t time, uint32_t recvProc, uint32_t sendProc, uint32_t group, uint32_t type, uint32_t length, uint32_t source);*/ + /* qRegisterMetaType<uint64_t>("uint64_t"); + qRegisterMetaType<uint32_t>("uint32_t"); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_begin_process(void *, uint64_t , uint32_t )), + SLOT(handler_begin_process(void *, uint64_t , uint32_t ))); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_end_process (void *, uint64_t , uint32_t )), + SLOT(handler_end_process (void *, uint64_t , uint32_t ))); + + parserevent2->connect(parserevent, + SIGNAL(signal_handler_enter (void *, uint64_t , uint32_t , uint32_t , uint32_t )), + SLOT(handler_enter (void *, uint64_t , uint32_t , uint32_t , uint32_t ))); + + + parserevent2->connect(parserevent, + SIGNAL(signal_handler_counter(void *, uint64_t , uint32_t , uint32_t , uint64_t )), + SLOT(handler_counter(void *, uint64_t , uint32_t , uint32_t , uint64_t ))); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_defmarker(void *, uint32_t , uint32_t , const char *, uint32_t )), + SLOT(handler_defmarker(void *, uint32_t , uint32_t , const char *, uint32_t ))); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_marker(void *, uint64_t , uint32_t , uint32_t , const char *)), + SLOT(handler_marker(void *, uint64_t , uint32_t , uint32_t , const char *))); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_send_message (void *, uint64_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t )), + SLOT(handler_send_message (void *, uint64_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t ))); + parserevent2->connect(parserevent, + SIGNAL(signal_handler_receive_message (void *, uint64_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t )), + SLOT(handler_receive_message (void *, uint64_t , uint32_t , uint32_t, uint32_t , uint32_t , uint32_t , uint32_t ))); + +*/ + int n_events=10000; + OTF_Trace_builder_struct* tb_structs= new OTF_Trace_builder_struct[n_events]; + parserevent2->connect((const QObject*)this, + SIGNAL(build_trace(int, OTF_Trace_builder_struct*)), + SLOT(build_trace(int, OTF_Trace_builder_struct*))); + parserevent2->connect((const QObject*)this, + SIGNAL(build_finished()), + SLOT(build_finished())); + QThread traceThread; + parserevent2->moveToThread(&traceThread); + traceThread.start(); + + reader = OTF_Reader_open(_file_to_parse.c_str(), manager); + if(reader == NULL) { + cerr << QObject::tr("open failed\n").toStdString() << endl; + delete parserdefinition; + delete parserevent; + OTF_FileManager_close(manager); + finish(); + + if(finish_trace_after_parse) { // true by default + trace.finish(); + } + return; + } + + parserdefinition->set_handlers(&trace); + parserdefinition->read_definitions(reader); + parserdefinition->create_container_types(&trace); + + //parserdefinition->print_definitions(); + + parserevent->set_number_event_read_by_each_pass(reader, n_events); + parserevent->set_handlers(&trace); + int n_read=0; + + while ( ((ret = parserevent->read_events(reader, tb_structs, &n_read)) != 0) + && (!_is_canceled)) { + if(ret == -1) { + cerr << QObject::tr("Error while reading events. Aborting").toStdString() << endl; + break; + } + freeSlots.acquire(); //do not produce too fast (5 blocks max at a time) + emit(build_trace(n_read, tb_structs)); + linesProduced.release(); + tb_structs= new OTF_Trace_builder_struct[n_events]; + } + + freeSlots.acquire(); //do not produce too fast (5 blocks max at a time) + emit(build_trace(n_read, tb_structs)); + linesProduced.release(); + //tb_structs= NULL; + + //same thing for markers + tb_structs= new OTF_Trace_builder_struct[n_events]; + while ( ((ret=parserevent->read_markers(reader, tb_structs,&n_read)) != 0) + && (!_is_canceled)) { + + freeSlots.acquire(); //do not produce too fast (5 blocks max at a time) + emit(build_trace(n_read, tb_structs)); + linesProduced.release(); + tb_structs= new OTF_Trace_builder_struct[n_events]; + } + + freeSlots.acquire(); //do not produce too fast (5 blocks max at a time) + emit(build_trace(n_read, tb_structs)); + linesProduced.release(); + + finish(); + + if(finish_trace_after_parse) { // true by default + trace.finish(); + } + + QMutexLocker locker(&mutex); + emit build_finished(); + ended.wait(&mutex); + locker.unlock(); + traceThread.quit(); + traceThread.wait(); + delete parserevent; + delete parserevent2; + delete parserdefinition; + + OTF_Reader_close(reader); + OTF_FileManager_close(manager); +} + + +float mt_ParserOTF::get_percent_loaded() const { + return mt_ParserEventOTF::get_percent_loaded(); +} diff --git a/src/parser/mt_ParserOTF.hpp b/src/parser/mt_ParserOTF.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0e16c33367fb7a517505c6db5d67dfa0d90b965e --- /dev/null +++ b/src/parser/mt_ParserOTF.hpp @@ -0,0 +1,102 @@ +/* +** This file is part of the ViTE project. +** +** This software is governed by the CeCILL-A license under French law +** and abiding by the rules of distribution of free software. You can +** use, modify and/or redistribute the software under the terms of the +** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following +** URL: "http://www.cecill.info". +** +** As a counterpart to the access to the source code and rights to copy, +** modify and redistribute granted by the license, users are provided +** only with a limited warranty and the software's author, the holder of +** the economic rights, and the successive licensors have only limited +** liability. +** +** In this respect, the user's attention is drawn to the risks associated +** with loading, using, modifying and/or developing or reproducing the +** software by the user in light of its specific status of free software, +** that may mean that it is complicated to manipulate, and that also +** therefore means that it is reserved for developers and experienced +** professionals having in-depth computer knowledge. Users are therefore +** encouraged to load and test the software's suitability as regards +** their requirements in conditions enabling the security of their +** systems and/or data to be ensured and, more generally, to use and +** operate it in the same conditions as regards security. +** +** The fact that you are presently reading this means that you have had +** knowledge of the CeCILL-A license and that you accept its terms. +** +** +** ViTE developers are (for version 0.* to 1.0): +** +** - COULOMB Kevin +** - FAVERGE Mathieu +** - JAZEIX Johnny +** - LAGRASSE Olivier +** - MARCOUEILLE Jule +** - NOISETTE Pascal +** - REDONDY Arthur +** - VUCHENER Clément +** +*/ +/*! + * \file mt_ParserOTF.hpp + * \brief the implementation of Parser for OTF traces. + */ + +#ifndef mt_ParserOTF_HPP +#define mt_ParserOTF_HPP +#include <QtCore> +#include <parser/Parser.hpp> +#include <parser/Parser.hpp> +#include <otf.h> +class mt_ParserEventOTF; +class ParserDefinitionOTF; +struct OTF_Trace_builder_struct; + +/*! + * + * \class mt_ParserOTF + * \brief parse the input data format of OTF. + * + */ +class mt_ParserOTF : public Parser { + + Q_OBJECT +private: + OTF_Reader* _reader; + + mt_ParserOTF(const mt_ParserOTF &); +public: + + /*! + * \fn mt_ParserOTF() + */ + mt_ParserOTF(); + mt_ParserOTF(const std::string &filename); + ~mt_ParserOTF(); + + /*! + * \fn parse(Trace &trace, bool finish_trace_after_parse = true) + * \param trace : the structure of data to fill + * \param finish_trace_after_parse boolean set if we do not have to finish the trace after parsing + */ + void parse(Trace &trace, + bool finish_trace_after_parse = true); + + /*! + * \fn get_percent_loaded() const + * \brief return the size of the file already read. + * \return the scale of the size already loaded of the file by the parser. (between 0 and 1) + */ + float get_percent_loaded() const; + + signals: + void build_finished(); + void build_trace(int, OTF_Trace_builder_struct*); + +}; + +#endif // mt_ParserOTF_HPP + diff --git a/src/trace/Container.cpp b/src/trace/Container.cpp index 87522b744a6c4a349c056bc88b505cad72903d7e..27123a8a9b63795a0ed867f250d663b75534f704 100644 --- a/src/trace/Container.cpp +++ b/src/trace/Container.cpp @@ -89,7 +89,7 @@ Container::Container(): Container::Container(Name name, Date creation_time, ContainerType *type, Container *parent, map<string, Value *> &opt): _name(name), _creation_time(creation_time), _destruction_time(0.0), _type(type), _parent(parent), - _n_states(0), _state_tree(0), _n_events(0), _event_tree(0), _n_variables(0), _extra_fields(opt) { + _n_states(0), _state_tree(NULL), _n_events(0), _event_tree(NULL), _n_variables(0), _extra_fields(opt) { if (parent) { _depth = parent->_depth+1; @@ -624,7 +624,7 @@ void Container::loadItcInside(Interval* splitInterval){ // printf("min: %lf, max: %lf\n", Info::Render::_x_min_visible, Info::Render::_x_max_visible); //test if we are past the last element of the container -> if yes, load its last itc - char* name=(char*)malloc(512*sizeof(char)); + int i=0; @@ -638,10 +638,11 @@ void Container::loadItcInside(Interval* splitInterval){ ((*it)->_beginning>=splitInterval->_left && (*it)->_beginning<=splitInterval->_right)) { if((*it)->_loaded==false){ + char* name=(char*)malloc(512*sizeof(char)); sprintf(name, "%s/%d_%d",Info::Splitter::path.c_str(),_uid ,i); - // printf("%s : need to load itc beginning at %lf and finishing at %lf, file %s \n", _name.to_string().c_str(), (*it)->_beginning.get_value(), (*it)->_end.get_value(), name); - - loading=(*it)->retrieve(name); + //printf("%s : need to load itc beginning at %lf and finishing at %lf, file %s \n", _name.to_string().c_str(), (*it)->_beginning.get_value(), (*it)->_end.get_value(), name); + SerializerDispatcher::Instance().load(*it, name); + //loading=(*it)->retrieve(name); if(loading==true)(*it)->_loaded=true; // else printf("bug de loading\n"); @@ -662,7 +663,7 @@ void Container::loadItcInside(Interval* splitInterval){ } - free(name); + // free(name); } @@ -704,11 +705,11 @@ void Container::loadPreview(){ } - if(_n_events==0)_event_tree=NULL; + /* if(_n_events==0)_event_tree=NULL; else _event_tree = new BinaryTree<Event>(_events, _n_events); if(_n_states==0)_state_tree=NULL; - else _state_tree = new BinaryTree<StateChange>(_states,_n_states); + else _state_tree = new BinaryTree<StateChange>(_states,_n_states);*/ } @@ -775,24 +776,33 @@ _state_tree=NULL; if((*it)->_n_variables!=0) for(int i=0; i< (*it)->_n_variables; i++){ - VariableType* type=((*it)->_variables[i]).get_type(); if (_variables.find(type)==_variables.end()){ _variables.insert(std::pair<VariableType*, Variable*>(type,(&((*it)->_variables[i])))); + _n_variables++; }else{ if(((*it)->_variables[i]).get_values()!=NULL){ + + /* int nb_items=0; + for(nb_items=0; nb_items<((*it)->_variables[i]).get_values()->size(); nb_items++){ + pair<Date, Double> t= ((*it)->_variables[i]).get_values()->[nb_items]; + printf("add first %lf value %lf\n", t.first.get_value(), t.second.get_value()); + _variables[type]->add_value(t.first, t.second); + + }*/ + std::list<std::pair<Date, Double> >::const_iterator it_end2=((*it)->_variables[i]).get_values()->end(); std::list<std::pair<Date, Double> >::const_iterator it_val = ((*it)->_variables[i]).get_values()->begin(); for(; - it_val!=((*it)->_variables[i]).get_values()->end(); + it_val!=it_end2 ; it_val++){ pair<Date, Double> t= *it_val; + _variables[type]->add_value(t.first, t.second); } } } - } } @@ -807,7 +817,6 @@ _state_tree=NULL; }*/ - } if(_n_events==0)_event_tree=NULL; else _event_tree = new BinaryTree<Event>(_events, _n_events); diff --git a/src/trace/EntityType.cpp b/src/trace/EntityType.cpp index e706abd8d2eae73a4ef811e1bf4bb11a7db04b7a..267e0de1e86f927c3d16e8770b7297128e04936e 100644 --- a/src/trace/EntityType.cpp +++ b/src/trace/EntityType.cpp @@ -60,7 +60,7 @@ EntityType::EntityType(Name name, ContainerType *container_type, map<std::string } -EntityType::EntityType() +EntityType::EntityType():_extra_fields(NULL) {} diff --git a/src/trace/Serializer.cpp b/src/trace/Serializer.cpp index c41d2d11546cafc88873055ff77ffa7ab1b4dc9f..36421256f64f68fa135699c8fafec3dff0c3edd7 100644 --- a/src/trace/Serializer.cpp +++ b/src/trace/Serializer.cpp @@ -5,6 +5,12 @@ #include <boost/bimap.hpp> #include <QMutex> using namespace std; + + template <typename T> + void Serializer<T>::clear(){ + _map.clear(); + + } template <typename T> bool Serializer<T>::setUid(int n, const T* c){ diff --git a/src/trace/Serializer.hpp b/src/trace/Serializer.hpp index 17ec628efabbfea6db2da2c776719a5537df88e9..31eef918b95972b88b15bf640c768f73349213be 100644 --- a/src/trace/Serializer.hpp +++ b/src/trace/Serializer.hpp @@ -60,6 +60,12 @@ private: */ int getUid(const T* c); + /*! + * \fn clear + * \brief Clear all data in the serializer + */ + void clear(); + }; //check if this is necessary for the compiler diff --git a/src/trace/SerializerDispatcher.cpp b/src/trace/SerializerDispatcher.cpp index 2960d7e5386bdd72e01b086cb3bb531eb8699668..3710a91b2f7d781ed04c192ec3694e9caa6e27b3 100644 --- a/src/trace/SerializerDispatcher.cpp +++ b/src/trace/SerializerDispatcher.cpp @@ -16,7 +16,26 @@ _nb_threads=boost::thread::hardware_concurrency(); // SerializerWriter* evt=NULL; - _mutex= new QMutex(); + + launch_threads(); + + + //evt=&(evt_array[_uid%nb_cpus]);//&(SerializerWriter::Instance()); + /*_cond = evt->get_cond(); + _freeSlots= evt->get_sem_free(); + _itcProduced= evt->get_sem_produced(); + _thread= evt->get_thread();*/ +//printf("récupérons %s %d %p %p\n",_name.to_string().c_str(),_uid%boost::thread::hardware_concurrency(), _thread, _cond); + + + + } + SerializerDispatcher::~SerializerDispatcher(){} + + +void SerializerDispatcher::launch_threads(){ + + _mutex= new QMutex(); _killed=false; _previous_call=0; _evt_array=new SerializerWriter[_nb_threads]; @@ -35,32 +54,22 @@ SLOT(finish_build()));*/ _evt_array[i].connect((const QObject*)this, - SIGNAL(dump_on_disk(IntervalOfContainer*, const char*)), - SLOT(dump_on_disk(IntervalOfContainer*, const char*))); + SIGNAL(dump_on_disk(IntervalOfContainer*, char*)), + SLOT(dump_on_disk(IntervalOfContainer*, char*))); + _evt_array[i].connect((const QObject*)this, + SIGNAL(load_data(IntervalOfContainer*, char*)), + SLOT(load(IntervalOfContainer*, char*))); } new(&_evt_array[i]) SerializerWriter (_cond, _freeSlots, _itcProduced, _thread, _mutex); - // _evt_array[i].set_values(_cond, _freeSlots, _itcProduced, _thread); - - + // _evt_array[i].set_values(_cond, _freeSlots, _itcProduced, _thread); _evt_array[i].moveToThread(_thread); _thread->start(); } - - //evt=&(evt_array[_uid%nb_cpus]);//&(SerializerWriter::Instance()); - /*_cond = evt->get_cond(); - _freeSlots= evt->get_sem_free(); - _itcProduced= evt->get_sem_produced(); - _thread= evt->get_thread();*/ -//printf("récupérons %s %d %p %p\n",_name.to_string().c_str(),_uid%boost::thread::hardware_concurrency(), _thread, _cond); - - - - } - SerializerDispatcher::~SerializerDispatcher(){} - + + } void SerializerDispatcher::kill_all_threads(){ if(!_killed){ for(unsigned int i=0;i<_nb_threads; i++){ @@ -85,7 +94,7 @@ void SerializerDispatcher::kill_all_threads(){ } } -void SerializerDispatcher::dump(IntervalOfContainer* itc, const char* name){ +void SerializerDispatcher::dump(IntervalOfContainer* itc, char* name){ bool changed=false; SerializerWriter* evt=&(_evt_array[_previous_call]); QSemaphore* _itcProduced= evt->get_sem_produced(); @@ -101,10 +110,10 @@ void SerializerDispatcher::dump(IntervalOfContainer* itc, const char* name){ if(changed!=false){ //the acquired semaphore isn't the same as the initial one, disconnect the signl and connect to the right thread - this->disconnect(SIGNAL(dump_on_disk(IntervalOfContainer*, const char*))); + this->disconnect(SIGNAL(dump_on_disk(IntervalOfContainer*, char*))); _evt_array[_previous_call].connect((const QObject*)this, - SIGNAL(dump_on_disk(IntervalOfContainer*, const char*)), - SLOT(dump_on_disk(IntervalOfContainer*, const char*))); + SIGNAL(dump_on_disk(IntervalOfContainer*, char*)), + SLOT(dump_on_disk(IntervalOfContainer*, char*))); // printf("changing at the end %s %d\n",_name.to_string().c_str(),slot_number); //_thread=evt_array[slot_number].get_thread(); // _cond=evt_array[slot_number].get_cond(); @@ -115,4 +124,42 @@ void SerializerDispatcher::dump(IntervalOfContainer* itc, const char* name){ emit dump_on_disk(itc, name); _evt_array[_previous_call].get_sem_free()->release(); } + +void SerializerDispatcher::load(IntervalOfContainer* itc, char* name){ + + bool changed=false; + SerializerWriter* evt=&(_evt_array[_previous_call]); + QSemaphore* _itcProduced= evt->get_sem_produced(); + while (_itcProduced->tryAcquire(1,10)==false){ + //the connected working thread is not free + changed=true; + _previous_call++; + _previous_call=_previous_call%_nb_threads; + + _itcProduced=_evt_array[_previous_call].get_sem_produced(); + + } + + if(changed!=false){ + //the acquired semaphore isn't the same as the initial one, disconnect the signl and connect to the right thread + + this->disconnect(SIGNAL(load_data(IntervalOfContainer*, char*))); + _evt_array[_previous_call].connect((const QObject*)this, + SIGNAL(load_data(IntervalOfContainer*, char*)), + SLOT(load(IntervalOfContainer*, char*))); + //_thread=evt_array[slot_number].get_thread(); + // _cond=evt_array[slot_number].get_cond(); + + + } + itc->_loaded=true; + emit load_data(itc, name); + _evt_array[_previous_call].get_sem_free()->release(); +} + + + void SerializerDispatcher::init(){ + _killed=false; + launch_threads(); + } diff --git a/src/trace/SerializerDispatcher.hpp b/src/trace/SerializerDispatcher.hpp index d1974af628b61f14c3dd4577b599db728fbb8e0a..f249393232aa4118df7f7e9bd9f48a6b7322d757 100644 --- a/src/trace/SerializerDispatcher.hpp +++ b/src/trace/SerializerDispatcher.hpp @@ -72,13 +72,14 @@ Q_OBJECT public: SerializerDispatcher(); ~SerializerDispatcher(); - + void init(); + void launch_threads(); void kill_all_threads(); //dump an itc, after choosing a free thread to use - void dump(IntervalOfContainer* itc, const char* ); - + void dump(IntervalOfContainer* itc, char* ); + void load(IntervalOfContainer*, char*); signals: - - void dump_on_disk(IntervalOfContainer*,const char*); + void load_data(IntervalOfContainer*, char*); + void dump_on_disk(IntervalOfContainer*, char*); void build_finish(); }; diff --git a/src/trace/SerializerWriter.cpp b/src/trace/SerializerWriter.cpp index 761681a5f715934a21b54b1fbeb54de358d9e60e..768fdcb85ff5ed23d79d0d9a31ebe6eb152c5d62 100644 --- a/src/trace/SerializerWriter.cpp +++ b/src/trace/SerializerWriter.cpp @@ -63,14 +63,20 @@ return _cond; return _thread; } -void SerializerWriter::dump_on_disk(IntervalOfContainer* itc,const char* filename){ +void SerializerWriter::dump_on_disk(IntervalOfContainer* itc,char* filename){ _freeSlots->acquire(); itc->dump_on_disk( filename); itc->unload(); _itcProduced->release(); - //free(filename); + free(filename); } +void SerializerWriter::load(IntervalOfContainer* itc,char* filename){ + _freeSlots->acquire(); + itc->retrieve( filename); + _itcProduced->release(); + free(filename); + } bool SerializerWriter::is_finished(){return _is_finished;} diff --git a/src/trace/SerializerWriter.hpp b/src/trace/SerializerWriter.hpp index d4c7eaf5902f1aa3464f4a865863ea397aa733a9..ea4496b58d8c3079b81f8d8fbb4a4265b94b5e9f 100644 --- a/src/trace/SerializerWriter.hpp +++ b/src/trace/SerializerWriter.hpp @@ -86,7 +86,9 @@ public: public slots: - void dump_on_disk(IntervalOfContainer* itc,const char* filename); + void dump_on_disk(IntervalOfContainer* itc, char* filename); + + void load(IntervalOfContainer* itc,char* filename); bool is_finished(); diff --git a/src/trace/Serializer_types.hpp b/src/trace/Serializer_types.hpp index d8f276e25f97e597075a0fc0583375bd39fc1d7f..ba79fd9b0e3124cd92ac0122a662158e137e8385 100644 --- a/src/trace/Serializer_types.hpp +++ b/src/trace/Serializer_types.hpp @@ -88,6 +88,7 @@ using namespace boost::serialization; template<class Archive> void load(Archive &ar, ContainerType& l, const unsigned int ) { + printf("Type 1\n"); Name _name; ContainerType *_parent; diff --git a/src/trace/Trace.cpp b/src/trace/Trace.cpp index eae762cd218293f760df89f1da53aaf0db0fe050..7c2d9ec1d362b2238b7a9e743cb53a8cfb545da7 100644 --- a/src/trace/Trace.cpp +++ b/src/trace/Trace.cpp @@ -427,7 +427,8 @@ if(Info::Splitter::load_splitted==true){ } void Trace::loadTraceInside(Interval* interval){ - stack<Container *> containers; + SerializerDispatcher::Instance().init(); + stack<Container *> containers; const Container::Vector* root_containers =&_view_root_containers; if(root_containers->empty())root_containers=&_root_containers; @@ -452,7 +453,8 @@ void Trace::loadTraceInside(Interval* interval){ containers.push(*it); } } - + //wait for loading to finish + SerializerDispatcher::Instance().kill_all_threads(); } void Trace::loadPreview (){