/*******************************************************************************
 * Copyright (c) 2016 École Polytechnique de Montréal
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License 2.0 which
 * accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/

package org.eclipse.tracecompass.incubator.internal.xaf.core.statemachine.backend;

import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfCpuAspect;
import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;

/**
 * The state provider used by our state machine state system analysis.
 *
 * <pre>
 * (root)
 *   `-- tid
 *        |-- (thread id 1)
 *        |    |-- (timer:cpu_usage)
 *        |    |-- (timer:wait_blocked)
 *        |    |-- (timer:wait_for_cpu)
 *        |    |-- (counter:syscalls)
 *        |    `-- (counter:preempt)
 *        |-- (thread id 2)
 *        |   ...
 *        |-- (thread id 3)
 *        |   ...
 *       ...
 * </pre>
 *
 * @author Raphaël Beamonte
 */
class StateMachineProviderEventTypes extends AbstractTmfStateProvider {

    /**
     * Version number of this input handler. Please bump this if you modify the
     * contents of the generated state history in some way.
     */
    private static final int VERSION = 2016070701;

    /** Forgotten string chains */
    private static final @NonNull String LAYOUT_CONTEXT_VTID = "context._vtid"; //$NON-NLS-1$
    private static final @NonNull String LAYOUT_PREV_PRIO = "prev_prio"; //$NON-NLS-1$
    private static final @NonNull String LAYOUT_STATE = "state"; //$NON-NLS-1$
    private static final @NonNull String LAYOUT_CPU_ID = "cpu_id"; //$NON-NLS-1$
    private static final @NonNull String EVENT_SCHED_WAKING = "sched_waking"; //$NON-NLS-1$
    private static final @NonNull String EVENT_IRQ_SOFTIRQ_ENTRY = "irq_softirq_entry"; //$NON-NLS-1$
    private static final @NonNull String EVENT_POWER_CPU_FREQUENCY = "power_cpu_frequency"; //$NON-NLS-1$

    /**
     * A map giving information about what process
     * is on what CPU
     */
    private Map<Integer, Long> threadByCPU = new TreeMap<>();

    /**
     * Save the information to compute the CPU Usage by TID
     */
    private Map<Long, ThreadInfo> info_by_tid = new HashMap<>();
    private @NonNull ThreadInfo getThreadInfoOrCreate(Long tid) {
        ThreadInfo threadInfo = info_by_tid.get(tid);
        if (threadInfo == null) {
            threadInfo = new ThreadInfo();
            info_by_tid.put(tid, threadInfo);
        }
        return threadInfo;
    }

    /**
     * Constructor
     *
     * @param trace
     *            The trace for which we build this state system
     */
    public StateMachineProviderEventTypes(@NonNull ITmfTrace trace) {
        super(trace , StateMachineBackendAnalysis.NAME);
    }

    @Override
    public int getVersion() {
        return VERSION;
    }

    @Override
    public StateMachineProviderEventTypes getNewInstance() {
        return new StateMachineProviderEventTypes(this.getTrace());
    }

    @Override
    protected void eventHandle(ITmfEvent event) {
        ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
        int quark;

        /* Since this can be used for any trace types, normalize all the
         * timestamp values to nanoseconds. */
        final long ts = event.getTimestamp().toNanos();

        final String eventName = event.getType().getName();
        IKernelAnalysisEventLayout layout = ((IKernelTrace) getTrace()).getKernelEventLayout();

        if (eventName.equals(layout.eventSchedSwitch())) {
            ITmfEventField content = event.getContent();
            Long prevTid = (Long)content.getField(layout.fieldPrevTid()).getValue();
            Long nextTid = (Long)content.getField(layout.fieldNextTid()).getValue();
            Long prevState = (Long)content.getField(layout.fieldPrevState()).getValue();
            Integer nextPrio = ((Long)content.getField(layout.fieldNextPrio()).getValue()).intValue();
            Integer prevPrio = ((Long)content.getField(LAYOUT_PREV_PRIO).getValue()).intValue();

            Integer cpu = checkNotNull((Integer)TmfTraceUtils.resolveEventAspectOfClassForEvent(getTrace(), TmfCpuAspect.class, event));
            threadByCPU.put(cpu, nextTid);

            ThreadInfo prevThreadInfo = getThreadInfoOrCreate(prevTid);
            ThreadInfo nextThreadInfo = getThreadInfoOrCreate(nextTid);

            ////////////////////////////////
            // NEXT THREAD (BEING SCHEDULED)
            int quarkNextTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, nextTid.toString());

            // CPU: update the cpu number if needed
            if (nextThreadInfo.cpu_last != cpu) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.CPU);
                    TmfStateValue value = TmfStateValue.newValueInt(cpu);
                    ss.modifyAttribute(ts, value, quark);
                    nextThreadInfo.cpu_last = cpu;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            // PRIO: update the priority if needed
            if (nextThreadInfo.prio_last != nextPrio) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.PRIO);
                    TmfStateValue value = TmfStateValue.newValueInt(nextPrio);
                    ss.modifyAttribute(ts, value, quark);
                    nextThreadInfo.prio_last = nextPrio;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            // STATE: Change to RUNNING
            BackendState s = null;
            if (!nextThreadInfo.stack_state.isEmpty()) {
                nextThreadInfo.stack_state.pop();
                s = nextThreadInfo.stack_state.peek();
            }
            if (s == null) {
                s = new BackendState(BackendStateValue.RUNNING.getValue());
            }
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }

            // TIMER_WAIT_(BLOCKED|FOR_CPU)
            // TODO: find a way to update the time spent in WAIT_FOR_SOMETHING
            // for cases where the thread hasn't returned when finishing
            if (nextThreadInfo.last_state != null) {
                if (nextThreadInfo.last_state != 0 && nextThreadInfo.last_state != 1024) {
                    // TIMER_WAIT_BLOCKED
                    try {
                        quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.TIMER_WAIT_BLOCKED);

                        if (nextThreadInfo.cumul_wait_blocked == 0L) {
                            TmfStateValue value = TmfStateValue.newValueLong(0L);
                            ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                        }

                        nextThreadInfo.cumul_wait_blocked += ts - nextThreadInfo.last_ts;

                        TmfStateValue value = TmfStateValue.newValueLong(nextThreadInfo.cumul_wait_blocked);
                        ss.modifyAttribute(ts, value, quark);
                    } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                        e.printStackTrace();
                    }
                } else {
                    // TIMER_WAIT_FOR_CPU
                    try {
                        quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.TIMER_WAIT_FOR_CPU);

                        if (nextThreadInfo.cumul_wait_for_cpu == 0L) {
                            TmfStateValue value = TmfStateValue.newValueLong(0L);
                            ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                        }

                        nextThreadInfo.cumul_wait_for_cpu += ts - nextThreadInfo.last_ts;

                        TmfStateValue value = TmfStateValue.newValueLong(nextThreadInfo.cumul_wait_for_cpu);
                        ss.modifyAttribute(ts, value, quark);
                    } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                        e.printStackTrace();
                    }
                }
            }

            // TIMER_WAKEUP_LATENCY
            if (nextThreadInfo.last_wakeup != null) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkNextTid, Attributes.TIMER_WAKEUP_LATENCY);

                    if (nextThreadInfo.cumul_wakeup_latency == 0L) {
                        TmfStateValue value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                    }

                    nextThreadInfo.cumul_wakeup_latency += ts - nextThreadInfo.last_wakeup;

                    TmfStateValue value = TmfStateValue.newValueLong(nextThreadInfo.cumul_wakeup_latency);
                    ss.modifyAttribute(ts, value, quark);

                    // Reset last wakeup time to null, so that it will be used only next time we receive a sched_waking
                    nextThreadInfo.last_wakeup = null;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            //////////////////////////////////////
            // PREVIOUS THREAD (BEING UNSCHEDULED)
            int quarkPrevTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, prevTid.toString());

            // PRIO: update the priority if needed
            if (prevThreadInfo.prio_last != prevPrio) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkPrevTid, Attributes.PRIO);
                    TmfStateValue value = TmfStateValue.newValueInt(prevPrio);
                    ss.modifyAttribute(ts, value, quark);
                    prevThreadInfo.prio_last = prevPrio;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            // TIMER_CPU_USAGE
            // We chose here to consider the data from the trace, even if it's not the actual running duration
            //if (prevThreadInfo.last_ts != null) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkPrevTid, Attributes.TIMER_CPU_USAGE);

                    if (prevThreadInfo.cumul_cpu_usage == 0L) {
                        TmfStateValue value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                        //ss.modifyAttribute(prevThreadInfo.last_ts, value, quark);
                    }

                    long previousTs = (prevThreadInfo.last_ts != null)
                            ? prevThreadInfo.last_ts
                            : getTrace().getStartTime().toNanos();
                    prevThreadInfo.cumul_cpu_usage += ts - previousTs;

                    TmfStateValue value = TmfStateValue.newValueLong(prevThreadInfo.cumul_cpu_usage);
                    ss.modifyAttribute(ts, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            //}
            nextThreadInfo.last_ts = ts;

            // For wait for CPU and wait blocked for next time
            prevThreadInfo.last_ts = ts;
            prevThreadInfo.last_state = prevState;

            s = null;
            if (prevState == 0 || prevState == 1024) {
                // STATE: Change to PREEMPTED
                s = new BackendState(BackendStateValue.PREEMPTED.getValue());
                // COUNTER_PREEMPT: Increment
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkPrevTid, Attributes.COUNTER_PREEMPT);

                    if (prevThreadInfo.counter_preempt == 0) {
                        TmfStateValue value = TmfStateValue.newValueInt(0);
                        ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                    }

                    prevThreadInfo.counter_preempt++;

                    TmfStateValue value = TmfStateValue.newValueInt(prevThreadInfo.counter_preempt);
                    ss.modifyAttribute(ts, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            } else {
                // STATE: Change to BLOCKED
                s = new BackendState(BackendStateValue.BLOCKED.getValue());
            }

            prevThreadInfo.stack_state.push(s);
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkPrevTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        } else if (eventName.equals(layout.eventSchedPiSetprio())) {
            ITmfEventField content = event.getContent();
            Long fromTid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();
            Long toTid = (Long)content.getField(layout.fieldTid()).getValue();
            Integer newPrio = ((Long)content.getField(layout.fieldNewPrio()).getValue()).intValue();

            // Get the threadInfo from the thread with raised priority
            ThreadInfo toThreadInfo = getThreadInfoOrCreate(toTid);

            // PRIO: update the priority if needed
            if (toThreadInfo.prio_last != newPrio) {
                try {
                    quark = ss.getQuarkAbsoluteAndAdd(Attributes.TID, toTid.toString(), Attributes.PRIO);
                    TmfStateValue value = TmfStateValue.newValueInt(newPrio);
                    ss.modifyAttribute(ts, value, quark);
                    toThreadInfo.prio_last = newPrio;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            if (fromTid.equals(toTid)) {
                // Going back to normal
                // Then, for each thread that raised its priority, add to the cumulated time
                for (Long tid : toThreadInfo.sched_pi_fromTids) {
                    ThreadInfo fromThreadInfo = getThreadInfoOrCreate(tid);

                    boolean wasZero = (fromThreadInfo.sched_pi_cumul == 0);
                    fromThreadInfo.sched_pi_cumul += ts - fromThreadInfo.sched_pi_lastTs;
                    fromThreadInfo.sched_pi_lastTs = null;
                    //fromThreadInfo.sched_pi_toTid = null;

                    // Update SS
                    try {
                        quark = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());
                        quark = ss.getQuarkRelativeAndAdd(quark, Attributes.TIMER_SCHED_PI);

                        if (wasZero) {
                            TmfStateValue value = TmfStateValue.newValueLong(0);
                            ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                        }

                        TmfStateValue value = TmfStateValue.newValueLong(fromThreadInfo.sched_pi_cumul);
                        ss.modifyAttribute(ts, value, quark);
                    } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                        e.printStackTrace();
                    }
                }
                // Then clear the list of fromTids
                toThreadInfo.sched_pi_fromTids.clear();
            } else {
                // fromTid started giving its priority to toTid

                // Update the threadInfo for the fromTid
                ThreadInfo fromThreadInfo = getThreadInfoOrCreate(fromTid);
                fromThreadInfo.sched_pi_lastTs = ts;
                //fromThreadInfo.sched_pi_toTid = toTid;

                // Update the threadInfo for the toTid
                toThreadInfo.sched_pi_fromTids.add(fromTid);
            }
        } else if (eventName.equals(EVENT_SCHED_WAKING)) {
            // Get the TID we want to wake up
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(layout.fieldTid()).getValue();
            Integer prio = ((Long)content.getField(layout.fieldPrio()).getValue()).intValue();

            ThreadInfo threadInfo = getThreadInfoOrCreate(tid);

            threadInfo.last_wakeup = ts;

            // Thread quark
            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // PRIO: update the priority if needed
            if (threadInfo.prio_last != prio) {
                try {
                    quark = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString(), Attributes.PRIO);
                    TmfStateValue value = TmfStateValue.newValueInt(prio);
                    ss.modifyAttribute(ts, value, quark);
                    threadInfo.prio_last = prio;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            // STATE: Change to WAKING
            BackendState s = new BackendState(BackendStateValue.WAKING.getValue());
            if (!threadInfo.stack_state.isEmpty()) {
                // If not empty, the last status should either be PREEMPTED or BLOCKED,
                // we don't need any of them anymore in the stack as they are over so...
                threadInfo.stack_state.pop();
            }
            threadInfo.stack_state.push(s);
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        } else if (eventName.equals(EVENT_POWER_CPU_FREQUENCY)) {
            ITmfEventField content = event.getContent();
            Long cpu = (Long)content.getField(LAYOUT_CPU_ID).getValue();
            Long freq = (Long)content.getField(LAYOUT_STATE).getValue();

            try {
                quark = ss.getQuarkAbsoluteAndAdd(Attributes.CPU_FREQ, cpu.toString());
                TmfStateValue value = TmfStateValue.newValueLong(freq);
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        } else if (eventName.equals(layout.eventSoftIrqEntry()) || eventName.equals(EVENT_IRQ_SOFTIRQ_ENTRY)) {
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();
            Long vec = (Long)content.getField("vec").getValue(); //$NON-NLS-1$

            // Thread quark
            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // Thread info
            ThreadInfo threadInfo = getThreadInfoOrCreate(tid);

            // STATE: Change to the right SOFTIRQ
            BackendState s = new BackendState(BackendState.TYPE_SOFTIRQ, vec);
            threadInfo.stack_state.push(s);
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        } else if (eventName.equals(layout.eventHRTimerExpireEntry()) || eventName.equals("timer_hrtimer_expire_entry")) { //$NON-NLS-1$
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();

            // Thread quark
            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // Thread info
            ThreadInfo threadInfo = getThreadInfoOrCreate(tid);

            // STATE: Change to HRTIMER
            BackendState s = new BackendState(BackendStateValue.HRTIMER.getValue());
            threadInfo.stack_state.push(s);
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        } else if (eventName.equals(layout.eventIrqHandlerEntry())) {
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();
            Long irq = (Long)content.getField("irq").getValue(); //$NON-NLS-1$

            // Thread quark
            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // Thread info
            ThreadInfo threadInfo = getThreadInfoOrCreate(tid);

            // STATE: Change to the right IRQ
            BackendState s = new BackendState(BackendState.TYPE_IRQ, irq);
            threadInfo.stack_state.push(s);
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
            // TODO: démarrer le timer de IRQ preemption, qui sera stoppé lors du irq handler exit
            // TODO: augmenter le compteur de préemptions ? (probablement!)
            // TODO: stopper le timer de CPU Usage et démarrer le timer de preemption ?
            // TODO: mettre à jour l'attribute state pour "IRQ_PREEMPTED" ?
        } else if (eventName.startsWith(layout.eventSyscallEntryPrefix())) {
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();

            /*
            Integer cpu = checkNotNull((Integer)TmfTraceUtils.resolveEventAspectOfClassForEvent(getTrace(), TmfCpuAspect.class, event));
            Long tid = threadByCPU.get(cpu);

            if (tid == null) {
                KernelAnalysisModule kernelAnalysisModule = (KernelAnalysisModule)TmfTraceUtils.getAnalysisModuleOfClass(getTrace(), TmfStateSystemAnalysisModule.class, KernelAnalysisModule.ID);
                if (kernelAnalysisModule != null) {
                    Integer eventTid = KernelThreadInformationProvider.getThreadOnCpu(kernelAnalysisModule, cpu, ts);
                    if (eventTid != null) {
                        tid = new Long(eventTid);
                        threadByCPU.put(cpu, tid);
                    }
                }
            }
            */

            if (tid != null) {
                ThreadInfo threadInfo = getThreadInfoOrCreate(tid);
                threadInfo.counter_syscalls += 1;

                // Thread quark
                int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

                // COUNTER_SYSCALLS
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.COUNTER_SYSCALLS);

                if (threadInfo.counter_syscalls == 1) {
                    try {
                        TmfStateValue value = TmfStateValue.newValueInt(0);
                        ss.modifyAttribute(getTrace().getStartTime().toNanos(), value, quark);
                    } catch (StateValueTypeException | IndexOutOfBoundsException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    TmfStateValue value = TmfStateValue.newValueInt(threadInfo.counter_syscalls);
                    ss.modifyAttribute(ts, value, quark);
                } catch (StateValueTypeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }

                // STATE: Change to SYSCALL
                BackendState s = new BackendState(BackendStateValue.SYSCALL.getValue());
                threadInfo.stack_state.push(s);
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                    TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                    ss.modifyAttribute(ts, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }
        } else if (eventName.equals(layout.eventSoftIrqExit()) || eventName.equals("irq_softirq_exit") //$NON-NLS-1$
                || eventName.equals(layout.eventHRTimerExpireExit()) || eventName.equals("timer_hrtimer_expire_exit") //$NON-NLS-1$
                || eventName.equals(layout.eventIrqHandlerExit())
                || eventName.startsWith(layout.eventSyscallExitPrefix())) {
            ITmfEventField content = event.getContent();
            Long tid = (Long)content.getField(LAYOUT_CONTEXT_VTID).getValue();

            // Thread quark
            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // Thread info
            ThreadInfo threadInfo = getThreadInfoOrCreate(tid);

            // STATE: Change to the last state value
            BackendState s = null;
            if (!threadInfo.stack_state.isEmpty()) {
                threadInfo.stack_state.pop();
                s = threadInfo.stack_state.peek();
            }
            if (s == null) {
                s = new BackendState(BackendStateValue.RUNNING.getValue());
            }
            try {
                quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.STATE);
                TmfStateValue value = TmfStateValue.newValueLong(s.getValue());
                ss.modifyAttribute(ts, value, quark);
            } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        //} else if (eventName.equals(layout.eventIrqHandlerExit())) {
            // TODO: stopper le timer de IRQ preemption
            // TODO: stopper le timer de preemption et redémarrer le timer de CPU Usage ?
        }
    }

    /**
     * @since 2.0
     */
    @Override
    public void done() {
        int quark;
        TmfStateValue value;
        ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
        long traceStartTime = getTrace().getStartTime().toNanos();
        long traceEndTime = getTrace().getEndTime().toNanos();

        // Update all the timers if necessary
        for (@NonNull Entry<Long, ThreadInfo> entry : info_by_tid.entrySet()) {
            Long tid = entry.getKey();
            ThreadInfo threadInfo = entry.getValue();

            int quarkTid = ss.getQuarkAbsoluteAndAdd(Attributes.TID, tid.toString());

            // TIMER_WAKEUP_LATENCY
            if (threadInfo.last_wakeup != null) {
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.TIMER_WAKEUP_LATENCY);

                    if (threadInfo.cumul_wakeup_latency == 0L) {
                        value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(traceStartTime, value, quark);
                    }

                    threadInfo.cumul_wakeup_latency += traceEndTime - threadInfo.last_wakeup;

                    value = TmfStateValue.newValueLong(threadInfo.cumul_wakeup_latency);
                    ss.modifyAttribute(traceEndTime, value, quark);

                    // Reset last wakeup time to null, so that it will be used only next time we receive a sched_waking
                    threadInfo.last_wakeup = null;
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }

            BackendState state = threadInfo.stack_state.peek();
            BackendStateValue stateValue = (state == null) ? null : BackendStateValue.getValue(state.getValue());

            if (stateValue == BackendStateValue.BLOCKED) {
                // TIMER_WAIT_BLOCKED
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.TIMER_WAIT_BLOCKED);

                    if (threadInfo.cumul_wait_blocked == 0L) {
                        value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(traceStartTime, value, quark);
                    }

                    threadInfo.cumul_wait_blocked += traceEndTime - threadInfo.last_ts;

                    value = TmfStateValue.newValueLong(threadInfo.cumul_wait_blocked);
                    ss.modifyAttribute(traceEndTime, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            } else if (stateValue == BackendStateValue.PREEMPTED) {
                // TIMER_WAIT_FOR_CPU
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.TIMER_WAIT_FOR_CPU);

                    if (threadInfo.cumul_wait_for_cpu == 0L) {
                        value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(traceStartTime, value, quark);
                    }

                    threadInfo.cumul_wait_for_cpu += traceEndTime - threadInfo.last_ts;

                    value = TmfStateValue.newValueLong(threadInfo.cumul_wait_for_cpu);
                    ss.modifyAttribute(traceEndTime, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            } else {
                // TIMER_CPU_USAGE
                try {
                    quark = ss.getQuarkRelativeAndAdd(quarkTid, Attributes.TIMER_CPU_USAGE);

                    if (threadInfo.cumul_cpu_usage == 0L) {
                        value = TmfStateValue.newValueLong(0L);
                        ss.modifyAttribute(traceStartTime, value, quark);
                    }

                    long previousTs = (threadInfo.last_ts != null)
                            ? threadInfo.last_ts
                            : traceStartTime;
                    threadInfo.cumul_cpu_usage += traceEndTime - previousTs;

                    value = TmfStateValue.newValueLong(threadInfo.cumul_cpu_usage);
                    ss.modifyAttribute(traceEndTime, value, quark);
                } catch (StateValueTypeException | TimeRangeException | IndexOutOfBoundsException e) {
                    e.printStackTrace();
                }
            }
            threadInfo.last_ts = traceEndTime;
        }
        info_by_tid.clear();
    }
}