1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7/**
8 * @fileoverview Provides the ProcessBase class.
9 */
10base.require('base.guid');
11base.require('base.range');
12base.require('tracing.trace_model.counter');
13base.require('tracing.trace_model.object_collection');
14base.require('tracing.trace_model.thread');
15base.require('tracing.trace_model_settings');
16base.exportTo('tracing.trace_model', function() {
17
18  var Thread = tracing.trace_model.Thread;
19  var Counter = tracing.trace_model.Counter;
20
21  /**
22   * The ProcessBase is an partial base class, upon which Kernel
23   * and Process are built.
24   *
25   * @constructor
26   */
27  function ProcessBase(model) {
28    if (!model)
29      throw new Error('Must provide a model');
30    this.guid_ = base.GUID.allocate();
31    this.model = model;
32    this.threads = {};
33    this.counters = {};
34    this.objects = new tracing.trace_model.ObjectCollection(this);
35    this.bounds = new base.Range();
36    this.sortIndex = 0;
37    this.ephemeralSettings = {};
38  };
39
40  ProcessBase.compare = function(x, y) {
41    return x.sortIndex - y.sortIndex;
42  };
43
44  ProcessBase.prototype = {
45    /*
46     * @return {Number} A globally unique identifier for this counter.
47     */
48    get guid() {
49      return this.guid_;
50    },
51
52    /**
53     * Gets the number of threads in this process.
54     */
55    get numThreads() {
56      var n = 0;
57      for (var p in this.threads) {
58        n++;
59      }
60      return n;
61    },
62
63    toJSON: function() {
64      var obj = new Object();
65      var keys = Object.keys(this);
66      for (var i = 0; i < keys.length; i++) {
67        var key = keys[i];
68        if (typeof this[key] == 'function')
69          continue;
70        if (key == 'model')
71          continue;
72        obj[key] = this[key];
73      }
74      return obj;
75    },
76
77    /**
78     * Shifts all the timestamps inside this process forward by the amount
79     * specified.
80     */
81    shiftTimestampsForward: function(amount) {
82      for (var tid in this.threads)
83        this.threads[tid].shiftTimestampsForward(amount);
84      for (var id in this.counters)
85        this.counters[id].shiftTimestampsForward(amount);
86      this.objects.shiftTimestampsForward(amount);
87    },
88
89    /**
90     * Closes any open slices.
91     */
92    autoCloseOpenSlices: function(opt_maxTimestamp) {
93      for (var tid in this.threads) {
94        var thread = this.threads[tid];
95        thread.autoCloseOpenSlices(opt_maxTimestamp);
96      }
97    },
98
99    autoDeleteObjects: function(maxTimestamp) {
100      this.objects.autoDeleteObjects(maxTimestamp);
101    },
102
103    /**
104     * Called by the model after finalizing imports,
105     * but before joining refs.
106     */
107    preInitializeObjects: function() {
108      this.objects.preInitializeAllObjects();
109    },
110
111    /**
112     * Called by the model after joining refs.
113     */
114    initializeObjects: function() {
115      this.objects.initializeAllObjects();
116    },
117
118    /**
119     * Merge slices from the kernel with those from userland for each thread.
120     */
121    mergeKernelWithUserland: function() {
122      for (var tid in this.threads) {
123        var thread = this.threads[tid];
124        thread.mergeKernelWithUserland();
125      }
126    },
127
128    updateBounds: function() {
129      this.bounds.reset();
130      for (var tid in this.threads) {
131        this.threads[tid].updateBounds();
132        this.bounds.addRange(this.threads[tid].bounds);
133      }
134      for (var id in this.counters) {
135        this.counters[id].updateBounds();
136        this.bounds.addRange(this.counters[id].bounds);
137      }
138      this.objects.updateBounds();
139      this.bounds.addRange(this.objects.bounds);
140    },
141
142    addCategoriesToDict: function(categoriesDict) {
143      for (var tid in this.threads)
144        this.threads[tid].addCategoriesToDict(categoriesDict);
145      for (var id in this.counters)
146        categoriesDict[this.counters[id].category] = true;
147      this.objects.addCategoriesToDict(categoriesDict);
148    },
149
150    /**
151     * @param {String} The name of the thread to find.
152     * @return {Array} An array of all the matched threads.
153     */
154    findAllThreadsNamed: function(name) {
155      var namedThreads = [];
156      for (var tid in this.threads) {
157        var thread = this.threads[tid];
158        if (thread.name == name)
159          namedThreads.push(thread);
160      }
161      return namedThreads;
162    },
163
164    /**
165     * Removes threads from the process that are fully empty.
166     */
167    pruneEmptyContainers: function() {
168      var threadsToKeep = {};
169      for (var tid in this.threads) {
170        var thread = this.threads[tid];
171        if (!thread.isEmpty)
172          threadsToKeep[tid] = thread;
173      }
174      this.threads = threadsToKeep;
175    },
176
177    /**
178     * @return {TimlineThread} The thread identified by tid on this process,
179     * creating it if it doesn't exist.
180     */
181    getOrCreateThread: function(tid) {
182      if (!this.threads[tid])
183        this.threads[tid] = new Thread(this, tid);
184      return this.threads[tid];
185    },
186
187    /**
188     * @return {TimlineCounter} The counter on this process named 'name',
189     * creating it if it doesn't exist.
190     */
191    getOrCreateCounter: function(cat, name) {
192      var id = cat + '.' + name;
193      if (!this.counters[id])
194        this.counters[id] = new Counter(this, id, cat, name);
195      return this.counters[id];
196    },
197
198    getSettingsKey: function() {
199      throw new Error('Not implemented');
200    }
201  };
202
203  return {
204    ProcessBase: ProcessBase
205  };
206});
207