1// Copyright (c) 2013 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 ObjectCollection class. 9 */ 10base.require('base.utils'); 11base.require('base.range'); 12base.require('base.sorted_array_utils'); 13base.require('tracing.trace_model.object_instance'); 14base.require('tracing.trace_model.time_to_object_instance_map'); 15 16base.exportTo('tracing.trace_model', function() { 17 var ObjectInstance = tracing.trace_model.ObjectInstance; 18 19 /** 20 * A collection of object instances and their snapshots, accessible by id and 21 * time, or by object name. 22 * 23 * @constructor 24 */ 25 function ObjectCollection(parent) { 26 this.parent = parent; 27 this.bounds = new base.Range(); 28 this.instanceMapsById_ = {}; // id -> TimeToObjectInstanceMap 29 this.instancesByTypeName_ = {}; 30 this.createObjectInstance_ = this.createObjectInstance_.bind(this); 31 } 32 33 ObjectCollection.prototype = { 34 __proto__: Object.prototype, 35 36 createObjectInstance_: function(parent, id, category, name, creationTs) { 37 var constructor = tracing.trace_model.ObjectInstance.getConstructor(name); 38 var instance = new constructor(parent, id, category, name, creationTs); 39 var typeName = instance.typeName; 40 var instancesOfTypeName = this.instancesByTypeName_[typeName]; 41 if (!instancesOfTypeName) { 42 instancesOfTypeName = []; 43 this.instancesByTypeName_[typeName] = instancesOfTypeName; 44 } 45 instancesOfTypeName.push(instance); 46 return instance; 47 }, 48 49 getOrCreateInstanceMap_: function(id) { 50 var instanceMap = this.instanceMapsById_[id]; 51 if (instanceMap) 52 return instanceMap; 53 instanceMap = new tracing.trace_model.TimeToObjectInstanceMap( 54 this.createObjectInstance_, this.parent, id); 55 this.instanceMapsById_[id] = instanceMap; 56 return instanceMap; 57 }, 58 59 idWasCreated: function(id, category, name, ts) { 60 var instanceMap = this.getOrCreateInstanceMap_(id); 61 return instanceMap.idWasCreated(category, name, ts); 62 }, 63 64 addSnapshot: function(id, category, name, ts, args) { 65 var instanceMap = this.getOrCreateInstanceMap_(id, category, name, ts); 66 var snapshot = instanceMap.addSnapshot(category, name, ts, args); 67 if (snapshot.objectInstance.category != category) { 68 throw new Error('Added snapshot with different category ' + 69 'than when it was created'); 70 } 71 if (snapshot.objectInstance.name != name) { 72 throw new Error('Added snapshot with different name than ' + 73 'when it was created'); 74 } 75 return snapshot; 76 }, 77 78 idWasDeleted: function(id, category, name, ts) { 79 var instanceMap = this.getOrCreateInstanceMap_(id, category, name, ts); 80 var deletedInstance = instanceMap.idWasDeleted(category, name, ts); 81 if (!deletedInstance) 82 return; 83 if (deletedInstance.category != category) { 84 throw new Error('Deleting an object with a different category ' + 85 'than when it was created'); 86 } 87 if (deletedInstance.name != name) { 88 throw new Error('Deleting an object with a different name than ' + 89 'when it was created'); 90 } 91 }, 92 93 autoDeleteObjects: function(maxTimestamp) { 94 base.iterItems(this.instanceMapsById_, function(id, i2imap) { 95 var lastInstance = i2imap.lastInstance; 96 if (lastInstance.deletionTs != Number.MAX_VALUE) 97 return; 98 i2imap.idWasDeleted( 99 lastInstance.category, lastInstance.name, maxTimestamp); 100 // idWasDeleted will cause lastInstance.deletionTsWasExplicit to be set 101 // to true. Unset it here. 102 lastInstance.deletionTsWasExplicit = false; 103 }); 104 }, 105 106 getObjectInstanceAt: function(id, ts) { 107 var instanceMap = this.instanceMapsById_[id]; 108 if (!instanceMap) 109 return undefined; 110 return instanceMap.getInstanceAt(ts); 111 }, 112 113 getSnapshotAt: function(id, ts) { 114 var instance = this.getObjectInstanceAt(id, ts); 115 if (!instance) 116 return undefined; 117 return instance.getSnapshotAt(ts); 118 }, 119 120 iterObjectInstances: function(iter, opt_this) { 121 opt_this = opt_this || this; 122 base.iterItems(this.instanceMapsById_, function(id, i2imap) { 123 i2imap.instances.forEach(iter, opt_this); 124 }); 125 }, 126 127 getAllObjectInstances: function() { 128 var instances = []; 129 this.iterObjectInstances(function(i) { instances.push(i); }); 130 return instances; 131 }, 132 133 getAllInstancesNamed: function(name) { 134 return this.instancesByTypeName_[name]; 135 }, 136 137 getAllInstancesByTypeName: function() { 138 return this.instancesByTypeName_; 139 }, 140 141 preInitializeAllObjects: function() { 142 this.iterObjectInstances(function(instance) { 143 instance.preInitialize(); 144 }); 145 }, 146 147 initializeAllObjects: function() { 148 this.iterObjectInstances(function(instance) { 149 instance.initialize(); 150 }); 151 }, 152 153 initializeInstances: function() { 154 this.iterObjectInstances(function(instance) { 155 instance.initialize(); 156 }); 157 }, 158 159 updateBounds: function() { 160 this.bounds.reset(); 161 this.iterObjectInstances(function(instance) { 162 instance.updateBounds(); 163 this.bounds.addRange(instance.bounds); 164 }, this); 165 }, 166 167 shiftTimestampsForward: function(amount) { 168 this.iterObjectInstances(function(instance) { 169 instance.shiftTimestampsForward(amount); 170 }); 171 }, 172 173 addCategoriesToDict: function(categoriesDict) { 174 this.iterObjectInstances(function(instance) { 175 categoriesDict[instance.category] = true; 176 }); 177 }, 178 179 toJSON: function() { 180 // TODO(nduca): Implement this if we need it. 181 return {}; 182 } 183 }; 184 185 return { 186 ObjectCollection: ObjectCollection 187 }; 188}); 189