Home | History | Annotate | Download | only in model
      1 <!DOCTYPE html>
      2 <!--
      3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
      4 Use of this source code is governed by a BSD-style license that can be
      5 found in the LICENSE file.
      6 -->
      7 
      8 <link rel="import" href="/tracing/model/event_container.html">
      9 <link rel="import" href="/tracing/model/object_instance.html">
     10 <link rel="import" href="/tracing/model/time_to_object_instance_map.html">
     11 <link rel="import" href="/tracing/base/utils.html">
     12 <link rel="import" href="/tracing/base/range.html">
     13 <link rel="import" href="/tracing/base/sorted_array_utils.html">
     14 
     15 <script>
     16 'use strict';
     17 
     18 /**
     19  * @fileoverview Provides the ObjectCollection class.
     20  */
     21 tr.exportTo('tr.model', function() {
     22   var ObjectInstance = tr.model.ObjectInstance;
     23   var ObjectSnapshot = tr.model.ObjectSnapshot;
     24 
     25   /**
     26    * A collection of object instances and their snapshots, accessible by id and
     27    * time, or by object name.
     28    *
     29    * @constructor
     30    */
     31   function ObjectCollection(parent) {
     32     tr.model.EventContainer.call(this);
     33     this.parent = parent;
     34     // scope -> {id -> TimeToObjectInstanceMap}
     35     this.instanceMapsByScopedId_ = {};
     36     this.instancesByTypeName_ = {};
     37     this.createObjectInstance_ = this.createObjectInstance_.bind(this);
     38   }
     39 
     40   ObjectCollection.prototype = {
     41     __proto__: tr.model.EventContainer.prototype,
     42 
     43     iterateAllChildEventContainers: function(callback, opt_this) {
     44     },
     45 
     46     iterateAllEventsInThisContainer: function(eventTypePredicate,
     47                                               callback, opt_this) {
     48       var bI = !!eventTypePredicate.call(opt_this, ObjectInstance);
     49       var bS = !!eventTypePredicate.call(opt_this, ObjectSnapshot);
     50       if (bI === false && bS === false)
     51         return;
     52       this.iterObjectInstances(function(instance) {
     53         if (bI)
     54           callback.call(opt_this, instance);
     55         if (bS)
     56           instance.snapshots.forEach(callback, opt_this);
     57       }, opt_this);
     58     },
     59 
     60     createObjectInstance_: function(
     61         parent, scopedId, category, name, creationTs, opt_baseTypeName) {
     62       var constructor = tr.model.ObjectInstance.getConstructor(
     63           category, name);
     64       var instance = new constructor(
     65           parent, scopedId, category, name, creationTs, opt_baseTypeName);
     66       var typeName = instance.typeName;
     67       var instancesOfTypeName = this.instancesByTypeName_[typeName];
     68       if (!instancesOfTypeName) {
     69         instancesOfTypeName = [];
     70         this.instancesByTypeName_[typeName] = instancesOfTypeName;
     71       }
     72       instancesOfTypeName.push(instance);
     73       return instance;
     74     },
     75 
     76     getOrCreateInstanceMap_: function(scopedId) {
     77       var dict;
     78       if (scopedId.scope in this.instanceMapsByScopedId_) {
     79         dict = this.instanceMapsByScopedId_[scopedId.scope];
     80       } else {
     81         dict = {};
     82         this.instanceMapsByScopedId_[scopedId.scope] = dict;
     83       }
     84       var instanceMap = dict[scopedId.id];
     85       if (instanceMap)
     86         return instanceMap;
     87       instanceMap = new tr.model.TimeToObjectInstanceMap(
     88           this.createObjectInstance_, this.parent, scopedId);
     89       dict[scopedId.id] = instanceMap;
     90       return instanceMap;
     91     },
     92 
     93     idWasCreated: function(scopedId, category, name, ts) {
     94       var instanceMap = this.getOrCreateInstanceMap_(scopedId);
     95       return instanceMap.idWasCreated(category, name, ts);
     96     },
     97 
     98     addSnapshot: function(
     99         scopedId, category, name, ts, args, opt_baseTypeName) {
    100       var instanceMap = this.getOrCreateInstanceMap_(scopedId);
    101       var snapshot = instanceMap.addSnapshot(
    102           category, name, ts, args, opt_baseTypeName);
    103       if (snapshot.objectInstance.category != category) {
    104         var msg = 'Added snapshot name=' + name + ' with cat=' + category +
    105             ' impossible. It instance was created/snapshotted with cat=' +
    106             snapshot.objectInstance.category + ' name=' +
    107             snapshot.objectInstance.name;
    108         throw new Error(msg);
    109       }
    110       if (opt_baseTypeName &&
    111           snapshot.objectInstance.baseTypeName != opt_baseTypeName) {
    112         throw new Error('Could not add snapshot with baseTypeName=' +
    113                         opt_baseTypeName + '. It ' +
    114                         'was previously created with name=' +
    115                         snapshot.objectInstance.baseTypeName);
    116       }
    117       if (snapshot.objectInstance.name != name) {
    118         throw new Error('Could not add snapshot with name=' + name + '. It ' +
    119                         'was previously created with name=' +
    120                         snapshot.objectInstance.name);
    121       }
    122       return snapshot;
    123     },
    124 
    125     idWasDeleted: function(scopedId, category, name, ts) {
    126       var instanceMap = this.getOrCreateInstanceMap_(scopedId);
    127       var deletedInstance = instanceMap.idWasDeleted(category, name, ts);
    128       if (!deletedInstance)
    129         return;
    130       if (deletedInstance.category != category) {
    131         var msg = 'Deleting object ' + deletedInstance.name +
    132             ' with a different category ' +
    133             'than when it was created. It previous had cat=' +
    134             deletedInstance.category + ' but the delete command ' +
    135             'had cat=' + category;
    136         throw new Error(msg);
    137       }
    138       if (deletedInstance.baseTypeName != name) {
    139         throw new Error('Deletion requested for name=' +
    140                         name + ' could not proceed: ' +
    141                         'An existing object with baseTypeName=' +
    142                         deletedInstance.baseTypeName + ' existed.');
    143       }
    144     },
    145 
    146     autoDeleteObjects: function(maxTimestamp) {
    147       tr.b.iterItems(this.instanceMapsByScopedId_, function(scope, imapById) {
    148         tr.b.iterItems(imapById, function(id, i2imap) {
    149           var lastInstance = i2imap.lastInstance;
    150           if (lastInstance.deletionTs != Number.MAX_VALUE)
    151             return;
    152           i2imap.idWasDeleted(
    153               lastInstance.category, lastInstance.name, maxTimestamp);
    154           // idWasDeleted will cause lastInstance.deletionTsWasExplicit to be
    155           // set to true. Unset it here.
    156           lastInstance.deletionTsWasExplicit = false;
    157         });
    158       });
    159     },
    160 
    161     getObjectInstanceAt: function(scopedId, ts) {
    162       var instanceMap;
    163       if (scopedId.scope in this.instanceMapsByScopedId_)
    164         instanceMap = this.instanceMapsByScopedId_[scopedId.scope][scopedId.id];
    165       if (!instanceMap)
    166         return undefined;
    167       return instanceMap.getInstanceAt(ts);
    168     },
    169 
    170     getSnapshotAt: function(scopedId, ts) {
    171       var instance = this.getObjectInstanceAt(scopedId, ts);
    172       if (!instance)
    173         return undefined;
    174       return instance.getSnapshotAt(ts);
    175     },
    176 
    177     iterObjectInstances: function(iter, opt_this) {
    178       opt_this = opt_this || this;
    179       tr.b.iterItems(this.instanceMapsByScopedId_, function(scope, imapById) {
    180         tr.b.iterItems(imapById, function(id, i2imap) {
    181           i2imap.instances.forEach(iter, opt_this);
    182         });
    183       });
    184     },
    185 
    186     getAllObjectInstances: function() {
    187       var instances = [];
    188       this.iterObjectInstances(function(i) { instances.push(i); });
    189       return instances;
    190     },
    191 
    192     getAllInstancesNamed: function(name) {
    193       return this.instancesByTypeName_[name];
    194     },
    195 
    196     getAllInstancesByTypeName: function() {
    197       return this.instancesByTypeName_;
    198     },
    199 
    200     preInitializeAllObjects: function() {
    201       this.iterObjectInstances(function(instance) {
    202         instance.preInitialize();
    203       });
    204     },
    205 
    206     initializeAllObjects: function() {
    207       this.iterObjectInstances(function(instance) {
    208         instance.initialize();
    209       });
    210     },
    211 
    212     initializeInstances: function() {
    213       this.iterObjectInstances(function(instance) {
    214         instance.initialize();
    215       });
    216     },
    217 
    218     updateBounds: function() {
    219       this.bounds.reset();
    220       this.iterObjectInstances(function(instance) {
    221         instance.updateBounds();
    222         this.bounds.addRange(instance.bounds);
    223       }, this);
    224     },
    225 
    226     shiftTimestampsForward: function(amount) {
    227       this.iterObjectInstances(function(instance) {
    228         instance.shiftTimestampsForward(amount);
    229       });
    230     },
    231 
    232     addCategoriesToDict: function(categoriesDict) {
    233       this.iterObjectInstances(function(instance) {
    234         categoriesDict[instance.category] = true;
    235       });
    236     }
    237   };
    238 
    239   return {
    240     ObjectCollection: ObjectCollection
    241   };
    242 });
    243 </script>
    244