/*
 ** 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 ParserEventOTF2.cpp
 *
 *  @author François Trahay
 *  @author Lagrasse Olivier
 *  @author Johnny Jazeix
 *  @author Mathieu Faverge
 *
 */
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <list>
#include <iostream>
/* -- */
#include <otf2/otf2.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/OTF2Parser/ParserDefinitionOTF2.hpp"
#include "parser/OTF2Parser/ParserEventOTF2.hpp"
/* -- */
using namespace std;

map <const String, Container *, String::less_than> ParserEventOTF2::_containers;

ParserEventOTF2::ParserEventOTF2(OTF2_Reader *reader) {
    _global_evt_reader = OTF2_Reader_GetGlobalEvtReader(reader);
    _global_evt_callbacks = OTF2_GlobalEvtReaderCallbacks_New();
}

ParserEventOTF2::~ParserEventOTF2() {
    OTF2_GlobalEvtReaderCallbacks_Delete(_global_evt_callbacks);
    _containers.clear();
}

void ParserEventOTF2::set_handlers(OTF2_Reader *reader, Trace *trace) {
    OTF2_GlobalEvtReaderCallbacks_SetUnknownCallback(_global_evt_callbacks, &callback_Unknown);
    OTF2_GlobalEvtReaderCallbacks_SetBufferFlushCallback(_global_evt_callbacks, &callback_BufferFlush);
    OTF2_GlobalEvtReaderCallbacks_SetMeasurementOnOffCallback(_global_evt_callbacks, &callback_MeasurementOnOff);
    OTF2_GlobalEvtReaderCallbacks_SetEnterCallback(_global_evt_callbacks, &callback_Enter);
    OTF2_GlobalEvtReaderCallbacks_SetLeaveCallback(_global_evt_callbacks, &callback_Leave);
    OTF2_GlobalEvtReaderCallbacks_SetMpiSendCallback(_global_evt_callbacks, &callback_MpiSend);
    OTF2_GlobalEvtReaderCallbacks_SetMpiIsendCallback(_global_evt_callbacks, &callback_MpiIsend);
    OTF2_GlobalEvtReaderCallbacks_SetMpiIsendCompleteCallback(_global_evt_callbacks, &callback_MpiIsendComplete);
    OTF2_GlobalEvtReaderCallbacks_SetMpiIrecvRequestCallback(_global_evt_callbacks, &callback_MpiIrecvRequest);
    OTF2_GlobalEvtReaderCallbacks_SetMpiRecvCallback(_global_evt_callbacks, &callback_MpiRecv);
    OTF2_GlobalEvtReaderCallbacks_SetMpiIrecvCallback(_global_evt_callbacks, &callback_MpiIrecv);
    OTF2_GlobalEvtReaderCallbacks_SetMpiRequestTestCallback(_global_evt_callbacks, &callback_MpiRequestTest);
    OTF2_GlobalEvtReaderCallbacks_SetMpiRequestCancelledCallback(_global_evt_callbacks, &callback_MpiRequestCancelled);
    OTF2_GlobalEvtReaderCallbacks_SetMpiCollectiveBeginCallback(_global_evt_callbacks, &callback_MpiCollectiveBegin);
    OTF2_GlobalEvtReaderCallbacks_SetMpiCollectiveEndCallback(_global_evt_callbacks, &callback_MpiCollectiveEnd);
    OTF2_GlobalEvtReaderCallbacks_SetOmpForkCallback(_global_evt_callbacks, &callback_OmpFork);
    OTF2_GlobalEvtReaderCallbacks_SetOmpJoinCallback(_global_evt_callbacks, &callback_OmpJoin);
    OTF2_GlobalEvtReaderCallbacks_SetOmpAcquireLockCallback(_global_evt_callbacks, &callback_OmpAcquireLock);
    OTF2_GlobalEvtReaderCallbacks_SetOmpReleaseLockCallback(_global_evt_callbacks, &callback_OmpReleaseLock);
    OTF2_GlobalEvtReaderCallbacks_SetOmpTaskCreateCallback(_global_evt_callbacks, &callback_OmpTaskCreate);
    OTF2_GlobalEvtReaderCallbacks_SetOmpTaskSwitchCallback(_global_evt_callbacks, &callback_OmpTaskSwitch);
    OTF2_GlobalEvtReaderCallbacks_SetOmpTaskCompleteCallback(_global_evt_callbacks, &callback_OmpTaskComplete);
    OTF2_GlobalEvtReaderCallbacks_SetMetricCallback(_global_evt_callbacks, &callback_Metric);
    OTF2_GlobalEvtReaderCallbacks_SetParameterStringCallback(_global_evt_callbacks, &callback_ParameterString);
    OTF2_GlobalEvtReaderCallbacks_SetParameterIntCallback(_global_evt_callbacks, &callback_ParameterInt);
    OTF2_GlobalEvtReaderCallbacks_SetParameterUnsignedIntCallback(_global_evt_callbacks, &callback_ParameterUnsignedInt);
    OTF2_GlobalEvtReaderCallbacks_SetRmaWinCreateCallback(_global_evt_callbacks, &callback_RmaWinCreate);
    OTF2_GlobalEvtReaderCallbacks_SetRmaWinDestroyCallback(_global_evt_callbacks, &callback_RmaWinDestroy);
    OTF2_GlobalEvtReaderCallbacks_SetRmaCollectiveBeginCallback(_global_evt_callbacks, &callback_RmaCollectiveBegin);
    OTF2_GlobalEvtReaderCallbacks_SetRmaCollectiveEndCallback(_global_evt_callbacks, &callback_RmaCollectiveEnd);
    OTF2_GlobalEvtReaderCallbacks_SetRmaGroupSyncCallback(_global_evt_callbacks, &callback_RmaGroupSync);
    OTF2_GlobalEvtReaderCallbacks_SetRmaRequestLockCallback(_global_evt_callbacks, &callback_RmaRequestLock);
    OTF2_GlobalEvtReaderCallbacks_SetRmaAcquireLockCallback(_global_evt_callbacks, &callback_RmaAcquireLock);
    OTF2_GlobalEvtReaderCallbacks_SetRmaTryLockCallback(_global_evt_callbacks, &callback_RmaTryLock);
    OTF2_GlobalEvtReaderCallbacks_SetRmaReleaseLockCallback(_global_evt_callbacks, &callback_RmaReleaseLock);
    OTF2_GlobalEvtReaderCallbacks_SetRmaSyncCallback(_global_evt_callbacks, &callback_RmaSync);
    OTF2_GlobalEvtReaderCallbacks_SetRmaWaitChangeCallback(_global_evt_callbacks, &callback_RmaWaitChange);
    OTF2_GlobalEvtReaderCallbacks_SetRmaPutCallback(_global_evt_callbacks, &callback_RmaPut);
    OTF2_GlobalEvtReaderCallbacks_SetRmaGetCallback(_global_evt_callbacks, &callback_RmaGet);
    OTF2_GlobalEvtReaderCallbacks_SetRmaAtomicCallback(_global_evt_callbacks, &callback_RmaAtomic);
    OTF2_GlobalEvtReaderCallbacks_SetRmaOpCompleteBlockingCallback(_global_evt_callbacks, &callback_RmaOpCompleteBlocking);
    OTF2_GlobalEvtReaderCallbacks_SetRmaOpCompleteNonBlockingCallback(_global_evt_callbacks, &callback_RmaOpCompleteNonBlocking);
    OTF2_GlobalEvtReaderCallbacks_SetRmaOpTestCallback(_global_evt_callbacks, &callback_RmaOpTest);
    OTF2_GlobalEvtReaderCallbacks_SetRmaOpCompleteRemoteCallback(_global_evt_callbacks, &callback_RmaOpCompleteRemote);
    OTF2_GlobalEvtReaderCallbacks_SetThreadForkCallback(_global_evt_callbacks, &callback_ThreadFork);
    OTF2_GlobalEvtReaderCallbacks_SetThreadJoinCallback(_global_evt_callbacks, &callback_ThreadJoin);
    OTF2_GlobalEvtReaderCallbacks_SetThreadTeamBeginCallback(_global_evt_callbacks, &callback_ThreadTeamBegin);
    OTF2_GlobalEvtReaderCallbacks_SetThreadTeamEndCallback(_global_evt_callbacks, &callback_ThreadTeamEnd);
    OTF2_GlobalEvtReaderCallbacks_SetThreadAcquireLockCallback(_global_evt_callbacks, &callback_ThreadAcquireLock);
    OTF2_GlobalEvtReaderCallbacks_SetThreadReleaseLockCallback(_global_evt_callbacks, &callback_ThreadReleaseLock);
    OTF2_GlobalEvtReaderCallbacks_SetThreadTaskCreateCallback(_global_evt_callbacks, &callback_ThreadTaskCreate);
    OTF2_GlobalEvtReaderCallbacks_SetThreadTaskSwitchCallback(_global_evt_callbacks, &callback_ThreadTaskSwitch);
    OTF2_GlobalEvtReaderCallbacks_SetThreadTaskCompleteCallback(_global_evt_callbacks, &callback_ThreadTaskComplete);
    OTF2_GlobalEvtReaderCallbacks_SetThreadCreateCallback(_global_evt_callbacks, &callback_ThreadCreate);
    OTF2_GlobalEvtReaderCallbacks_SetThreadBeginCallback(_global_evt_callbacks, &callback_ThreadBegin);
    OTF2_GlobalEvtReaderCallbacks_SetThreadWaitCallback(_global_evt_callbacks, &callback_ThreadWait);
    OTF2_GlobalEvtReaderCallbacks_SetThreadEndCallback(_global_evt_callbacks, &callback_ThreadEnd);
    OTF2_GlobalEvtReaderCallbacks_SetCallingContextEnterCallback(_global_evt_callbacks, &callback_CallingContextEnter);
    OTF2_GlobalEvtReaderCallbacks_SetCallingContextLeaveCallback(_global_evt_callbacks, &callback_CallingContextLeave);
    OTF2_GlobalEvtReaderCallbacks_SetCallingContextSampleCallback(_global_evt_callbacks, &callback_CallingContextSample);
    OTF2_GlobalEvtReaderCallbacks_SetIoCreateHandleCallback(_global_evt_callbacks, &callback_IoCreateHandle);
    OTF2_GlobalEvtReaderCallbacks_SetIoDestroyHandleCallback(_global_evt_callbacks, &callback_IoDestroyHandle);
    OTF2_GlobalEvtReaderCallbacks_SetIoDuplicateHandleCallback(_global_evt_callbacks, &callback_IoDuplicateHandle);
    OTF2_GlobalEvtReaderCallbacks_SetIoSeekCallback(_global_evt_callbacks, &callback_IoSeek);
    OTF2_GlobalEvtReaderCallbacks_SetIoChangeStatusFlagsCallback(_global_evt_callbacks, &callback_IoChangeStatusFlags);
    OTF2_GlobalEvtReaderCallbacks_SetIoDeleteFileCallback(_global_evt_callbacks, &callback_IoDeleteFile);
    OTF2_GlobalEvtReaderCallbacks_SetIoOperationBeginCallback(_global_evt_callbacks, &callback_IoOperationBegin);
    OTF2_GlobalEvtReaderCallbacks_SetIoOperationTestCallback(_global_evt_callbacks, &callback_IoOperationTest);
    OTF2_GlobalEvtReaderCallbacks_SetIoOperationIssuedCallback(_global_evt_callbacks, &callback_IoOperationIssued);
    OTF2_GlobalEvtReaderCallbacks_SetIoOperationCompleteCallback(_global_evt_callbacks, &callback_IoOperationComplete);
    OTF2_GlobalEvtReaderCallbacks_SetIoOperationCancelledCallback(_global_evt_callbacks, &callback_IoOperationCancelled);
    OTF2_GlobalEvtReaderCallbacks_SetIoAcquireLockCallback(_global_evt_callbacks, &callback_IoAcquireLock);
    OTF2_GlobalEvtReaderCallbacks_SetIoReleaseLockCallback(_global_evt_callbacks, &callback_IoReleaseLock);
    OTF2_GlobalEvtReaderCallbacks_SetIoTryLockCallback(_global_evt_callbacks, &callback_IoTryLock);
    OTF2_GlobalEvtReaderCallbacks_SetProgramBeginCallback(_global_evt_callbacks, &callback_ProgramBegin);
    OTF2_GlobalEvtReaderCallbacks_SetProgramEndCallback(_global_evt_callbacks, &callback_ProgramEnd);

    OTF2_Reader_RegisterGlobalEvtCallbacks(reader, _global_evt_reader, _global_evt_callbacks, trace);
}


#if defined(OTF2_DEBUG)
static inline void ENTER_CALLBACK( OTF2_TimeStamp time, OTF2_LocationRef locationID ) {
    Date d = ParserDefinitionOTF2::get_timestamp(time);
    OTF2_Location *temp_location = ParserDefinitionOTF2::get_location_by_id(locationID);
    const String proc_name = String(ParserDefinitionOTF2::get_string_id(temp_location));
    cout<<d.to_string()<<" - "<<proc_name.to_string()<<" - "<<__FUNCTION__<<"\n";
}
#else
static inline void ENTER_CALLBACK( OTF2_TimeStamp, OTF2_LocationRef ) {
}
#endif

#define NOT_IMPLEMENTED_YET(timestamp) do {                             \
        Date d = ParserDefinitionOTF2::get_timestamp(timestamp);        \
        cout<<"Warning OTF2 parser: "<< d.to_string()<<"  "<<__FUNCTION__<<" not implemented\n"; \
        return OTF2_CALLBACK_SUCCESS;                                   \
    } while(0)

OTF2_CallbackCode  ParserEventOTF2::callback_ProgramBegin(OTF2_LocationRef       locationID,
                                                          OTF2_TimeStamp         time,
                                                          void *                 /*userData*/,
                                                          OTF2_AttributeList *   /*attributeList*/,
                                                          OTF2_StringRef         /*programName*/,
                                                          uint32_t               /*numberOfArguments*/,
                                                          const OTF2_StringRef * /*programArguments*/ )
{
    ENTER_CALLBACK(time, locationID);
    // make sure get_timestamp is called anyway since it initialize the first timestamp
    Date d = ParserDefinitionOTF2::get_timestamp(time);
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode  ParserEventOTF2::callback_ProgramEnd(OTF2_LocationRef locationID,
                                                        OTF2_TimeStamp   time,
                                                        void *               /*userData*/,
                                                        OTF2_AttributeList * /*attributeList*/,
                                                        int64_t              /*exitStatus*/ )
{
    ENTER_CALLBACK(time, locationID);
    return OTF2_CALLBACK_SUCCESS;
}

//
// Start definition of handlers for OTF2 event records
//
OTF2_CallbackCode ParserEventOTF2::callback_Enter(OTF2_LocationRef    locationID,
                                                  OTF2_TimeStamp      time,
                                                  void               *userData,
                                                  OTF2_AttributeList */*attributes*/,
                                                  OTF2_RegionRef      regionID)
{
    ENTER_CALLBACK(time, locationID);
    Trace *t = (Trace *)userData;
    Date d = ParserDefinitionOTF2::get_timestamp(time);
    OTF2_Function temp_function = ParserDefinitionOTF2::get_function_by_id(regionID);
    const String function_name = String(ParserDefinitionOTF2::get_string_by_id(temp_function._name_id));
    map<string, Value *> extra_fields;

    // get the container
    OTF2_Location *temp_location = ParserDefinitionOTF2::get_location_by_id(locationID);
    const String proc_name = String(ParserDefinitionOTF2::get_string_id(temp_location));
    Container* temp_container = temp_location->container;

#if defined(OTF2_DEBUG)
    cout<<d.to_string()<<"  Enter_print(location="<<proc_name.to_string()<<", region="<<regionID<<", fname="<<function_name.to_string()<<")\n";
#endif  // defined(OTF2_DEBUG)

    // get the state type
    String state_type_string("Function");
    StateType *temp_state_type = t->search_state_type(state_type_string);
    if(temp_state_type == 0) {
        Name name_temp(state_type_string);
        ContainerType cont_type=*temp_container->get_type();
        t->define_state_type(name_temp, &cont_type, extra_fields);
        temp_state_type = t->search_state_type(state_type_string);
        assert(temp_state_type != 0);
    }

    // get the entity value
    EntityValue *temp_value = NULL;
    temp_value = t->search_entity_value(function_name, temp_state_type);
    if( temp_value == NULL ) {
        map<string, Value *> opt;
        Name entity_name(function_name);
        opt["Color"] = ParserDefinitionOTF2::get_color(regionID);
        t->define_entity_value(entity_name, temp_state_type, opt);
        temp_value = t->search_entity_value(function_name, temp_state_type);
    }
    assert(temp_value);

    t->push_state(d, temp_state_type, temp_container, temp_value, extra_fields);

    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_Leave(OTF2_LocationRef locationID,
                                                  OTF2_TimeStamp time,
                                                  void *userData,
                                                  OTF2_AttributeList */*attributes*/,
                                                  OTF2_RegionRef regionID)
{
    ENTER_CALLBACK(time, locationID);
    Trace *t = (Trace *)userData;
    Date d = ParserDefinitionOTF2::get_timestamp(time);
    map<string, Value *> extra_fields;

    OTF2_Function temp_function = ParserDefinitionOTF2::get_function_by_id(regionID);
    const String function_name = String(ParserDefinitionOTF2::get_string_by_id(temp_function._name_id));

    // get the container
    OTF2_Location *temp_location = ParserDefinitionOTF2::get_location_by_id(locationID);
    const String proc_name = String(ParserDefinitionOTF2::get_string_id(temp_location));
    Container* temp_container = temp_location->container;

#if defined(OTF2_DEBUG)
    cout<<d.to_string()<<"  Leave_print(location="<<proc_name.to_string()<<", region="<<regionID<<", fname="<<function_name.to_string()<<")\n";
#endif  // defined(OTF2_DEBUG)

    // get the state type
    String state_type_string("Function");
    StateType *temp_state_type = t->search_state_type(state_type_string);
    if(temp_state_type == 0) {
        Name name_temp(state_type_string);
        ContainerType cont_type=*temp_container->get_type();
        t->define_state_type(name_temp, &cont_type, extra_fields);
        temp_state_type = t->search_state_type(state_type_string);
        assert(temp_state_type != 0);
    }

    t->pop_state(d, temp_state_type, temp_container, extra_fields);

    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiSend(OTF2_LocationRef sender,
                                                    OTF2_TimeStamp time,
                                                    void *userData,
                                                    OTF2_AttributeList */*attributes*/,
                                                    uint32_t receiver,
                                                    OTF2_CommRef communicator,
                                                    uint32_t msgTag,
                                                    uint64_t length)
{
    ENTER_CALLBACK(time, sender);
    // We define the LinkType if not exist and we store the time and other fields
    Trace *t  = (Trace *)userData;
    Date d = ParserDefinitionOTF2::get_timestamp(time);

    OTF2_Location *temp_sender = ParserDefinitionOTF2::get_location_by_id(sender);
    OTF2_Location *temp_receiver = ParserDefinitionOTF2::get_location_in_communicator(communicator, receiver);

    // The sender process may have no ancestor, so let's say that his ancestor is himself
    OTF2_Location *temp_ancestor = temp_sender;

    String sender_string = String(ParserDefinitionOTF2::get_string_id(temp_sender));
    String ancestor_string = String(ParserDefinitionOTF2::get_string_id(temp_ancestor));
    String receiver_string = String(ParserDefinitionOTF2::get_string_id(temp_receiver));

#if defined(OTF2_DEBUG)
    cout<<d.to_string()<<"   start_link(src="<<sender_string.to_string()<<", dest="<<receiver_string.to_string()<<")\n";
#endif
    String sender_type_string = String(ParserDefinitionOTF2::get_string_by_id(temp_sender->_name_id));
    String ancestor_type_string = String(ParserDefinitionOTF2::get_string_by_id(temp_ancestor->_name_id));
    String receiver_type_string = String(ParserDefinitionOTF2::get_string_by_id(temp_receiver->_name_id));

    /* Value */
    string name = string(ParserDefinitionOTF2::get_string_id(temp_sender)) + " to " + ParserDefinitionOTF2::get_string_id(temp_receiver)+ " tag "+to_string(msgTag);
    String name_string = String(name);

    ostringstream link_type_oss;
    link_type_oss << communicator;
    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_type_string);
    ContainerType *destination_type = t->search_container_type(receiver_type_string);
    ContainerType *ancestor_type = t->search_container_type(ancestor_type_string);

    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(source_container==0) {
        // ignore this event
        // TODO: fix this !
        cout<<"MPI_Send: cannot find source container !"<<sender_string.to_string()<<"\n";
        return OTF2_CALLBACK_SUCCESS;
    }
    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);
        assert(link_type != NULL);
    }

    /* Creation of the optional fields */
    if(length != 0) {
        Integer *length_int = new Integer(length);
        opt["Length"] = length_int;
    }
    opt["Tag"] = new Integer(msgTag);

    t->start_link(d, link_type, ancestor_container, source_container, name_string, opt);

    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiIsend(OTF2_LocationRef locationID,
                                                     OTF2_TimeStamp time,
                                                     void *userData,
                                                     OTF2_AttributeList *attributeList,
                                                     uint32_t receiver,
                                                     OTF2_CommRef communicator,
                                                     uint32_t msgTag,
                                                     uint64_t msgLength,
                                                     uint64_t /*requestID*/)
{
    ENTER_CALLBACK(time, locationID);
    return callback_MpiSend(locationID, time, userData, attributeList, receiver, communicator, msgTag, msgLength);
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiRecv(OTF2_LocationRef receiver,
                                                    OTF2_TimeStamp time,
                                                    void *userData,
                                                    OTF2_AttributeList */*attributes*/,
                                                    uint32_t sender,
                                                    OTF2_CommRef communicator,
                                                    uint32_t msgTag,
                                                    uint64_t length)
{
    ENTER_CALLBACK(time, receiver);
    Trace *t  = (Trace *)userData;
    Date d = ParserDefinitionOTF2::get_timestamp(time);

    OTF2_Location *temp_sender = ParserDefinitionOTF2::get_location_in_communicator(communicator, sender);
    OTF2_Location *temp_receiver = ParserDefinitionOTF2::get_location_by_id(receiver);
    // The sender process may have no ancestor, so let's say that his ancestor is himself
    OTF2_Location *temp_ancestor = temp_sender;

    String sender_string = String(ParserDefinitionOTF2::get_string_id(temp_sender));
    String ancestor_string = String(ParserDefinitionOTF2::get_string_id(temp_ancestor));
    String receiver_string = String(ParserDefinitionOTF2::get_string_id(temp_receiver));

    /* Value */
    string name = string(ParserDefinitionOTF2::get_string_id(temp_sender)) + " to " + ParserDefinitionOTF2::get_string_id(temp_receiver)+ " tag "+to_string(msgTag);

    String name_string = String(name);

    ostringstream link_type_oss;
    link_type_oss << communicator;
    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_string);
    ContainerType *ancestor_type = t->search_container_type(ancestor_string);
    ContainerType *sender_type = t->search_container_type(sender_string);

    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(destination_cont == 0) {
        return OTF2_CALLBACK_SUCCESS;

    }
    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);
        assert(link_type != NULL);
    }

    /* Creation of the optional fields */
    if(length != 0) {
        Integer *length_int = new Integer(length);
        opt["Length"] = length_int;
    }
    opt["Tag"] = new Integer(msgTag);

    t->end_link(d, link_type, ancestor_cont, destination_cont, name_string, opt);

    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiIrecv(OTF2_LocationRef locationID,
                                                     OTF2_TimeStamp time,
                                                     void *userData,
                                                     OTF2_AttributeList *attributeList,
                                                     uint32_t sender,
                                                     OTF2_CommRef communicator,
                                                     uint32_t msgTag,
                                                     uint64_t msgLength,
                                                     uint64_t /*requestID*/) {
    ENTER_CALLBACK(time, locationID);
    // A MpiIrecv record indicates that a MPI message was received (MPI_IRECV).
    return callback_MpiRecv(locationID, time, userData, attributeList, sender, communicator, msgTag, msgLength);
}

OTF2_CallbackCode ParserEventOTF2::callback_Unknown( OTF2_LocationRef    locationID,
                                                     OTF2_TimeStamp      time,
                                                     void*               /*userData*/,
                                                     OTF2_AttributeList* /*attributeList*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_BufferFlush( OTF2_LocationRef    locationID,
                                                         OTF2_TimeStamp      time,
                                                         void*                /*userData*/,
                                                         OTF2_AttributeList*  /*attributeList*/,
                                                         OTF2_TimeStamp       /*stopTime*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_MeasurementOnOff( OTF2_LocationRef     locationID,
                                                              OTF2_TimeStamp       time,
                                                              void*                 /*userData*/,
                                                              OTF2_AttributeList*   /*attributeList*/,
                                                              OTF2_MeasurementMode  /*measurementMode*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiIsendComplete( OTF2_LocationRef    locationID,
                                                              OTF2_TimeStamp      time,
                                                              void*                /*userData*/,
                                                              OTF2_AttributeList*  /*attributeList*/,
                                                              uint64_t             /*requestID*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiIrecvRequest( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             uint64_t             /*requestID*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiRequestTest( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            uint64_t             /*requestID*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiRequestCancelled( OTF2_LocationRef    locationID,
                                                                 OTF2_TimeStamp      time,
                                                                 void*                /*userData*/,
                                                                 OTF2_AttributeList*  /*attributeList*/,
                                                                 uint64_t             /*requestID*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiCollectiveBegin( OTF2_LocationRef    locationID,
                                                                OTF2_TimeStamp      time,
                                                                void*                /*userData*/,
                                                                OTF2_AttributeList*  /*attributeList*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
    //    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_MpiCollectiveEnd( OTF2_LocationRef    locationID,
                                                              OTF2_TimeStamp      time,
                                                              void*                /*userData*/,
                                                              OTF2_AttributeList*  /*attributeList*/,
                                                              OTF2_CollectiveOp    /*collectiveOp*/,
                                                              OTF2_CommRef         /*communicator*/,
                                                              uint32_t             /*root*/,
                                                              uint64_t             /*sizeSent*/,
                                                              uint64_t             /*sizeReceived*/ ) {
    ENTER_CALLBACK(time, locationID);
    //    NOT_IMPLEMENTED_YET(time);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;

}

OTF2_CallbackCode ParserEventOTF2::callback_OmpFork( OTF2_LocationRef    locationID,
                                                     OTF2_TimeStamp      time,
                                                     void*                /*userData*/,
                                                     OTF2_AttributeList*  /*attributeList*/,
                                                     uint32_t             /*numberOfRequestedThreads*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpJoin( OTF2_LocationRef    locationID,
                                                     OTF2_TimeStamp      time,
                                                     void*                /*userData*/,
                                                     OTF2_AttributeList*  /*attributeList*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpAcquireLock( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            uint32_t             /*lockID*/,
                                                            uint32_t             /*acquisitionOrder*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpReleaseLock( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            uint32_t             /*lockID*/,
                                                            uint32_t             /*acquisitionOrder*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpTaskCreate( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           uint64_t             /*taskID*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpTaskSwitch( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           uint64_t             /*taskID*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_OmpTaskComplete( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             uint64_t             /*taskID*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_Metric( OTF2_LocationRef        locationID,
                                                    OTF2_TimeStamp          time,
                                                    void*                   userData,
                                                    OTF2_AttributeList*     /*attributeList*/,
                                                    OTF2_MetricRef          metric,
                                                    uint8_t                 numberOfMetrics,
                                                    const OTF2_Type*        typeIDs,
                                                    const OTF2_MetricValue* metricValues ) {
    ENTER_CALLBACK(time, locationID);
    Trace *t = (Trace *)userData;
    Date d = ParserDefinitionOTF2::get_timestamp(time);

    OTF2_Location *temp_location = ParserDefinitionOTF2::get_location_by_id(locationID);
    const String proc_name = ParserDefinitionOTF2::get_string_id(temp_location);
    Container* temp_container = t->search_container(proc_name);
    if(!temp_container) {
        Error::set(Error::VITE_ERR_UNKNOWN_CONTAINER, Error::VITE_ERRCODE_ERROR);
        return OTF2_CALLBACK_SUCCESS;
    }

    const ContainerType* temp_container_type = temp_container->get_type();
    if(!temp_container_type) {
        Error::set(Error::VITE_ERR_UNKNOWN_CONTAINER_TYPE, Error::VITE_ERRCODE_ERROR);
        return OTF2_CALLBACK_SUCCESS;
    }

    OTF2_MetricClass m = ParserDefinitionOTF2::get_metric_class(metric);

    for(int i=0; i<numberOfMetrics; i++) {
        map<string, Value *> extra_fields;
        OTF2_MetricMember member = ParserDefinitionOTF2::get_metric_member(m, i);
        VariableType *temp_variable_type = t->search_variable_type(String(ParserDefinitionOTF2::get_string_by_id(member._name)));
        OTF2_MetricValue value = metricValues[i];
        double value_double=-1;
        switch(typeIDs[i]) {
        case OTF2_TYPE_UINT8 : value_double = (double)((uint8_t)  value.unsigned_int); break;
        case OTF2_TYPE_UINT16: value_double = (double)((uint16_t) value.unsigned_int); break;
        case OTF2_TYPE_UINT32: value_double = (double)((uint32_t) value.unsigned_int); break;
        case OTF2_TYPE_UINT64: value_double = (double)((uint64_t) value.unsigned_int); break;

        case OTF2_TYPE_INT8  : value_double = (double)((int8_t)  value.signed_int); break;
        case OTF2_TYPE_INT16 : value_double = (double)((int16_t) value.signed_int); break;
        case OTF2_TYPE_INT32 : value_double = (double)((int32_t) value.signed_int); break;
        case OTF2_TYPE_INT64 : value_double = (double)((int64_t) value.signed_int); break;

        case OTF2_TYPE_FLOAT : value_double = (double)((float) value.floating_point); break;
        case OTF2_TYPE_DOUBLE: value_double = (double)(value.floating_point); break;
        }

        t->set_variable(d, temp_variable_type, temp_container, value_double, extra_fields);
    }
    return OTF2_CALLBACK_SUCCESS;

}

OTF2_CallbackCode ParserEventOTF2::callback_ParameterString( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             OTF2_ParameterRef    /*parameter*/,
                                                             OTF2_StringRef       /*string*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_ParameterInt( OTF2_LocationRef    locationID,
                                                          OTF2_TimeStamp      time,
                                                          void*                /*userData*/,
                                                          OTF2_AttributeList*  /*attributeList*/,
                                                          OTF2_ParameterRef    /*parameter*/,
                                                          int64_t              /*value*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_ParameterUnsignedInt( OTF2_LocationRef    locationID,
                                                                  OTF2_TimeStamp      time,
                                                                  void*                /*userData*/,
                                                                  OTF2_AttributeList*  /*attributeList*/,
                                                                  OTF2_ParameterRef    /*parameter*/,
                                                                  uint64_t             /*value*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaWinCreate( OTF2_LocationRef    locationID,
                                                          OTF2_TimeStamp      time,
                                                          void*                /*userData*/,
                                                          OTF2_AttributeList*  /*attributeList*/,
                                                          OTF2_RmaWinRef       /*win*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaWinDestroy( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           OTF2_RmaWinRef       /*win*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaCollectiveBegin( OTF2_LocationRef    locationID,
                                                                OTF2_TimeStamp      time,
                                                                void*                /*userData*/,
                                                                OTF2_AttributeList*  /*attributeList*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaCollectiveEnd( OTF2_LocationRef    locationID,
                                                              OTF2_TimeStamp      time,
                                                              void*                /*userData*/,
                                                              OTF2_AttributeList*  /*attributeList*/,
                                                              OTF2_CollectiveOp    /*collectiveOp*/,
                                                              OTF2_RmaSyncLevel    /*syncLevel*/,
                                                              OTF2_RmaWinRef       /*win*/,
                                                              uint32_t             /*root*/,
                                                              uint64_t             /*bytesSent*/,
                                                              uint64_t             /*bytesReceived*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaGroupSync( OTF2_LocationRef    locationID,
                                                          OTF2_TimeStamp      time,
                                                          void*                /*userData*/,
                                                          OTF2_AttributeList*  /*attributeList*/,
                                                          OTF2_RmaSyncLevel    /*syncLevel*/,
                                                          OTF2_RmaWinRef       /*win*/,
                                                          OTF2_GroupRef        /*group*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaRequestLock( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            OTF2_RmaWinRef       /*win*/,
                                                            uint32_t             /*remote*/,
                                                            uint64_t             /*lockId*/,
                                                            OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaAcquireLock( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            OTF2_RmaWinRef       /*win*/,
                                                            uint32_t             /*remote*/,
                                                            uint64_t             /*lockId*/,
                                                            OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaTryLock( OTF2_LocationRef    locationID,
                                                        OTF2_TimeStamp      time,
                                                        void*                /*userData*/,
                                                        OTF2_AttributeList*  /*attributeList*/,
                                                        OTF2_RmaWinRef       /*win*/,
                                                        uint32_t             /*remote*/,
                                                        uint64_t             /*lockId*/,
                                                        OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaReleaseLock( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            OTF2_RmaWinRef       /*win*/,
                                                            uint32_t             /*remote*/,
                                                            uint64_t             /*lockId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaSync( OTF2_LocationRef    locationID,
                                                     OTF2_TimeStamp      time,
                                                     void*                /*userData*/,
                                                     OTF2_AttributeList*  /*attributeList*/,
                                                     OTF2_RmaWinRef       /*win*/,
                                                     uint32_t             /*remote*/,
                                                     OTF2_RmaSyncType     /*syncType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaWaitChange( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           OTF2_RmaWinRef       /*win*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaPut( OTF2_LocationRef    locationID,
                                                    OTF2_TimeStamp      time,
                                                    void*                /*userData*/,
                                                    OTF2_AttributeList*  /*attributeList*/,
                                                    OTF2_RmaWinRef       /*win*/,
                                                    uint32_t             /*remote*/,
                                                    uint64_t             /*bytes*/,
                                                    uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaGet( OTF2_LocationRef    locationID,
                                                    OTF2_TimeStamp      time,
                                                    void*                /*userData*/,
                                                    OTF2_AttributeList*  /*attributeList*/,
                                                    OTF2_RmaWinRef       /*win*/,
                                                    uint32_t             /*remote*/,
                                                    uint64_t             /*bytes*/,
                                                    uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaAtomic( OTF2_LocationRef    locationID,
                                                       OTF2_TimeStamp      time,
                                                       void*                /*userData*/,
                                                       OTF2_AttributeList*  /*attributeList*/,
                                                       OTF2_RmaWinRef       /*win*/,
                                                       uint32_t             /*remote*/,
                                                       OTF2_RmaAtomicType   /*type*/,
                                                       uint64_t             /*bytesSent*/,
                                                       uint64_t             /*bytesReceived*/,
                                                       uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaOpCompleteBlocking( OTF2_LocationRef    locationID,
                                                                   OTF2_TimeStamp      time,
                                                                   void*                /*userData*/,
                                                                   OTF2_AttributeList*  /*attributeList*/,
                                                                   OTF2_RmaWinRef       /*win*/,
                                                                   uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaOpCompleteNonBlocking( OTF2_LocationRef    locationID,
                                                                      OTF2_TimeStamp      time,
                                                                      void*                /*userData*/,
                                                                      OTF2_AttributeList*  /*attributeList*/,
                                                                      OTF2_RmaWinRef       /*win*/,
                                                                      uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaOpTest( OTF2_LocationRef    locationID,
                                                       OTF2_TimeStamp      time,
                                                       void*                /*userData*/,
                                                       OTF2_AttributeList*  /*attributeList*/,
                                                       OTF2_RmaWinRef       /*win*/,
                                                       uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_RmaOpCompleteRemote( OTF2_LocationRef    locationID,
                                                                 OTF2_TimeStamp      time,
                                                                 void*                /*userData*/,
                                                                 OTF2_AttributeList*  /*attributeList*/,
                                                                 OTF2_RmaWinRef       /*win*/,
                                                                 uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadFork( OTF2_LocationRef    locationID,
                                                        OTF2_TimeStamp      time,
                                                        void*                /*userData*/,
                                                        OTF2_AttributeList*  /*attributeList*/,
                                                        OTF2_Paradigm        /*model*/,
                                                        uint32_t             /*numberOfRequestedThreads*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadJoin( OTF2_LocationRef    locationID,
                                                        OTF2_TimeStamp      time,
                                                        void*                /*userData*/,
                                                        OTF2_AttributeList*  /*attributeList*/,
                                                        OTF2_Paradigm        /*model*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadTeamBegin( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             OTF2_CommRef         /*threadTeam*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadTeamEnd( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           OTF2_CommRef         /*threadTeam*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadAcquireLock( OTF2_LocationRef    locationID,
                                                               OTF2_TimeStamp      time,
                                                               void*                /*userData*/,
                                                               OTF2_AttributeList*  /*attributeList*/,
                                                               OTF2_Paradigm        /*model*/,
                                                               uint32_t             /*lockID*/,
                                                               uint32_t             /*acquisitionOrder*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadReleaseLock( OTF2_LocationRef    locationID,
                                                               OTF2_TimeStamp      time,
                                                               void*                /*userData*/,
                                                               OTF2_AttributeList*  /*attributeList*/,
                                                               OTF2_Paradigm        /*model*/,
                                                               uint32_t             /*lockID*/,
                                                               uint32_t             /*acquisitionOrder*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadTaskCreate( OTF2_LocationRef    locationID,
                                                              OTF2_TimeStamp      time,
                                                              void*                /*userData*/,
                                                              OTF2_AttributeList*  /*attributeList*/,
                                                              OTF2_CommRef         /*threadTeam*/,
                                                              uint32_t             /*creatingThread*/,
                                                              uint32_t             /*generationNumber*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadTaskSwitch( OTF2_LocationRef    locationID,
                                                              OTF2_TimeStamp      time,
                                                              void*                /*userData*/,
                                                              OTF2_AttributeList*  /*attributeList*/,
                                                              OTF2_CommRef         /*threadTeam*/,
                                                              uint32_t             /*creatingThread*/,
                                                              uint32_t             /*generationNumber*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadTaskComplete( OTF2_LocationRef    locationID,
                                                                OTF2_TimeStamp      time,
                                                                void*                /*userData*/,
                                                                OTF2_AttributeList*  /*attributeList*/,
                                                                OTF2_CommRef         /*threadTeam*/,
                                                                uint32_t             /*creatingThread*/,
                                                                uint32_t             /*generationNumber*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadCreate( OTF2_LocationRef    locationID,
                                                          OTF2_TimeStamp      time,
                                                          void*                /*userData*/,
                                                          OTF2_AttributeList*  /*attributeList*/,
                                                          OTF2_CommRef         /*threadContingent*/,
                                                          uint64_t             /*sequenceCount*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadBegin( OTF2_LocationRef    locationID,
                                                         OTF2_TimeStamp      time,
                                                         void*                /*userData*/,
                                                         OTF2_AttributeList*  /*attributeList*/,
                                                         OTF2_CommRef         /*threadContingent*/,
                                                         uint64_t             /*sequenceCount*/ ) {

    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadWait( OTF2_LocationRef    locationID,
                                                        OTF2_TimeStamp      time,
                                                        void*                /*userData*/,
                                                        OTF2_AttributeList*  /*attributeList*/,
                                                        OTF2_CommRef         /*threadContingent*/,
                                                        uint64_t             /*sequenceCount*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_ThreadEnd( OTF2_LocationRef    locationID,
                                                       OTF2_TimeStamp      time,
                                                       void*                /*userData*/,
                                                       OTF2_AttributeList*  /*attributeList*/,
                                                       OTF2_CommRef         /*threadContingent*/,
                                                       uint64_t             /*sequenceCount*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_CallingContextEnter( OTF2_LocationRef       locationID,
                                                                 OTF2_TimeStamp         time,
                                                                 void*                   /*userData*/,
                                                                 OTF2_AttributeList*     /*attributeList*/,
                                                                 OTF2_CallingContextRef  /*callingContext*/,
                                                                 uint32_t                /*unwindDistance*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_CallingContextLeave( OTF2_LocationRef       locationID,
                                                                 OTF2_TimeStamp         time,
                                                                 void*                   /*userData*/,
                                                                 OTF2_AttributeList*     /*attributeList*/,
                                                                 OTF2_CallingContextRef  /*callingContext*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_CallingContextSample( OTF2_LocationRef           locationID,
                                                                  OTF2_TimeStamp             time,
                                                                  void*                       /*userData*/,
                                                                  OTF2_AttributeList*         /*attributeList*/,
                                                                  OTF2_CallingContextRef      /*callingContext*/,
                                                                  uint32_t                    /*unwindDistance*/,
                                                                  OTF2_InterruptGeneratorRef  /*interruptGenerator*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoCreateHandle( OTF2_LocationRef    locationID,
                                                            OTF2_TimeStamp      time,
                                                            void*                /*userData*/,
                                                            OTF2_AttributeList*  /*attributeList*/,
                                                            OTF2_IoHandleRef     /*handle*/,
                                                            OTF2_IoAccessMode    /*mode*/,
                                                            OTF2_IoCreationFlag  /*creationFlags*/,
                                                            OTF2_IoStatusFlag    /*statusFlags*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoDestroyHandle( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             OTF2_IoHandleRef     /*handle*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoDuplicateHandle( OTF2_LocationRef    locationID,
                                                               OTF2_TimeStamp      time,
                                                               void*                /*userData*/,
                                                               OTF2_AttributeList*  /*attributeList*/,
                                                               OTF2_IoHandleRef     /*oldHandle*/,
                                                               OTF2_IoHandleRef     /*newHandle*/,
                                                               OTF2_IoStatusFlag    /*statusFlags*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoSeek( OTF2_LocationRef    locationID,
                                                    OTF2_TimeStamp      time,
                                                    void*                /*userData*/,
                                                    OTF2_AttributeList*  /*attributeList*/,
                                                    OTF2_IoHandleRef     /*handle*/,
                                                    int64_t              /*offsetRequest*/,
                                                    OTF2_IoSeekOption    /*whence*/,
                                                    uint64_t             /*offsetResult*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoChangeStatusFlags( OTF2_LocationRef    locationID,
                                                                 OTF2_TimeStamp      time,
                                                                 void*                /*userData*/,
                                                                 OTF2_AttributeList*  /*attributeList*/,
                                                                 OTF2_IoHandleRef     /*handle*/,
                                                                 OTF2_IoStatusFlag    /*statusFlags*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoDeleteFile( OTF2_LocationRef    locationID,
                                                          OTF2_TimeStamp      time,
                                                          void*                /*userData*/,
                                                          OTF2_AttributeList*  /*attributeList*/,
                                                          OTF2_IoParadigmRef   /*ioParadigm*/,
                                                          OTF2_IoFileRef       /*file*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoOperationBegin( OTF2_LocationRef     locationID,
                                                              OTF2_TimeStamp       time,
                                                              void*                 /*userData*/,
                                                              OTF2_AttributeList*   /*attributeList*/,
                                                              OTF2_IoHandleRef      /*handle*/,
                                                              OTF2_IoOperationMode  /*mode*/,
                                                              OTF2_IoOperationFlag  /*operationFlags*/,
                                                              uint64_t              /*bytesRequest*/,
                                                              uint64_t              /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoOperationTest( OTF2_LocationRef    locationID,
                                                             OTF2_TimeStamp      time,
                                                             void*                /*userData*/,
                                                             OTF2_AttributeList*  /*attributeList*/,
                                                             OTF2_IoHandleRef     /*handle*/,
                                                             uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoOperationIssued( OTF2_LocationRef    locationID,
                                                               OTF2_TimeStamp      time,
                                                               void*                /*userData*/,
                                                               OTF2_AttributeList*  /*attributeList*/,
                                                               OTF2_IoHandleRef     /*handle*/,
                                                               uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    NOT_IMPLEMENTED_YET(time);
}

OTF2_CallbackCode ParserEventOTF2::callback_IoOperationComplete( OTF2_LocationRef    locationID,
                                                                 OTF2_TimeStamp      time,
                                                                 void*                /*userData*/,
                                                                 OTF2_AttributeList*  /*attributeList*/,
                                                                 OTF2_IoHandleRef     /*handle*/,
                                                                 uint64_t             /*bytesResult*/,
                                                                 uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoOperationCancelled( OTF2_LocationRef    locationID,
                                                                  OTF2_TimeStamp      time,
                                                                  void*                /*userData*/,
                                                                  OTF2_AttributeList*  /*attributeList*/,
                                                                  OTF2_IoHandleRef     /*handle*/,
                                                                  uint64_t             /*matchingId*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoAcquireLock( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           OTF2_IoHandleRef     /*handle*/,
                                                           OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoReleaseLock( OTF2_LocationRef    locationID,
                                                           OTF2_TimeStamp      time,
                                                           void*                /*userData*/,
                                                           OTF2_AttributeList*  /*attributeList*/,
                                                           OTF2_IoHandleRef     /*handle*/,
                                                           OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

OTF2_CallbackCode ParserEventOTF2::callback_IoTryLock( OTF2_LocationRef    locationID,
                                                       OTF2_TimeStamp      time,
                                                       void*                /*userData*/,
                                                       OTF2_AttributeList*  /*attributeList*/,
                                                       OTF2_IoHandleRef     /*handle*/,
                                                       OTF2_LockType        /*lockType*/ ) {
    ENTER_CALLBACK(time, locationID);
    // Nothing to do here
    return OTF2_CALLBACK_SUCCESS;
}

//
//  End of all handlers
//

int ParserEventOTF2::read_events(OTF2_Reader *reader) {

    uint64_t events_read = 0;
    OTF2_Reader_ReadAllGlobalEvents(reader, _global_evt_reader, &events_read);
    return events_read;
}

float ParserEventOTF2::get_percent_loaded() {
    // TODO: there's no easy way of computing this.
    return 0.5f;
}
