15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/trace_event_analyzer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace trace_analyzer {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceEvent
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceEvent::TraceEvent()
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : thread(0, 0),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timestamp(0),
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      duration(0),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      phase(TRACE_EVENT_PHASE_BEGIN),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other_event(NULL) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceEvent::~TraceEvent() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::SetFromJSON(const base::Value* event_value) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_value->GetType() != base::Value::TYPE_DICTIONARY) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Value must be TYPE_DICTIONARY";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* dictionary =
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<const base::DictionaryValue*>(event_value);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string phase_str;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* args = NULL;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dictionary->GetString("ph", &phase_str)) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ph is missing from TraceEvent JSON";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  phase = *phase_str.data();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool may_have_duration = (phase == TRACE_EVENT_PHASE_COMPLETE);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN ||
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     phase == TRACE_EVENT_PHASE_ASYNC_STEP_INTO ||
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     phase == TRACE_EVENT_PHASE_ASYNC_STEP_PAST ||
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     phase == TRACE_EVENT_PHASE_ASYNC_END);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "pid is missing from TraceEvent JSON";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "tid is missing from TraceEvent JSON";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (require_origin && !dictionary->GetDouble("ts", &timestamp)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ts is missing from TraceEvent JSON";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (may_have_duration) {
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    dictionary->GetDouble("dur", &duration);
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dictionary->GetString("cat", &category)) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "cat is missing from TraceEvent JSON";
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dictionary->GetString("name", &name)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "name is missing from TraceEvent JSON";
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dictionary->GetDictionary("args", &args)) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "args is missing from TraceEvent JSON";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (require_id && !dictionary->GetString("id", &id)) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "id is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each argument, copy the type and create a trace_analyzer::TraceValue.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it.Advance()) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool boolean = false;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int int_num = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double double_num = 0.0;
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (it.value().GetAsString(&str)) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_strings[it.key()] = str;
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else if (it.value().GetAsInteger(&int_num)) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = static_cast<double>(int_num);
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else if (it.value().GetAsBoolean(&boolean)) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0);
10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else if (it.value().GetAsDouble(&double_num)) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = double_num;
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else {
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      LOG(WARNING) << "Value type of argument is not supported: " <<
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<int>(it.value().GetType());
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      continue;  // Skip non-supported arguments.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double TraceEvent::GetAbsTimeToOtherEvent() const {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fabs(other_event->timestamp - timestamp);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::GetArgAsString(const std::string& name,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                std::string* arg) const {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string>::const_iterator i = arg_strings.find(name);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != arg_strings.end()) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *arg = i->second;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::GetArgAsNumber(const std::string& name,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                double* arg) const {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, double>::const_iterator i = arg_numbers.find(name);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != arg_numbers.end()) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *arg = i->second;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::HasStringArg(const std::string& name) const {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (arg_strings.find(name) != arg_strings.end());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::HasNumberArg(const std::string& name) const {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (arg_numbers.find(name) != arg_numbers.end());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TraceEvent::GetKnownArgAsString(const std::string& name) const {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string arg_string;
14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool result = GetArgAsString(name, &arg_string);
14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(result);
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return arg_string;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double TraceEvent::GetKnownArgAsDouble(const std::string& name) const {
15223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  double arg_double = 0;
15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool result = GetArgAsNumber(name, &arg_double);
15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(result);
15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return arg_double;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TraceEvent::GetKnownArgAsInt(const std::string& name) const {
15923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  double arg_double = 0;
16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool result = GetArgAsNumber(name, &arg_double);
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(result);
16223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return static_cast<int>(arg_double);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::GetKnownArgAsBool(const std::string& name) const {
16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  double arg_double = 0;
16723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool result = GetArgAsNumber(name, &arg_double);
16823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(result);
16923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return (arg_double != 0.0);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// QueryNode
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QueryNode::QueryNode(const Query& query) : query_(query) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QueryNode::~QueryNode() {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Query
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(TraceEventMember member)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_EVENT_MEMBER),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(member),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(TraceEventMember member, const std::string& arg_name)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_EVENT_MEMBER),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(member),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(arg_name),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& query)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(query.type_),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(query.operator_),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(query.left_),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      right_(query.right_),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(query.member_),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(query.number_),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(query.string_),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(query.is_pattern_) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::~Query() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::String(const std::string& str) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(str);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Double(double num) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(num);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Int(int32 num) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(num));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Uint(uint32 num) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(num));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Bool(bool boolean) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(boolean ? 1.0 : 0.0);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Phase(char phase) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(phase));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Pattern(const std::string& pattern) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query query(pattern);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.is_pattern_ = true;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return query;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::Evaluate(const TraceEvent& event) const {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First check for values that can convert to bool.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // double is true if != 0:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double bool_value = 0.0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_bool = GetAsDouble(event, &bool_value);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_bool)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (bool_value != 0.0);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string is true if it is non-empty:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str_value;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_str = GetAsString(event, &str_value);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_str)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !str_value.empty();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Invalid query: missing boolean expression";
26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(left_.get());
26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(right_.get() || is_unary_operator());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_comparison_operator()) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(left().is_value() && right().is_value())
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Invalid query: comparison operator used between event member and "
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           "value.";
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compare_result = false;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CompareAsDouble(event, &compare_result))
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return compare_result;
27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (CompareAsString(event, &compare_result))
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return compare_result;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's a logical operator.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_AND:
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return left().Evaluate(event) && right().Evaluate(event);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_OR:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return left().Evaluate(event) || right().Evaluate(event);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NOT:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return !left().Evaluate(event);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return false;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double lhs, rhs;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_EQ:
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs == rhs);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NE:
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs != rhs);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LT:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs < rhs);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LE:
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs <= rhs);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GT:
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs > rhs);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GE:
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs >= rhs);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lhs, rhs;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_EQ:
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (right().is_pattern_)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = MatchPattern(lhs, rhs);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (left().is_pattern_)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = MatchPattern(rhs, lhs);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = (lhs == rhs);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NE:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (right().is_pattern_)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = !MatchPattern(lhs, rhs);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (left().is_pattern_)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = !MatchPattern(rhs, lhs);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = (lhs != rhs);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LT:
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs < rhs);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LE:
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs <= rhs);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GT:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs > rhs);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GE:
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs >= rhs);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       double* num) const {
35823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_);
35923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(left_.get());
36023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(right_.get() || is_unary_operator());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double lhs = 0, rhs = 0;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsDouble(event, &lhs))
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_ADD:
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs + rhs;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_SUB:
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs - rhs;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_MUL:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs * rhs;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_DIV:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs / rhs;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_MOD:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(static_cast<int64>(lhs) %
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 static_cast<int64>(rhs));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NEGATE:
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = -lhs;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type_) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_ARITHMETIC_OPERATOR:
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EvaluateArithmeticOperator(event, num);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_EVENT_MEMBER:
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetMemberValueAsDouble(event, num);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_NUMBER:
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = number_;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type_) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_EVENT_MEMBER:
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetMemberValueAsString(event, str);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_STRING:
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = string_;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetMemberValueAsDouble(const TraceEvent& event,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   double* num) const {
42223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This could be a request for a member of |event| or a member of |event|'s
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated event. Store the target event in the_event:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TraceEvent* the_event = (member_ < OTHER_PID) ?
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event : event.other_event;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request for member of associated event, but there is no associated event.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!the_event)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (member_) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_PID:
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_PID:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->thread.process_id);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_TID:
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_TID:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->thread.thread_id);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_TIME:
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_TIME:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = the_event->timestamp;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_DURATION:
44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (!the_event->has_other_event())
44823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        return false;
44923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *num = the_event->GetAbsTimeToOtherEvent();
45023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return true;
4518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case EVENT_COMPLETE_DURATION:
45223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE)
45323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        return false;
45423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *num = the_event->duration;
45523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return true;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_PHASE:
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_PHASE:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->phase);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_STRING_ARG:
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_HAS_STRING_ARG:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_NUMBER_ARG:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_HAS_NUMBER_ARG:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ARG:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ARG: {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the argument name and return its value if found.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, double>::const_iterator num_i =
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          the_event->arg_numbers.find(string_);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (num_i == the_event->arg_numbers.end())
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = num_i->second;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_OTHER:
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // return 1.0 (true) if the other event exists
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = event.other_event ? 1.0 : 0.0;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetMemberValueAsString(const TraceEvent& event,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   std::string* str) const {
48923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This could be a request for a member of |event| or a member of |event|'s
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated event. Store the target event in the_event:
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TraceEvent* the_event = (member_ < OTHER_PID) ?
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event : event.other_event;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request for member of associated event, but there is no associated event.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!the_event)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (member_) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_CATEGORY:
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_CATEGORY:
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->category;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_NAME:
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_NAME:
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->name;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ID:
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ID:
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->id;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ARG:
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ARG: {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the argument name and return its value if found.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, std::string>::const_iterator str_i =
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          the_event->arg_strings.find(string_);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (str_i == the_event->arg_strings.end())
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = str_i->second;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const std::string& str)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_STRING),
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(str),
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(double num)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_NUMBER),
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(num),
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Query& Query::left() const {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return left_->query();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Query& Query::right() const {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return right_->query();
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator==(const Query& rhs) const {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_EQ);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator!=(const Query& rhs) const {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_NE);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator<(const Query& rhs) const {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_LT);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator<=(const Query& rhs) const {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_LE);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator>(const Query& rhs) const {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_GT);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator>=(const Query& rhs) const {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_GE);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator&&(const Query& rhs) const {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_AND);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator||(const Query& rhs) const {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_OR);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator!() const {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, OP_NOT);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator+(const Query& rhs) const {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_ADD);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator-(const Query& rhs) const {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_SUB);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator*(const Query& rhs) const {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_MUL);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator/(const Query& rhs) const {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_DIV);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator%(const Query& rhs) const {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_MOD);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator-() const {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, OP_NEGATE);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& left, const Query& right, Operator binary_op)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operator_(binary_op),
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(new QueryNode(left)),
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      right_(new QueryNode(right)),
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = (binary_op < OP_ADD ?
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& left, Operator unary_op)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operator_(unary_op),
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(new QueryNode(left)),
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = (unary_op < OP_ADD ?
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Search |events| for |query| and add matches to |output|.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const Query& query,
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          TraceEventVector* output,
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          bool ignore_metadata_events) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < events.size(); ++i) {
640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (ignore_metadata_events && events[i].phase == TRACE_EVENT_PHASE_METADATA)
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(events[i]))
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output->push_back(&events[i]);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output->size();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseEventsFromJson(const std::string& json,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         std::vector<TraceEvent>* output) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> root;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.reset(base::JSONReader::Read(json));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* root_list = NULL;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!root.get() || !root->GetAsList(&root_list))
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < root_list->GetSize(); ++i) {
6587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::Value* item = NULL;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (root_list->Get(i, &item)) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TraceEvent event;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.SetFromJSON(item))
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output->push_back(event);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceAnalyzer
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TraceAnalyzer::TraceAnalyzer()
676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : ignore_metadata_events_(false),
677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      allow_assocation_changes_(true) {}
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceAnalyzer::~TraceAnalyzer() {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (analyzer->SetEvents(json_events))
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return analyzer.release();
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceAnalyzer::SetEvents(const std::string& json_events) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_events_.clear();
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseEventsFromJson(json_events, &raw_events_))
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stable_sort(raw_events_.begin(), raw_events_.end());
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseMetadata();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateBeginEndEvents() {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using trace_analyzer::Query;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END));
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query match(Query::EventName() == Query::OtherName() &&
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventCategory() == Query::OtherCategory() &&
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventTid() == Query::OtherTid() &&
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventPid() == Query::OtherPid());
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssociateEvents(begin, end, match);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateAsyncBeginEndEvents() {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using trace_analyzer::Query;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query begin(
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
7171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
7181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) ||
7201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query match(Query::EventName() == Query::OtherName() &&
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventCategory() == Query::OtherCategory() &&
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventId() == Query::OtherId());
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssociateEvents(begin, end, match);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateEvents(const Query& first,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const Query& second,
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const Query& match) {
73223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(allow_assocation_changes_)
73323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      << "AssociateEvents not allowed after FindEvents";
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search for matching begin/end event pairs. When a matching end is found,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it is associated with the begin event.
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TraceEvent*> begin_stack;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t event_index = 0; event_index < raw_events_.size();
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++event_index) {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEvent& this_event = raw_events_[event_index];
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (second.Evaluate(this_event)) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search stack for matching begin, starting from end.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           stack_index >= 0; --stack_index) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TraceEvent& begin_event = *begin_stack[stack_index];
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Temporarily set other to test against the match query.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const TraceEvent* other_backup = begin_event.other_event;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin_event.other_event = &this_event;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (match.Evaluate(begin_event)) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Found a matching begin/end pair.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Erase the matching begin event index from the stack.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          begin_stack.erase(begin_stack.begin() + stack_index);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Not a match, restore original other and continue.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin_event.other_event = other_backup;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even if this_event is a |second| event that has matched an earlier
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |first| event, it can still also be a |first| event and be associated
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with a later |second| event.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (first.Evaluate(this_event)) {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      begin_stack.push_back(&this_event);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::MergeAssociatedEventArgs() {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < raw_events_.size(); ++i) {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge all associated events with the first event.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TraceEvent* other = raw_events_[i].other_event;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Avoid looping by keeping set of encountered TraceEvents.
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<const TraceEvent*> encounters;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encounters.insert(&raw_events_[i]);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (other && encounters.find(other) == encounters.end()) {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encounters.insert(other);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raw_events_[i].arg_numbers.insert(
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_numbers.begin(),
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_numbers.end());
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raw_events_[i].arg_strings.insert(
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_strings.begin(),
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_strings.end());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other = other->other_event;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allow_assocation_changes_ = false;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->clear();
795cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return FindMatchingEvents(
796cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      raw_events_, query, output, ignore_metadata_events_);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventVector output;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindEvents(query, &output) > 0)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return output.front();
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventVector output;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindEvents(query, &output) > 0)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return output.back();
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& TraceAnalyzer::GetThreadName(
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TraceEvent::ProcessThreadID& thread) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If thread is not found, just add and return empty string.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return thread_names_[thread];
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::ParseMetadata() {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < raw_events_.size(); ++i) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEvent& this_event = raw_events_[i];
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for thread name metadata.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (this_event.phase != TRACE_EVENT_PHASE_METADATA ||
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this_event.name != "thread_name")
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<std::string, std::string>::const_iterator string_it =
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this_event.arg_strings.find("name");
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (string_it != this_event.arg_strings.end())
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_names_[this_event.thread] = string_it->second;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceEventVector utility functions.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetRateStats(const TraceEventVector& events,
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  RateStats* stats,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const RateStatsOptions* options) {
83823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(stats);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need at least 3 events to calculate rate stats.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kMinEvents = 3;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.size() < kMinEvents) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Not enough events: " << events.size();
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<double> deltas;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_deltas = events.size() - 1;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta < 0.0) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Events are out of order";
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.push_back(delta);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(deltas.begin(), deltas.end());
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Attempt to trim too many events";
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.erase(deltas.begin(), deltas.begin() + options->trim_min);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.erase(deltas.end() - options->trim_max, deltas.end());
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_deltas = deltas.size();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double delta_sum = 0.0;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delta_sum += deltas[i];
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->min_us = *std::min_element(deltas.begin(), deltas.end());
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->max_us = *std::max_element(deltas.begin(), deltas.end());
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->mean_us = delta_sum / static_cast<double>(num_deltas);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double sum_mean_offsets_squared = 0.0;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double offset = fabs(deltas[i] - stats->mean_us);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sum_mean_offsets_squared += offset * offset;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->standard_deviation_us =
8833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1));
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindFirstOf(const TraceEventVector& events,
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Query& query,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t position,
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_index) {
89223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(return_index);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = position; i < events.size(); ++i) {
89423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (query.Evaluate(*events[i])) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *return_index = i;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindLastOf(const TraceEventVector& events,
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const Query& query,
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                size_t position,
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                size_t* return_index) {
90623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(return_index);
90723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (size_t i = std::min(position + 1, events.size()); i != 0; --i) {
90823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (query.Evaluate(*events[i - 1])) {
90923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *return_index = i - 1;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindClosest(const TraceEventVector& events,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Query& query,
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t position,
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_closest,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_second_closest) {
92123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(return_closest);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.empty() || position >= events.size())
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t closest = events.size();
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t second_closest = events.size();
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < events.size(); ++i) {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!query.Evaluate(*events.at(i)))
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (closest == events.size()) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closest = i;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) <
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      second_closest = closest;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closest = i;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (second_closest == events.size()) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      second_closest = i;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (closest < events.size() &&
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (!return_second_closest || second_closest < events.size())) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *return_closest = closest;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (return_second_closest)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *return_second_closest = second_closest;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t CountMatches(const TraceEventVector& events,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const Query& query,
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t begin_position,
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t end_position) {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (begin_position >= events.size())
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0u;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_position = (end_position < events.size()) ? end_position : events.size();
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = 0u;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = begin_position; i < end_position; ++i) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(*events.at(i)))
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++count;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return count;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace trace_analyzer
969