1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/base/guid.html">
9<link rel="import" href="/tracing/base/range.html">
10<link rel="import" href="/tracing/model/async_slice.html">
11<link rel="import" href="/tracing/model/event_container.html">
12
13<script>
14'use strict';
15
16/**
17 * @fileoverview Provides the AsyncSliceGroup class.
18 */
19tr.exportTo('tr.model', function() {
20  /**
21   * A group of AsyncSlices associated with a thread.
22   * @constructor
23   * @extends {tr.model.EventContainer}
24   */
25  function AsyncSliceGroup(parentContainer, opt_name) {
26    tr.model.EventContainer.call(this);
27    this.parentContainer_ = parentContainer;
28    this.slices = [];
29    this.name_ = opt_name;
30    this.viewSubGroups_ = undefined;
31  }
32
33  AsyncSliceGroup.prototype = {
34    __proto__: tr.model.EventContainer.prototype,
35
36    get parentContainer() {
37      return this.parentContainer_;
38    },
39
40    get model() {
41      return this.parentContainer_.parent.model;
42    },
43
44    get stableId() {
45      return this.parentContainer_.stableId + '.AsyncSliceGroup';
46    },
47
48    getSettingsKey: function() {
49      if (!this.name_)
50        return undefined;
51      var parentKey = this.parentContainer_.getSettingsKey();
52      if (!parentKey)
53        return undefined;
54      return parentKey + '.' + this.name_;
55    },
56
57    /**
58     * Helper function that pushes the provided slice onto the slices array.
59     */
60    push: function(slice) {
61      slice.parentContainer = this.parentContainer;
62      this.slices.push(slice);
63      return slice;
64    },
65
66    /**
67     * @return {Number} The number of slices in this group.
68     */
69    get length() {
70      return this.slices.length;
71    },
72
73    /**
74     * Shifts all the timestamps inside this group forward by the amount
75     * specified, including all nested subSlices if there are any.
76     */
77    shiftTimestampsForward: function(amount) {
78      for (var sI = 0; sI < this.slices.length; sI++) {
79        var slice = this.slices[sI];
80        slice.start = (slice.start + amount);
81        // Shift all nested subSlices recursively.
82        var shiftSubSlices = function(subSlices) {
83          if (subSlices === undefined || subSlices.length === 0)
84            return;
85          for (var sJ = 0; sJ < subSlices.length; sJ++) {
86            subSlices[sJ].start += amount;
87            shiftSubSlices(subSlices[sJ].subSlices);
88          }
89        };
90        shiftSubSlices(slice.subSlices);
91      }
92    },
93
94    /**
95     * Updates the bounds for this group based on the slices it contains.
96     */
97    updateBounds: function() {
98      this.bounds.reset();
99      for (var i = 0; i < this.slices.length; i++) {
100        this.bounds.addValue(this.slices[i].start);
101        this.bounds.addValue(this.slices[i].end);
102      }
103    },
104
105    /**
106     * Gets the sub-groups in this A-S-G defined by the group titles.
107     *
108     * @return {Array} An array of AsyncSliceGroups where each group has
109     * slices that started on the same thread.
110     */
111    get viewSubGroups() {
112      if (this.viewSubGroups_ === undefined) {
113        var prefix = '';
114        if (this.name !== undefined)
115          prefix = this.name + '.';
116        else
117          prefix = '';
118
119        var subGroupsByTitle = {};
120        for (var i = 0; i < this.slices.length; ++i) {
121          var slice = this.slices[i];
122          var subGroupTitle = slice.viewSubGroupTitle;
123          if (!subGroupsByTitle[subGroupTitle]) {
124            subGroupsByTitle[subGroupTitle] = new AsyncSliceGroup(
125                this.parentContainer_, prefix + subGroupTitle);
126          }
127          subGroupsByTitle[subGroupTitle].push(slice);
128        }
129        this.viewSubGroups_ = tr.b.dictionaryValues(subGroupsByTitle);
130        this.viewSubGroups_.sort(function(a, b) {
131          return a.slices[0].compareTo(b.slices[0]);
132        });
133      }
134      return this.viewSubGroups_;
135    },
136
137    iterateAllEventsInThisContainer: function(eventTypePredicate,
138                                              callback, opt_this) {
139      if (eventTypePredicate.call(opt_this, tr.model.AsyncSlice)) {
140        for (var i = 0; i < this.slices.length; i++) {
141          var slice = this.slices[i];
142          callback.call(opt_this, slice);
143          if (slice.subSlices)
144            slice.subSlices.forEach(callback, opt_this);
145        }
146      }
147    },
148
149    iterateAllChildEventContainers: function(callback, opt_this) {
150    }
151  };
152
153  return {
154    AsyncSliceGroup: AsyncSliceGroup
155  };
156});
157</script>
158