/**
 *
 * @file src/parser/OTF2Parser/ParserEventOTF2.cpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Mathieu Faverge
 * @author Francois Trahay
 * @author Philippe Swartvagher
 *
 * @date 2024-07-17
 */
/**
 *  @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);

    // MPIRecv contains information on the thread that receives the message, and
    // on the mpi rank that sent the message.
    //
    // Similarly, MPISend contains information on the thread that sends the
    // message, and the mpi rank (within a communicator) that receive.
    //
    // To match Send and Recv operation, we construct a string "<send_rank> to
    // <recv_rank> tag <tag>"

    OTF2_Location *send_thread = ParserDefinitionOTF2::get_location_by_id(sender);
    OTF2_LocationGroup *send_process = ParserDefinitionOTF2::get_location_group_by_id(send_thread->_group_id);

    OTF2_LocationGroup *recv_process = ParserDefinitionOTF2::get_location_group_in_communicator(communicator, receiver);

    Container *send_container = send_thread->container;
    Container *recv_container = recv_process->container;
    // The sender process may have no ancestor, so let's say that his ancestor is himself
    Container *ancestor_container = recv_container;

    String send_string = send_process->container->get_name(); // use the process name because the receiver does not know which thread sends the data
    String ancestor_string = ancestor_container->get_name();
    String recv_string = recv_container->get_name();

    /* Value */
    string name = send_string.to_string() + " to " + recv_string.to_string() + " 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);

    map<string, Value *> opt;

    if (link_type == 0) {
        const ContainerType *source_type = send_container->get_type();
        const ContainerType *ancestor_type = ancestor_container->get_type();

        ContainerType *temp_source_type = t->search_container_type(source_type->get_Name().to_string());
        ContainerType *temp_ancestor_type = t->search_container_type(ancestor_type->get_Name().to_string());

        Name link_name = Name(link_type_oss.str());
        t->define_link_type(link_name, temp_ancestor_type, temp_source_type, temp_source_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, send_container, /* TODO: EntityValue */ NULL, 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);

    // MPIRecv contains information on the thread that receives the message, and
    // on the mpi rank that sent the message.
    //
    // Similarly, MPISend contains information on the thread that sends the
    // message, and the mpi rank (within a communicator) that receive.
    //
    // To match Send and Recv operation, we construct a string "<send_rank> to
    // <recv_rank> tag <tag>"

    OTF2_LocationGroup *send_process = ParserDefinitionOTF2::get_location_group_in_communicator(communicator, sender);

    OTF2_Location *recv_thread = ParserDefinitionOTF2::get_location_by_id(receiver);
    OTF2_LocationGroup *recv_process = ParserDefinitionOTF2::get_location_group_by_id(recv_thread->_group_id);

    Container *recv_cont = recv_thread->container;
    Container *send_cont = send_process->container;
    Container *ancestor_cont = recv_process->container;

    String send_string = send_cont->get_name();
    String ancestor_string = ancestor_cont->get_name();
    String recv_string = recv_process->container->get_name();

    /* Value */
    // This string is used for matching send and recv operations
    string name = send_string.to_string() + " to " + recv_string.to_string() + " 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);

    map<string, Value *> opt;

    if (link_type == 0) {

        const ContainerType *recv_type = recv_cont->get_type();
        const ContainerType *ancestor_type = ancestor_cont->get_type();

        ContainerType *temp_recv_type = t->search_container_type(recv_type->get_Name().to_string());
        ContainerType *temp_ancestor_type = t->search_container_type(ancestor_type->get_Name().to_string());

        Name link_name = Name(link_type_oss.str());
        t->define_link_type(link_name, temp_ancestor_type, temp_recv_type, temp_recv_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, recv_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;
}
