<!DOCTYPE html>
<!--
Copyright (c) 2013 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="/base/range.html">
<link rel="import" href="/model/counter.html">
<link rel="import" href="/model/cpu_slice.html">
<link rel="import" href="/model/thread_time_slice.html">

<script>
'use strict';

/**
 * @fileoverview Provides the Cpu class.
 */
tr.exportTo('tr.model', function() {

  var Counter = tr.model.Counter;
  var Slice = tr.model.Slice;
  var CpuSlice = tr.model.CpuSlice;

  /**
   * The Cpu represents a Cpu from the kernel's point of view.
   * @constructor
   */
  function Cpu(kernel, number) {
    if (kernel === undefined || number === undefined)
      throw new Error('Missing arguments');
    this.kernel = kernel;
    this.cpuNumber = number;
    this.slices = [];
    this.counters = {};
    this.bounds = new tr.b.Range();
    this.samples_ = undefined; // Set during createSubSlices

    // Start timestamp of the last active thread.
    this.lastActiveTimestamp_ = undefined;

    // Identifier of the last active thread. On Linux, it's a pid while on
    // Windows it's a thread id.
    this.lastActiveThread_ = undefined;

    // Name and arguments of the last active thread.
    this.lastActiveName_ = undefined;
    this.lastActiveArgs_ = undefined;
  };

  Cpu.prototype = {
    iterateAllEventsInThisContainer: function(eventTypePredicate,
                                              callback, opt_this) {
      if (eventTypePredicate.call(opt_this, tr.model.CpuSlice))
        this.slices.forEach(callback, opt_this);

      if (this.samples_) {
        if (eventTypePredicate.call(opt_this, tr.model.Sample))
          this.samples_.forEach(callback, opt_this);
      }
    },

    iterateAllChildEventContainers: function(callback, opt_this) {
      for (var id in this.counters)
        callback.call(opt_this, this.counters[id]);
    },

    /**
     * @return {Counter} The counter on this CPU with the given category/name
     * combination, creating it if it doesn't exist.
     */
    getOrCreateCounter: function(cat, name) {
      var id = cat + '.' + name;
      if (!this.counters[id])
        this.counters[id] = new Counter(this, id, cat, name);
      return this.counters[id];
    },

    /**
     * Shifts all the timestamps inside this CPU forward by the amount
     * specified.
     */
    shiftTimestampsForward: function(amount) {
      for (var sI = 0; sI < this.slices.length; sI++)
        this.slices[sI].start = (this.slices[sI].start + amount);
      for (var id in this.counters)
        this.counters[id].shiftTimestampsForward(amount);
    },

    /**
     * Updates the range based on the current slices attached to the cpu.
     */
    updateBounds: function() {
      this.bounds.reset();
      if (this.slices.length) {
        this.bounds.addValue(this.slices[0].start);
        this.bounds.addValue(this.slices[this.slices.length - 1].end);
      }
      for (var id in this.counters) {
        this.counters[id].updateBounds();
        this.bounds.addRange(this.counters[id].bounds);
      }
      if (this.samples_ && this.samples_.length) {
        this.bounds.addValue(this.samples_[0].start);
        this.bounds.addValue(
            this.samples_[this.samples_.length - 1].end);
      }
    },

    createSubSlices: function() {
      this.samples_ = this.kernel.model.samples.filter(function(sample) {
        return sample.cpu == this;
      }, this);
    },

    addCategoriesToDict: function(categoriesDict) {
      for (var i = 0; i < this.slices.length; i++)
        categoriesDict[this.slices[i].category] = true;
      for (var id in this.counters)
        categoriesDict[this.counters[id].category] = true;
      for (var i = 0; i < this.samples_.length; i++)
        categoriesDict[this.samples_[i].category] = true;
    },

    get userFriendlyName() {
      return 'CPU ' + this.cpuNumber;
    },

    /*
     * Returns the index of the slice in the CPU's slices, or undefined.
     */
    indexOf: function(cpuSlice) {
      var i = tr.b.findLowIndexInSortedArray(
          this.slices,
          function(slice) { return slice.start; },
          cpuSlice.start);
      if (this.slices[i] !== cpuSlice)
        return undefined;
      return i;
    },

    /**
     * Closes the thread running on the CPU. |end_timestamp| is the timestamp
     * at which the thread was unscheduled. |args| is merged with the arguments
     * specified when the thread was initially scheduled.
     */
    closeActiveThread: function(end_timestamp, args) {
      // Don't generate a slice if the last active thread is the idle task.
      if (this.lastActiveThread_ == undefined || this.lastActiveThread_ == 0)
        return;

      if (end_timestamp < this.lastActiveTimestamp_) {
        throw new Error('The end timestamp of a thread running on CPU ' +
                        this.cpuNumber + ' is before its start timestamp.');
      }

      // Merge |args| with |this.lastActiveArgs_|. If a key is in both
      // dictionaries, the value from |args| is used.
      for (var key in args) {
        this.lastActiveArgs_[key] = args[key];
      }

      var duration = end_timestamp - this.lastActiveTimestamp_;
      var slice = new tr.model.CpuSlice(
          '', this.lastActiveName_,
          tr.ui.b.getColorIdForGeneralPurposeString(this.lastActiveName_),
          this.lastActiveTimestamp_,
          this.lastActiveArgs_,
          duration);
      slice.cpu = this;
      this.slices.push(slice);

      // Clear the last state.
      this.lastActiveTimestamp_ = undefined;
      this.lastActiveThread_ = undefined;
      this.lastActiveName_ = undefined;
      this.lastActiveArgs_ = undefined;
    },

    switchActiveThread: function(timestamp, old_thread_args, new_thread_id,
                                 new_thread_name, new_thread_args) {
      // Close the previous active thread and generate a slice.
      this.closeActiveThread(timestamp, old_thread_args);

      // Keep track of the new thread.
      this.lastActiveTimestamp_ = timestamp;
      this.lastActiveThread_ = new_thread_id;
      this.lastActiveName_ = new_thread_name;
      this.lastActiveArgs_ = new_thread_args;
    },

    get samples() {
      return this.samples_;
    }
  };

  /**
   * Comparison between processes that orders by cpuNumber.
   */
  Cpu.compare = function(x, y) {
    return x.cpuNumber - y.cpuNumber;
  };


  return {
    Cpu: Cpu
  };
});
</script>
