1# Copyright 2014 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
5import telemetry.timeline.counter as tracing_counter
6import telemetry.timeline.event as event_module
7import telemetry.timeline.event_container as event_container
8import telemetry.timeline.thread as tracing_thread
9
10
11class Process(event_container.TimelineEventContainer):
12  ''' The Process represents a single userland process in the trace.
13  '''
14  def __init__(self, parent, pid):
15    super(Process, self).__init__('process %s' % pid, parent)
16    self.pid = pid
17    self._threads = {}
18    self._counters = {}
19    self._trace_buffer_overflow_event = None
20
21  @property
22  def trace_buffer_did_overflow(self):
23    return self._trace_buffer_overflow_event is not None
24
25  @property
26  def trace_buffer_overflow_event(self):
27    return self._trace_buffer_overflow_event
28
29  @property
30  def threads(self):
31    return self._threads
32
33  @property
34  def counters(self):
35    return self._counters
36
37  def IterChildContainers(self):
38    for thread in self._threads.itervalues():
39      yield thread
40    for counter in self._counters.itervalues():
41      yield counter
42
43  def IterEventsInThisContainer(self, event_type_predicate, event_predicate):
44    if (not self.trace_buffer_did_overflow or
45        not event_type_predicate(event_module.TimelineEvent) or
46        not event_predicate(self._trace_buffer_overflow_event)):
47      return
48      yield # pylint: disable=W0101
49    yield self._trace_buffer_overflow_event
50
51  def GetOrCreateThread(self, tid):
52    thread = self.threads.get(tid, None)
53    if thread:
54      return thread
55    thread = tracing_thread.Thread(self, tid)
56    self._threads[tid] = thread
57    return thread
58
59  def GetCounter(self, category, name):
60    counter_id = category + '.' + name
61    if counter_id in self.counters:
62      return self.counters[counter_id]
63    raise ValueError(
64        'Counter %s not found in process with id %s.' % (counter_id,
65                                                         self.pid))
66  def GetOrCreateCounter(self, category, name):
67    try:
68      return self.GetCounter(category, name)
69    except ValueError:
70      ctr = tracing_counter.Counter(self, category, name)
71      self._counters[ctr.full_name] = ctr
72      return ctr
73
74  def AutoCloseOpenSlices(self, max_timestamp, thread_time_bounds):
75    for thread in self._threads.itervalues():
76      thread.AutoCloseOpenSlices(max_timestamp, thread_time_bounds[thread].max)
77
78  def SetTraceBufferOverflowTimestamp(self, timestamp):
79    # TODO: use instant event for trace_buffer_overflow_event
80    self._trace_buffer_overflow_event = event_module.TimelineEvent(
81        "TraceBufferInfo", "trace_buffer_overflowed", timestamp, 0)
82
83  def FinalizeImport(self):
84    for thread in self._threads.itervalues():
85      thread.FinalizeImport()
86    for counter in self._counters.itervalues():
87      counter.FinalizeImport()
88