<!DOCTYPE html>
<!--
Copyright (c) 2012 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="/ui/base/color_scheme.html">
<link rel="import" href="/extras/importer/linux_perf/bus_parser.html">
<link rel="import" href="/extras/importer/linux_perf/clock_parser.html">
<link rel="import" href="/extras/importer/linux_perf/cpufreq_parser.html">
<link rel="import" href="/extras/importer/linux_perf/disk_parser.html">
<link rel="import" href="/extras/importer/linux_perf/drm_parser.html">
<link rel="import" href="/extras/importer/linux_perf/irq_parser.html">
<link rel="import" href="/extras/importer/linux_perf/exynos_parser.html">
<link rel="import" href="/extras/importer/linux_perf/gesture_parser.html">
<link rel="import" href="/extras/importer/linux_perf/i915_parser.html">
<link rel="import" href="/extras/importer/linux_perf/mali_parser.html">
<link rel="import" href="/extras/importer/linux_perf/memreclaim_parser.html">
<link rel="import" href="/extras/importer/linux_perf/binder_parser.html">
<link rel="import" href="/extras/importer/linux_perf/power_parser.html">
<link rel="import" href="/extras/importer/linux_perf/regulator_parser.html">
<link rel="import" href="/extras/importer/linux_perf/sched_parser.html">
<link rel="import" href="/extras/importer/linux_perf/sync_parser.html">
<link rel="import" href="/extras/importer/linux_perf/workqueue_parser.html">
<link rel="import" href="/extras/importer/linux_perf/android_parser.html">
<link rel="import" href="/extras/importer/linux_perf/kfunc_parser.html">
<link rel="import" href="/importer/importer.html">
<link rel="import" href="/importer/simple_line_reader.html">
<link rel="import" href="/model/model.html">

<script>
/**
 * @fileoverview Imports text files in the Linux event trace format into the
 * Model. This format is output both by sched_trace and by Linux's perf tool.
 *
 * This importer assumes the events arrive as a string. The unit tests provide
 * examples of the trace format.
 *
 * Linux scheduler traces use a definition for 'pid' that is different than
 * tracing uses. Whereas tracing uses pid to identify a specific process, a pid
 * in a linux trace refers to a specific thread within a process. Within this
 * file, we the definition used in Linux traces, as it improves the importing
 * code's readability.
 */
'use strict';

tr.exportTo('tr.e.importer.linux_perf', function() {
  var Importer = tr.importer.Importer;
  var ClockSyncRecord = tr.ClockSyncRecord;

  /**
   * Imports linux perf events into a specified model.
   * @constructor
   */
  function LinuxPerfImporter(model, events) {
    this.importPriority = 2;
    this.model_ = model;
    this.events_ = events;
    this.newlyAddedClockSyncRecords_ = [];
    this.wakeups_ = [];
    this.kernelThreadStates_ = {};
    this.buildMapFromLinuxPidsToThreads();
    this.lines_ = [];
    this.pseudoThreadCounter = 1;
    this.parsers_ = [];
    this.eventHandlers_ = {};
  }

  var TestExports = {};

  // Matches the trace record in 3.2 and later with the print-tgid option:
  //          <idle>-0    0 [001] d...  1.23: sched_switch
  //
  // A TGID (Thread Group ID) is basically what the Linux kernel calls what
  // userland refers to as a process ID (as opposed to a Linux pid, which is
  // what userland calls a thread ID).
  var lineREWithTGID = new RegExp(
      '^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]' +
      '\\s+[dX.][N.][Hhs.][0-9a-f.]' +
      '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
  var lineParserWithTGID = function(line) {
    var groups = lineREWithTGID.exec(line);
    if (!groups) {
      return groups;
    }

    var tgid = groups[3];
    if (tgid[0] === '-')
      tgid = undefined;

    return {
      threadName: groups[1],
      pid: groups[2],
      tgid: tgid,
      cpuNumber: groups[4],
      timestamp: groups[5],
      eventName: groups[6],
      details: groups[7]
    };
  };
  TestExports.lineParserWithTGID = lineParserWithTGID;

  // Matches the default trace record in 3.2 and later (includes irq-info):
  //          <idle>-0     [001] d...  1.23: sched_switch
  var lineREWithIRQInfo = new RegExp(
      '^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]' +
      '\\s+[dX.][N.][Hhs.][0-9a-f.]' +
      '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
  var lineParserWithIRQInfo = function(line) {
    var groups = lineREWithIRQInfo.exec(line);
    if (!groups) {
      return groups;
    }
    return {
      threadName: groups[1],
      pid: groups[2],
      cpuNumber: groups[3],
      timestamp: groups[4],
      eventName: groups[5],
      details: groups[6]
    };
  };
  TestExports.lineParserWithIRQInfo = lineParserWithIRQInfo;

  // Matches the default trace record pre-3.2:
  //          <idle>-0     [001]  1.23: sched_switch
  var lineREWithLegacyFmt =
      /^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;
  var lineParserWithLegacyFmt = function(line) {
    var groups = lineREWithLegacyFmt.exec(line);
    if (!groups) {
      return groups;
    }
    return {
      threadName: groups[1],
      pid: groups[2],
      cpuNumber: groups[3],
      timestamp: groups[4],
      eventName: groups[5],
      details: groups[6]
    };
  };
  TestExports.lineParserWithLegacyFmt = lineParserWithLegacyFmt;

  // Matches the trace_event_clock_sync record
  //  0: trace_event_clock_sync: parent_ts=19581477508
  var traceEventClockSyncRE = /trace_event_clock_sync: parent_ts=(\d+\.?\d*)/;
  TestExports.traceEventClockSyncRE = traceEventClockSyncRE;

  var genericClockSyncRE = /trace_event_clock_sync: name=(\w+)/;

  // Some kernel trace events are manually classified in slices and
  // hand-assigned a pseudo PID.
  var pseudoKernelPID = 0;

  /**
   * Deduce the format of trace data. Linux kernels prior to 3.3 used one
   * format (by default); 3.4 and later used another.  Additionally, newer
   * kernels can optionally trace the TGID.
   *
   * @return {function} the function for parsing data when the format is
   * recognized; otherwise null.
   */
  function autoDetectLineParser(line) {
    if (line[0] == '{')
      return false;
    if (lineREWithTGID.test(line))
      return lineParserWithTGID;
    if (lineREWithIRQInfo.test(line))
      return lineParserWithIRQInfo;
    if (lineREWithLegacyFmt.test(line))
      return lineParserWithLegacyFmt;
    return null;
  };
  TestExports.autoDetectLineParser = autoDetectLineParser;

  /**
   * Guesses whether the provided events is a Linux perf string.
   * Looks for the magic string "# tracer" at the start of the file,
   * or the typical task-pid-cpu-timestamp-function sequence of a typical
   * trace's body.
   *
   * @return {boolean} True when events is a linux perf array.
   */
  LinuxPerfImporter.canImport = function(events) {
    if (!(typeof(events) === 'string' || events instanceof String))
      return false;

    if (LinuxPerfImporter._extractEventsFromSystraceHTML(events, false).ok)
      return true;

    if (LinuxPerfImporter._extractEventsFromSystraceMultiHTML(events, false).ok)
      return true;

    if (/^# tracer:/.test(events))
      return true;

    var lineBreakIndex = events.indexOf('\n');
    if (lineBreakIndex > -1)
      events = events.substring(0, lineBreakIndex);

    if (autoDetectLineParser(events))
      return true;

    return false;
  };

  LinuxPerfImporter._extractEventsFromSystraceHTML = function(
      incoming_events, produce_result) {
    var failure = {ok: false};
    if (produce_result === undefined)
      produce_result = true;

    if (/^<!DOCTYPE HTML>/.test(incoming_events) == false)
      return failure;
    var r = new tr.importer.SimpleLineReader(incoming_events);

    // Try to find the data...
    if (!r.advanceToLineMatching(/^  <script>$/))
      return failure;
    if (!r.advanceToLineMatching(/^  var linuxPerfData = "\\$/))
      return failure;

    var events_begin_at_line = r.curLineNumber + 1;
    r.beginSavingLines();
    if (!r.advanceToLineMatching(/^  <\/script>$/))
      return failure;

    var raw_events = r.endSavingLinesAndGetResult();

    // Drop off first and last event as it contains the tag.
    raw_events = raw_events.slice(1, raw_events.length - 1);

    if (!r.advanceToLineMatching(/^<\/body>$/))
      return failure;
    if (!r.advanceToLineMatching(/^<\/html>$/))
      return failure;

    function endsWith(str, suffix) {
      return str.indexOf(suffix, str.length - suffix.length) !== -1;
    }
    function stripSuffix(str, suffix) {
      if (!endsWith(str, suffix))
        return str;
      return str.substring(str, str.length - suffix.length);
    }

    // Strip off escaping in the file needed to preserve linebreaks.
    var events = [];
    if (produce_result) {
      for (var i = 0; i < raw_events.length; i++) {
        var event = raw_events[i];
        event = stripSuffix(event, '\\n\\');
        events.push(event);
      }
    } else {
      events = [raw_events[raw_events.length - 1]];
    }

    // Last event ends differently. Strip that off too,
    // treating absence of that trailing string as a failure.
    var oldLastEvent = events[events.length - 1];
    var newLastEvent = stripSuffix(oldLastEvent, '\\n";');
    if (newLastEvent == oldLastEvent)
      return failure;
    events[events.length - 1] = newLastEvent;

    return {ok: true,
      lines: produce_result ? events : undefined,
      events_begin_at_line: events_begin_at_line};
  };

  LinuxPerfImporter._extractEventsFromSystraceMultiHTML = function(
      incoming_events, produce_result) {
    var failure = {ok: false};
    if (produce_result === undefined)
      produce_result = true;

    if (/^<!DOCTYPE HTML>/.test(incoming_events) == false)
      return failure;
    var r = new tr.importer.SimpleLineReader(incoming_events);

    // Try to find the Linux perf trace in any of the trace-data tags
    var events = [];
    while (!/^# tracer:/.test(events)) {
      if (!r.advanceToLineMatching(
          /^  <script class="trace-data" type="application\/text">$/))
        return failure;

      var events_begin_at_line = r.curLineNumber + 1;

      r.beginSavingLines();
      if (!r.advanceToLineMatching(/^  <\/script>$/))
        return failure;

      events = r.endSavingLinesAndGetResult();

      // Drop off first and last event as it contains the tag.
      events = events.slice(1, events.length - 1);
    }

    if (!r.advanceToLineMatching(/^<\/body>$/))
      return failure;
    if (!r.advanceToLineMatching(/^<\/html>$/))
      return failure;

    return {ok: true,
      lines: produce_result ? events : undefined,
      events_begin_at_line: events_begin_at_line};
  };

  LinuxPerfImporter.prototype = {
    __proto__: Importer.prototype,

    get model() {
      return this.model_;
    },

    /**
     * Precomputes a lookup table from linux pids back to existing
     * Threads. This is used during importing to add information to each
     * thread about whether it was running, descheduled, sleeping, et
     * cetera.
     */
    buildMapFromLinuxPidsToThreads: function() {
      this.threadsByLinuxPid = {};
      this.model_.getAllThreads().forEach(
          function(thread) {
            this.threadsByLinuxPid[thread.tid] = thread;
          }.bind(this));
    },

    /**
     * @return {Cpu} A Cpu corresponding to the given cpuNumber.
     */
    getOrCreateCpu: function(cpuNumber) {
      return this.model_.kernel.getOrCreateCpu(cpuNumber);
    },

    /**
     * @return {TimelineThread} A thread corresponding to the kernelThreadName.
     */
    getOrCreateKernelThread: function(kernelThreadName, pid, tid) {
      if (!this.kernelThreadStates_[kernelThreadName]) {
        var thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);
        thread.name = kernelThreadName;
        this.kernelThreadStates_[kernelThreadName] = {
          pid: pid,
          thread: thread,
          openSlice: undefined,
          openSliceTS: undefined
        };
        this.threadsByLinuxPid[pid] = thread;
      }
      return this.kernelThreadStates_[kernelThreadName];
    },

    /**
     * Processes can have multiple binder threads.
     * Binder thread names are not unique across processes we therefore need to
     * keep more information in order to return the correct threads.
     */
    getOrCreateBinderKernelThread: function(kernelThreadName, pid, tid) {
      var key = kernelThreadName + pid + tid;
      if (!this.kernelThreadStates_[key]) {
        var thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);
        thread.name = kernelThreadName;
        this.kernelThreadStates_[key] = {
          pid: pid,
          thread: thread,
          openSlice: undefined,
          openSliceTS: undefined
        };
        this.threadsByLinuxPid[pid] = thread;
      }
      return this.kernelThreadStates_[key];
    },

    /**
     * @return {TimelineThread} A pseudo thread corresponding to the
     * threadName.  Pseudo threads are for events that we want to break
     * out to a separate timeline but would not otherwise happen.
     * These threads are assigned to pseudoKernelPID and given a
     * unique (incrementing) TID.
     */
    getOrCreatePseudoThread: function(threadName) {
      var thread = this.kernelThreadStates_[threadName];
      if (!thread) {
        thread = this.getOrCreateKernelThread(threadName, pseudoKernelPID,
            this.pseudoThreadCounter);
        this.pseudoThreadCounter++;
      }
      return thread;
    },

    /**
     * Imports the data in this.events_ into model_.
     */
    importEvents: function(isSecondaryImport) {
      this.parsers_ = this.createParsers_();
      this.registerDefaultHandlers_();
      this.parseLines();
      this.importClockSyncRecords();
      var timeShift = this.computeTimeTransform();
      if (timeShift === undefined) {
        this.model_.importWarning({
          type: 'clock_sync',
          message: 'Cannot import kernel trace without a clock sync.'
        });
        return;
      }
      this.shiftNewlyAddedClockSyncRecords(timeShift);
      this.importCpuData(timeShift);
      this.buildMapFromLinuxPidsToThreads();
      this.buildPerThreadCpuSlicesFromCpuState();
      this.computeCpuTimestampsForSlicesAsNeeded();
    },

    /**
     * Builds the timeSlices array on each thread based on our knowledge of what
     * each Cpu is doing.  This is done only for Threads that are
     * already in the model, on the assumption that not having any traced data
     * on a thread means that it is not of interest to the user.
     */
    buildPerThreadCpuSlicesFromCpuState: function() {
      var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;

      // Push the cpu slices to the threads that they run on.
      for (var cpuNumber in this.model_.kernel.cpus) {
        var cpu = this.model_.kernel.cpus[cpuNumber];

        for (var i = 0; i < cpu.slices.length; i++) {
          var cpuSlice = cpu.slices[i];

          var thread = this.threadsByLinuxPid[cpuSlice.args.tid];
          if (!thread)
            continue;

          cpuSlice.threadThatWasRunning = thread;

          if (!thread.tempCpuSlices)
            thread.tempCpuSlices = [];
          thread.tempCpuSlices.push(cpuSlice);
        }
      }

      for (var i in this.wakeups_) {
        var wakeup = this.wakeups_[i];
        var thread = this.threadsByLinuxPid[wakeup.tid];
        if (!thread)
          continue;
        thread.tempWakeups = thread.tempWakeups || [];
        thread.tempWakeups.push(wakeup);
      }

      // Create slices for when the thread is not running.
      this.model_.getAllThreads().forEach(function(thread) {
        if (thread.tempCpuSlices === undefined)
          return;
        var origSlices = thread.tempCpuSlices;
        delete thread.tempCpuSlices;

        origSlices.sort(function(x, y) {
          return x.start - y.start;
        });

        var wakeups = thread.tempWakeups || [];
        delete thread.tempWakeups;
        wakeups.sort(function(x, y) {
          return x.ts - y.ts;
        });

        // Walk the slice list and put slices between each original slice to
        // show when the thread isn't running.
        var slices = [];

        if (origSlices.length) {
          var slice = origSlices[0];

          if (wakeups.length && wakeups[0].ts < slice.start) {
            var wakeup = wakeups.shift();
            var wakeupDuration = slice.start - wakeup.ts;
            var args = {'wakeup from tid': wakeup.fromTid};
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.RUNNABLE, '',
                wakeup.ts, args, wakeupDuration));
          }

          var runningSlice = new tr.model.ThreadTimeSlice(
              thread, SCHEDULING_STATE.RUNNING, '',
              slice.start, {}, slice.duration);
          runningSlice.cpuOnWhichThreadWasRunning = slice.cpu;
          slices.push(runningSlice);
        }

        var wakeup = undefined;
        for (var i = 1; i < origSlices.length; i++) {
          var prevSlice = origSlices[i - 1];
          var nextSlice = origSlices[i];
          var midDuration = nextSlice.start - prevSlice.end;
          while (wakeups.length && wakeups[0].ts < nextSlice.start) {
            var w = wakeups.shift();
            if (wakeup === undefined && w.ts > prevSlice.end) {
              wakeup = w;
            }
          }

          // Push a sleep slice onto the slices list, interrupting it with a
          // wakeup if appropriate.
          var pushSleep = function(state) {
            if (wakeup !== undefined) {
              midDuration = wakeup.ts - prevSlice.end;
            }
            slices.push(new tr.model.ThreadTimeSlice(
                thread,
                state, '', prevSlice.end, {}, midDuration));
            if (wakeup !== undefined) {
              var wakeupDuration = nextSlice.start - wakeup.ts;
              var args = {'wakeup from tid': wakeup.fromTid};
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.RUNNABLE, '',
                  wakeup.ts, args, wakeupDuration));
              wakeup = undefined;
            }
          };

          if (prevSlice.args.stateWhenDescheduled == 'S') {
            pushSleep(SCHEDULING_STATE.SLEEPING);
          } else if (prevSlice.args.stateWhenDescheduled == 'R' ||
                     prevSlice.args.stateWhenDescheduled == 'R+') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.RUNNABLE, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'D') {
            pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);
          } else if (prevSlice.args.stateWhenDescheduled == 'T') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.STOPPED, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 't') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.DEBUG, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'Z') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.ZOMBIE, '', ioWaitId,
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'X') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.EXIT_DEAD, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'x') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.TASK_DEAD, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'K') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.WAKE_KILL, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'W') {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.WAKING, '',
                prevSlice.end, {}, midDuration));
          } else if (prevSlice.args.stateWhenDescheduled == 'D|K') {
            pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);
          } else if (prevSlice.args.stateWhenDescheduled == 'D|W') {
            pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);
          } else {
            slices.push(new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.UNKNOWN, '',
                prevSlice.end, {}, midDuration));
            this.model_.importWarning({
              type: 'parse_error',
              message: 'Unrecognized sleep state: ' +
                  prevSlice.args.stateWhenDescheduled
            });
          }

          var runningSlice = new tr.model.ThreadTimeSlice(
              thread, SCHEDULING_STATE.RUNNING, '',
              nextSlice.start, {}, nextSlice.duration);
          runningSlice.cpuOnWhichThreadWasRunning = prevSlice.cpu;
          slices.push(runningSlice);
        }
        thread.timeSlices = slices;
      }, this);
    },

    computeCpuTimestampsForSlicesAsNeeded: function() {
      /* iterate all slices and try to figure out cpuStart/endTimes */

    },

    /**
     * Computes a time transform from perf time to parent time based on the
     * imported clock sync records.
     * @return {number} offset from perf time to parent time or undefined if
     * the necessary sync records were not found.
     */
    computeTimeTransform: function() {
      var isSecondaryImport = this.model.getClockSyncRecordsNamed(
          'ftrace_importer').length !== 0;

      var mSyncs = this.model_.getClockSyncRecordsNamed('monotonic');
      // If this is a secondary import, and no clock syncing records were
      // found, then abort the import. Otherwise, just skip clock alignment.
      if (mSyncs.length == 0)
        return isSecondaryImport ? undefined : 0;

      // Shift all the slice times based on the sync record.
      // TODO(skyostil): Compute a scaling factor if we have multiple clock sync
      // records.
      var sync = mSyncs[0].args;
      // NB: parentTS of zero denotes no times-shift; this is
      // used when user and kernel event clocks are identical.
      if (sync.parentTS == 0 || sync.parentTS == sync.perfTS)
        return 0;
      return sync.parentTS - sync.perfTS;
    },

    /**
     * Creates an instance of each registered linux perf event parser.
     * This allows the parsers to register handlers for the events they
     * understand.  We also register our own special handlers (for the
     * timestamp synchronization markers).
     */
    createParsers_: function() {
      // Instantiate the parsers; this will register handlers for known events
      var allTypeInfos = tr.e.importer.linux_perf.
          Parser.getAllRegisteredTypeInfos();
      var parsers = allTypeInfos.map(
          function(typeInfo) {
            return new typeInfo.constructor(this);
          }, this);

      return parsers;
    },

    registerDefaultHandlers_: function() {
      this.registerEventHandler('tracing_mark_write',
          LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));
      // NB: old-style trace markers; deprecated
      this.registerEventHandler('0',
          LinuxPerfImporter.prototype.traceMarkingWriteEvent.bind(this));
      // Register dummy clock sync handlers to avoid warnings in the log.
      this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',
          function() { return true; });
      this.registerEventHandler('0:trace_event_clock_sync',
          function() { return true; });
    },

    /**
     * Registers a linux perf event parser used by importCpuData.
     */
    registerEventHandler: function(eventName, handler) {
      // TODO(sleffler) how to handle conflicts?
      this.eventHandlers_[eventName] = handler;
    },

    /**
     * Records the fact that a pid has become runnable. This data will
     * eventually get used to derive each thread's timeSlices array.
     */
    markPidRunnable: function(ts, pid, comm, prio, fromPid) {
      // The the pids that get passed in to this function are Linux kernel
      // pids, which identify threads.  The rest of trace-viewer refers to
      // these as tids, so the change of nomenclature happens in the following
      // construction of the wakeup object.
      this.wakeups_.push({ts: ts, tid: pid, fromTid: fromPid});
    },

    /**
     * Processes a trace_event_clock_sync event.
     */
    traceClockSyncEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
      // Check for new-style clock sync records.
      var event = /name=(\w+?)\s(.+)/.exec(eventBase.details);
      if (event) {
        var name = event[1];
        var pieces = event[2].split(' ');
        var args = {
          perfTS: ts
        };
        for (var i = 0; i < pieces.length; i++) {
          var parts = pieces[i].split('=');
          if (parts.length != 2)
            throw new Error('omgbbq');
          args[parts[0]] = parts[1];
        }
        this.addClockSyncRecord(new ClockSyncRecord(name, ts, args));
        return true;
      }

      // Old-style clock sync records from chromium
      event = /parent_ts=(\d+\.?\d*)/.exec(eventBase.details);
      if (!event)
        return false;

      this.addClockSyncRecord(new ClockSyncRecord('monotonic', ts, {
        perfTS: ts,
        parentTS: event[1] * 1000
      }));
      return true;
    },

    /**
     * Processes a trace_marking_write event.
     */
    traceMarkingWriteEvent: function(eventName, cpuNumber, pid, ts, eventBase,
                                     threadName) {

      // Some profiles end up with a \n\ on the end of each line. Strip it
      // before we do the comparisons.
      eventBase.details = eventBase.details.replace(/\\n.*$/, '');

      var event = /^\s*(\w+):\s*(.*)$/.exec(eventBase.details);
      if (!event) {
        // Check if the event matches events traced by the Android framework
        var tag = eventBase.details.substring(0, 2);
        if (tag == 'B|' || tag == 'E' || tag == 'E|' || tag == 'X|' ||
            tag == 'C|' || tag == 'S|' || tag == 'F|') {
          eventBase.subEventName = 'android';
        } else {
          return false;
        }
      } else {
        eventBase.subEventName = event[1];
        eventBase.details = event[2];
      }

      var writeEventName = eventName + ':' + eventBase.subEventName;
      var handler = this.eventHandlers_[writeEventName];
      if (!handler) {
        this.model_.importWarning({
          type: 'parse_error',
          message: 'Unknown trace_marking_write event ' + writeEventName
        });
        return true;
      }
      return handler(writeEventName, cpuNumber, pid, ts, eventBase, threadName);
    },

    /**
     * Populates model clockSyncRecords with found clock sync markers.
     */
    importClockSyncRecords: function() {
      this.forEachLine(function(text, eventBase, cpuNumber, pid, ts) {
        var eventName = eventBase.eventName;
        if (eventName !== 'tracing_mark_write' && eventName !== '0')
          return;
        if (traceEventClockSyncRE.exec(eventBase.details))
          this.traceClockSyncEvent(eventName, cpuNumber, pid, ts, eventBase);
        if (genericClockSyncRE.exec(eventBase.details))
          this.traceClockSyncEvent(eventName, cpuNumber, pid, ts, eventBase);
      }.bind(this));
    },
    addClockSyncRecord: function(csr) {
      this.newlyAddedClockSyncRecords_.push(csr);
      this.model_.clockSyncRecords.push(csr);
    },

    shiftNewlyAddedClockSyncRecords: function(timeShift) {
      this.newlyAddedClockSyncRecords_.forEach(function(csr) {
        csr.ts += timeShift;
      });
    },

    /**
     * Walks the this.events_ structure and creates Cpu objects.
     */
    importCpuData: function(timeShift) {
      this.forEachLine(function(text, eventBase, cpuNumber, pid, ts) {
        var eventName = eventBase.eventName;
        var handler = this.eventHandlers_[eventName];
        if (!handler) {
          this.model_.importWarning({
            type: 'parse_error',
            message: 'Unknown event ' + eventName + ' (' + text + ')'
          });
          return;
        }
        ts += timeShift;
        if (!handler(eventName, cpuNumber, pid, ts, eventBase)) {
          this.model_.importWarning({
            type: 'parse_error',
            message: 'Malformed ' + eventName + ' event (' + text + ')'
          });
        }
      }.bind(this));
    },

    /**
     * Walks the this.events_ structure and populates this.lines_.
     */
    parseLines: function() {
      var lines = [];
      var extractResult = LinuxPerfImporter._extractEventsFromSystraceHTML(
          this.events_, true);
      if (!extractResult.ok)
        extractResult = LinuxPerfImporter._extractEventsFromSystraceMultiHTML(
            this.events_, true);
      var lines = extractResult.ok ?
        extractResult.lines : this.events_.split('\n');

      var lineParser = null;
      for (var lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
        var line = lines[lineNumber].trim();
        if (line.length == 0 || /^#/.test(line))
          continue;
        if (lineParser == null) {
          lineParser = autoDetectLineParser(line);
          if (lineParser == null) {
            this.model_.importWarning({
              type: 'parse_error',
              message: 'Cannot parse line: ' + line
            });
            continue;
          }
        }
        var eventBase = lineParser(line);
        if (!eventBase) {
          this.model_.importWarning({
            type: 'parse_error',
            message: 'Unrecognized line: ' + line
          });
          continue;
        }

        this.lines_.push([
          line,
          eventBase,
          parseInt(eventBase.cpuNumber),
          parseInt(eventBase.pid),
          parseFloat(eventBase.timestamp) * 1000
        ]);
      }
    },

    /**
     * Calls |handler| for every parsed line.
     */
    forEachLine: function(handler) {
      for (var i = 0; i < this.lines_.length; ++i) {
        var line = this.lines_[i];
        handler.apply(this, line);
      }
    }
  };

  tr.importer.Importer.register(LinuxPerfImporter);

  return {
    LinuxPerfImporter: LinuxPerfImporter,
    _LinuxPerfImporterTestExports: TestExports
  };
});
</script>
