// 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.
'use strict';
/**
* @fileoverview Provides the ObjectCollection class.
*/
base.require('base.utils');
base.require('base.range');
base.require('base.sorted_array_utils');
base.require('tracing.trace_model.object_instance');
base.require('tracing.trace_model.time_to_object_instance_map');
base.exportTo('tracing.trace_model', function() {
var ObjectInstance = tracing.trace_model.ObjectInstance;
/**
* A collection of object instances and their snapshots, accessible by id and
* time, or by object name.
*
* @constructor
*/
function ObjectCollection(parent) {
this.parent = parent;
this.bounds = new base.Range();
this.instanceMapsById_ = {}; // id -> TimeToObjectInstanceMap
this.instancesByTypeName_ = {};
this.createObjectInstance_ = this.createObjectInstance_.bind(this);
}
ObjectCollection.prototype = {
__proto__: Object.prototype,
createObjectInstance_: function(parent, id, category, name, creationTs) {
var constructor = tracing.trace_model.ObjectInstance.getConstructor(name);
var instance = new constructor(parent, id, category, name, creationTs);
var typeName = instance.typeName;
var instancesOfTypeName = this.instancesByTypeName_[typeName];
if (!instancesOfTypeName) {
instancesOfTypeName = [];
this.instancesByTypeName_[typeName] = instancesOfTypeName;
}
instancesOfTypeName.push(instance);
return instance;
},
getOrCreateInstanceMap_: function(id) {
var instanceMap = this.instanceMapsById_[id];
if (instanceMap)
return instanceMap;
instanceMap = new tracing.trace_model.TimeToObjectInstanceMap(
this.createObjectInstance_, this.parent, id);
this.instanceMapsById_[id] = instanceMap;
return instanceMap;
},
idWasCreated: function(id, category, name, ts) {
var instanceMap = this.getOrCreateInstanceMap_(id);
return instanceMap.idWasCreated(category, name, ts);
},
addSnapshot: function(id, category, name, ts, args) {
var instanceMap = this.getOrCreateInstanceMap_(id, category, name, ts);
var snapshot = instanceMap.addSnapshot(category, name, ts, args);
if (snapshot.objectInstance.category != category) {
throw new Error('Added snapshot with different category ' +
'than when it was created');
}
if (snapshot.objectInstance.name != name) {
throw new Error('Added snapshot with different name than ' +
'when it was created');
}
return snapshot;
},
idWasDeleted: function(id, category, name, ts) {
var instanceMap = this.getOrCreateInstanceMap_(id, category, name, ts);
var deletedInstance = instanceMap.idWasDeleted(category, name, ts);
if (!deletedInstance)
return;
if (deletedInstance.category != category) {
throw new Error('Deleting an object with a different category ' +
'than when it was created');
}
if (deletedInstance.name != name) {
throw new Error('Deleting an object with a different name than ' +
'when it was created');
}
},
autoDeleteObjects: function(maxTimestamp) {
base.iterItems(this.instanceMapsById_, function(id, i2imap) {
var lastInstance = i2imap.lastInstance;
if (lastInstance.deletionTs != Number.MAX_VALUE)
return;
i2imap.idWasDeleted(
lastInstance.category, lastInstance.name, maxTimestamp);
// idWasDeleted will cause lastInstance.deletionTsWasExplicit to be set
// to true. Unset it here.
lastInstance.deletionTsWasExplicit = false;
});
},
getObjectInstanceAt: function(id, ts) {
var instanceMap = this.instanceMapsById_[id];
if (!instanceMap)
return undefined;
return instanceMap.getInstanceAt(ts);
},
getSnapshotAt: function(id, ts) {
var instance = this.getObjectInstanceAt(id, ts);
if (!instance)
return undefined;
return instance.getSnapshotAt(ts);
},
iterObjectInstances: function(iter, opt_this) {
opt_this = opt_this || this;
base.iterItems(this.instanceMapsById_, function(id, i2imap) {
i2imap.instances.forEach(iter, opt_this);
});
},
getAllObjectInstances: function() {
var instances = [];
this.iterObjectInstances(function(i) { instances.push(i); });
return instances;
},
getAllInstancesNamed: function(name) {
return this.instancesByTypeName_[name];
},
getAllInstancesByTypeName: function() {
return this.instancesByTypeName_;
},
preInitializeAllObjects: function() {
this.iterObjectInstances(function(instance) {
instance.preInitialize();
});
},
initializeAllObjects: function() {
this.iterObjectInstances(function(instance) {
instance.initialize();
});
},
initializeInstances: function() {
this.iterObjectInstances(function(instance) {
instance.initialize();
});
},
updateBounds: function() {
this.bounds.reset();
this.iterObjectInstances(function(instance) {
instance.updateBounds();
this.bounds.addRange(instance.bounds);
}, this);
},
shiftTimestampsForward: function(amount) {
this.iterObjectInstances(function(instance) {
instance.shiftTimestampsForward(amount);
});
},
addCategoriesToDict: function(categoriesDict) {
this.iterObjectInstances(function(instance) {
categoriesDict[instance.category] = true;
});
},
toJSON: function() {
// TODO(nduca): Implement this if we need it.
return {};
}
};
return {
ObjectCollection: ObjectCollection
};
});