<!DOCTYPE html>
<!--
Copyright 2017 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/tracing/base/trace_stream.html">
<link rel="import" href="/tracing/importer/importer.html">
<link rel="import" href="/tracing/model/model.html">

<script>
'use strict';

tr.exportTo('tr.e.importer.fuchsia', function() {
  const IMPORT_PRIORITY = 0;
  const IDLE_THREAD_THRESHOLD = 6444000000;

  // Zircon thread state constants from:
  // https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_get_info.md
  const ZX_THREAD_STATE_NEW = 0;
  const ZX_THREAD_STATE_RUNNING = 1;
  const ZX_THREAD_STATE_SUSPENDED = 2;
  const ZX_THREAD_STATE_BLOCKED = 3;
  const ZX_THREAD_STATE_DYING = 4;
  const ZX_THREAD_STATE_DEAD = 5;

  class FuchsiaImporter extends tr.importer.Importer {
    constructor(model, eventData) {
      super(model, eventData);
      this.importPriority = IMPORT_PRIORITY;
      this.model_ = model;
      this.events_ = eventData.events;
      this.parsers_ = [];
      this.threadInfo_ = new Map();
      this.processNames_ = new Map();
      this.threadStates_ = new Map();
    }

    static canImport(eventData) {
      if (eventData instanceof tr.b.TraceStream) {
        if (eventData.isBinary) return false;
        eventData = eventData.header;
      }

      if (eventData instanceof Object && eventData.type === 'fuchsia') {
        return true;
      }

      return false;
    }

    get importerName() {
      return 'FuchsiaImporter';
    }

    get model() {
      return this.model_;
    }

    importClockSyncMarkers() {
    }

    finalizeImport() {
    }

    isIdleThread(prio, tid) {
      if (prio === undefined) {
        // If the "prio" field is not available (if we were, for example,
        // using an old trace), then fall back to the legacy heuristic of
        // assuming that large numbered threads are idle ones.
        return tid > IDLE_THREAD_THRESHOLD;
      }
      // A thread is idle iff its priority is set to 0.
      return prio === 0;
    }

    recordThreadState_(tid, timestamp, state, prio) {
      if (this.isIdleThread(prio, tid)) {
        return;
      }
      const states =
        this.threadStates_.has(tid) ? this.threadStates_.get(tid) : [];
      states.push({'ts': timestamp, state});
      this.threadStates_.set(tid, states);
    }

    // Context switch events take the form:
    // {
    //     "ph": "k",
    //     "ts": 151981130.88743783,
    //     "cpu": 1,
    //     "out": {
    //       "pid": 25977,
    //       "tid": 28909,
    //       "state": 3,
    //       "prio": 20
    //     },
    //     "in": {
    //       "pid": 0,
    //       "tid": 6444931392,
    //       "prio": 0
    //     }
    //   },
    processContextSwitchEvent_(event) {
      let tid = event.in.tid;
      let threadName = tid.toString();
      let procName = '';
      const prio = event.in.prio;

      if (this.threadInfo_.has(tid)) {
        const threadInfo = this.threadInfo_.get(tid);
        threadName = threadInfo.name;
        const pid = threadInfo.pid;
        if (this.processNames_.has(pid)) {
          procName = this.processNames_.get(pid) + ':';
        }
      }

      const name = procName + threadName;

      if (this.isIdleThread(prio, tid)) {
        tid = undefined; // Fake kernel idle task
      }

      const cpu = this.model_.kernel.getOrCreateCpu(event.cpu);
      const timestamp = tr.b.Unit.timestampFromUs(event.ts);
      cpu.switchActiveThread(timestamp, {}, tid, name, tid);

      const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
      this.recordThreadState_(tid, timestamp, SCHEDULING_STATE.RUNNING, prio);

      let outState = SCHEDULING_STATE.UNKNOWN;

      switch (event.out.state) {
        case ZX_THREAD_STATE_NEW:
          outState = SCHEDULING_STATE.RUNNABLE;
          break;

        case ZX_THREAD_STATE_RUNNING:
          outState = SCHEDULING_STATE.RUNNABLE;
          break;

        case ZX_THREAD_STATE_BLOCKED:
          outState = SCHEDULING_STATE.SLEEPING;
          break;

        case ZX_THREAD_STATE_SUSPENDED:
          outState = SCHEDULING_STATE.STOPPED;
          break;

        case ZX_THREAD_STATE_DEAD:
          outState = SCHEDULING_STATE.TASK_DEAD;
          break;
      }
      this.recordThreadState_(event.out.tid, timestamp, outState,
          event.out.prio);
    }

    processProcessInfoEvent_(event) {
      const process = this.model_.getOrCreateProcess(event.pid);
      process.name = event.name;
      this.processNames_.set(event.pid, event.name);

      if ('sort_index' in event) {
        process.sortIndex = event.sort_index;
      }
    }

    processThreadInfoEvent_(event) {
      const thread = this.model_.getOrCreateProcess(event.pid).
          getOrCreateThread(event.tid);
      thread.name = event.name;
      this.threadInfo_.set(event.tid, {'name': event.name, 'pid': event.pid});

      if ('sort_index' in event) {
        const thread = this.model_.getOrCreateProcess(event.pid).
            getOrCreateThread(event.tid);
        thread.sortIndex = event.sort_index;
      }
    }

    processEvent_(event) {
      switch (event.ph) {
        case 'k':
          this.processContextSwitchEvent_(event);
          break;
        case 'p':
          this.processProcessInfoEvent_(event);
          break;
        case 't':
          this.processThreadInfoEvent_(event);
          break;
      }
    }

    postProcessStates_() {
      for (const [tid, states] of this.threadStates_) {
        if (!this.threadInfo_.has(tid)) {
          continue;
        }
        const pid = this.threadInfo_.get(tid).pid;
        const thread = this.model_.getOrCreateProcess(
            pid).getOrCreateThread(tid);
        const slices = [];
        for (let i = 0; i < states.length - 1; i++) {
          slices.push(new tr.model.ThreadTimeSlice(
              thread, states[i].state, '',
              states[i].ts, {}, states[i + 1].ts - states[i].ts));
        }

        thread.timeSlices = slices;
      }
    }

    /**
     * Imports the data in this.events_ into model_.
     */
    importEvents() {
      for (const event of this.events_) {
        this.processEvent_(event);
      }
      this.postProcessStates_();
    }
  }

  tr.importer.Importer.register(FuchsiaImporter);

  return {
    FuchsiaImporter,
    IMPORT_PRIORITY,
  };
});
</script>
