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;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it.value().GetAsString(&str))
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_strings[it.key()] = str;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (it.value().GetAsInteger(&int_num))
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = static_cast<double>(int_num);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (it.value().GetAsBoolean(&boolean))
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (it.value().GetAsDouble(&double_num))
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arg_numbers[it.key()] = double_num;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetArgAsString(name, &arg_string))
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return arg_string;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double TraceEvent::GetKnownArgAsDouble(const std::string& name) const {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double arg_double;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetArgAsNumber(name, &arg_double))
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return arg_double;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TraceEvent::GetKnownArgAsInt(const std::string& name) const {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double arg_double;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetArgAsNumber(name, &arg_double))
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(arg_double);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceEvent::GetKnownArgAsBool(const std::string& name) const {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double arg_double;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetArgAsNumber(name, &arg_double))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (arg_double != 0.0);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// QueryNode
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QueryNode::QueryNode(const Query& query) : query_(query) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QueryNode::~QueryNode() {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Query
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(TraceEventMember member)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_EVENT_MEMBER),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(member),
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(TraceEventMember member, const std::string& arg_name)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_EVENT_MEMBER),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(member),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(arg_name),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& query)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(query.type_),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(query.operator_),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(query.left_),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      right_(query.right_),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(query.member_),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(query.number_),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(query.string_),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(query.is_pattern_) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::~Query() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::String(const std::string& str) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(str);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Double(double num) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(num);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Int(int32 num) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(num));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Uint(uint32 num) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(num));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Bool(bool boolean) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(boolean ? 1.0 : 0.0);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Phase(char phase) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(static_cast<double>(phase));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::Pattern(const std::string& pattern) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query query(pattern);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  query.is_pattern_ = true;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return query;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::Evaluate(const TraceEvent& event) const {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First check for values that can convert to bool.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // double is true if != 0:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double bool_value = 0.0;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_bool = GetAsDouble(event, &bool_value);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_bool)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (bool_value != 0.0);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string is true if it is non-empty:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str_value;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_str = GetAsString(event, &str_value);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_str)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !str_value.empty();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type_ == QUERY_BOOLEAN_OPERATOR)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Invalid query: missing boolean expression";
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(left_.get() && (right_.get() || is_unary_operator()));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_comparison_operator()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(left().is_value() && right().is_value())
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Invalid query: comparison operator used between event member and "
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           "value.";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool compare_result = false;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CompareAsDouble(event, &compare_result))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return compare_result;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (CompareAsString(event, &compare_result))
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return compare_result;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's a logical operator.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_AND:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return left().Evaluate(event) && right().Evaluate(event);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_OR:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return left().Evaluate(event) || right().Evaluate(event);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NOT:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return !left().Evaluate(event);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double lhs, rhs;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_EQ:
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs == rhs);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NE:
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs != rhs);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LT:
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs < rhs);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LE:
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs <= rhs);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GT:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs > rhs);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GE:
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs >= rhs);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lhs, rhs;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_EQ:
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (right().is_pattern_)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = MatchPattern(lhs, rhs);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (left().is_pattern_)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = MatchPattern(rhs, lhs);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = (lhs == rhs);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NE:
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (right().is_pattern_)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = !MatchPattern(lhs, rhs);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (left().is_pattern_)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = !MatchPattern(rhs, lhs);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = (lhs != rhs);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LT:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs < rhs);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_LE:
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs <= rhs);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GT:
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs > rhs);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_GE:
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = (lhs >= rhs);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       double* num) const {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type_ == QUERY_ARITHMETIC_OPERATOR);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(left_.get() && (right_.get() || is_unary_operator()));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double lhs = 0, rhs = 0;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!left().GetAsDouble(event, &lhs))
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (operator_) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_ADD:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs + rhs;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_SUB:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs - rhs;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_MUL:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs * rhs;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_DIV:
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = lhs / rhs;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_MOD:
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(static_cast<int64>(lhs) %
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 static_cast<int64>(rhs));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OP_NEGATE:
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = -lhs;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type_) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_ARITHMETIC_OPERATOR:
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EvaluateArithmeticOperator(event, num);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_EVENT_MEMBER:
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetMemberValueAsDouble(event, num);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_NUMBER:
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = number_;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type_) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_EVENT_MEMBER:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetMemberValueAsString(event, str);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case QUERY_STRING:
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = string_;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetMemberValueAsDouble(const TraceEvent& event,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   double* num) const {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type_ == QUERY_EVENT_MEMBER);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This could be a request for a member of |event| or a member of |event|'s
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated event. Store the target event in the_event:
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TraceEvent* the_event = (member_ < OTHER_PID) ?
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event : event.other_event;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request for member of associated event, but there is no associated event.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!the_event)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (member_) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_PID:
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_PID:
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->thread.process_id);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_TID:
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_TID:
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->thread.thread_id);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_TIME:
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_TIME:
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = the_event->timestamp;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_DURATION:
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (the_event->has_other_event()) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *num = the_event->GetAbsTimeToOtherEvent();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case EVENT_COMPLETE_DURATION:
4598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if (the_event->phase == TRACE_EVENT_PHASE_COMPLETE) {
4608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        *num = the_event->duration;
4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return true;
4628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
4638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_PHASE:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_PHASE:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = static_cast<double>(the_event->phase);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_STRING_ARG:
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_HAS_STRING_ARG:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_NUMBER_ARG:
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_HAS_NUMBER_ARG:
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ARG:
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ARG: {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the argument name and return its value if found.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, double>::const_iterator num_i =
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          the_event->arg_numbers.find(string_);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (num_i == the_event->arg_numbers.end())
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = num_i->second;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_HAS_OTHER:
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // return 1.0 (true) if the other event exists
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *num = event.other_event ? 1.0 : 0.0;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Query::GetMemberValueAsString(const TraceEvent& event,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   std::string* str) const {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type_ == QUERY_EVENT_MEMBER);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This could be a request for a member of |event| or a member of |event|'s
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated event. Store the target event in the_event:
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TraceEvent* the_event = (member_ < OTHER_PID) ?
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &event : event.other_event;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request for member of associated event, but there is no associated event.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!the_event)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (member_) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_CATEGORY:
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_CATEGORY:
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->category;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_NAME:
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_NAME:
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->name;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ID:
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ID:
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = the_event->id;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EVENT_ARG:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OTHER_ARG: {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search for the argument name and return its value if found.
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, std::string>::const_iterator str_i =
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          the_event->arg_strings.find(string_);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (str_i == the_event->arg_strings.end())
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *str = str_i->second;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const std::string& str)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_STRING),
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string_(str),
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(double num)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(QUERY_NUMBER),
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      operator_(OP_INVALID),
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(num),
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_pattern_(false) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Query& Query::left() const {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return left_->query();
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Query& Query::right() const {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return right_->query();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator==(const Query& rhs) const {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_EQ);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator!=(const Query& rhs) const {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_NE);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator<(const Query& rhs) const {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_LT);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator<=(const Query& rhs) const {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_LE);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator>(const Query& rhs) const {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_GT);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator>=(const Query& rhs) const {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_GE);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator&&(const Query& rhs) const {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_AND);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator||(const Query& rhs) const {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_OR);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator!() const {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, OP_NOT);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator+(const Query& rhs) const {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_ADD);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator-(const Query& rhs) const {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_SUB);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator*(const Query& rhs) const {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_MUL);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator/(const Query& rhs) const {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_DIV);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator%(const Query& rhs) const {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, rhs, OP_MOD);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query Query::operator-() const {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Query(*this, OP_NEGATE);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& left, const Query& right, Operator binary_op)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operator_(binary_op),
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(new QueryNode(left)),
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      right_(new QueryNode(right)),
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = (binary_op < OP_ADD ?
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Query::Query(const Query& left, Operator unary_op)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : operator_(unary_op),
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      left_(new QueryNode(left)),
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member_(EVENT_INVALID),
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_(0) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = (unary_op < OP_ADD ?
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Search |events| for |query| and add matches to |output|.
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const Query& query,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          TraceEventVector* output) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < events.size(); ++i) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(events[i]))
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output->push_back(&events[i]);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output->size();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseEventsFromJson(const std::string& json,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         std::vector<TraceEvent>* output) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> root;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  root.reset(base::JSONReader::Read(json));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* root_list = NULL;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!root.get() || !root->GetAsList(&root_list))
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < root_list->GetSize(); ++i) {
6637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::Value* item = NULL;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (root_list->Get(i, &item)) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TraceEvent event;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (event.SetFromJSON(item))
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output->push_back(event);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceAnalyzer
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceAnalyzer::TraceAnalyzer() : allow_assocation_changes_(true) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceAnalyzer::~TraceAnalyzer() {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (analyzer->SetEvents(json_events))
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return analyzer.release();
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TraceAnalyzer::SetEvents(const std::string& json_events) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_events_.clear();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseEventsFromJson(json_events, &raw_events_))
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stable_sort(raw_events_.begin(), raw_events_.end());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseMetadata();
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateBeginEndEvents() {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using trace_analyzer::Query;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN));
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END));
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query match(Query::EventName() == Query::OtherName() &&
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventCategory() == Query::OtherCategory() &&
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventTid() == Query::OtherTid() &&
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventPid() == Query::OtherPid());
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssociateEvents(begin, end, match);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateAsyncBeginEndEvents() {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  using trace_analyzer::Query;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query begin(
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
7221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) ||
7241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
7251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Query match(Query::EventName() == Query::OtherName() &&
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventCategory() == Query::OtherCategory() &&
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Query::EventId() == Query::OtherId());
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssociateEvents(begin, end, match);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::AssociateEvents(const Query& first,
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const Query& second,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const Query& match) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after "
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      "FindEvents";
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Search for matching begin/end event pairs. When a matching end is found,
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it is associated with the begin event.
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TraceEvent*> begin_stack;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t event_index = 0; event_index < raw_events_.size();
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++event_index) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEvent& this_event = raw_events_[event_index];
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (second.Evaluate(this_event)) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Search stack for matching begin, starting from end.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           stack_index >= 0; --stack_index) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TraceEvent& begin_event = *begin_stack[stack_index];
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Temporarily set other to test against the match query.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const TraceEvent* other_backup = begin_event.other_event;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin_event.other_event = &this_event;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (match.Evaluate(begin_event)) {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Found a matching begin/end pair.
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Erase the matching begin event index from the stack.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          begin_stack.erase(begin_stack.begin() + stack_index);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Not a match, restore original other and continue.
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin_event.other_event = other_backup;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even if this_event is a |second| event that has matched an earlier
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |first| event, it can still also be a |first| event and be associated
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with a later |second| event.
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (first.Evaluate(this_event)) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      begin_stack.push_back(&this_event);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::MergeAssociatedEventArgs() {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < raw_events_.size(); ++i) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Merge all associated events with the first event.
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TraceEvent* other = raw_events_[i].other_event;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Avoid looping by keeping set of encountered TraceEvents.
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<const TraceEvent*> encounters;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encounters.insert(&raw_events_[i]);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (other && encounters.find(other) == encounters.end()) {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encounters.insert(other);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raw_events_[i].arg_numbers.insert(
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_numbers.begin(),
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_numbers.end());
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raw_events_[i].arg_strings.insert(
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_strings.begin(),
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          other->arg_strings.end());
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other = other->other_event;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allow_assocation_changes_ = false;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->clear();
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindMatchingEvents(raw_events_, query, output);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventVector output;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindEvents(query, &output) > 0)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return output.front();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventVector output;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FindEvents(query, &output) > 0)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return output.back();
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& TraceAnalyzer::GetThreadName(
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TraceEvent::ProcessThreadID& thread) {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If thread is not found, just add and return empty string.
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return thread_names_[thread];
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceAnalyzer::ParseMetadata() {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < raw_events_.size(); ++i) {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEvent& this_event = raw_events_[i];
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for thread name metadata.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (this_event.phase != TRACE_EVENT_PHASE_METADATA ||
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this_event.name != "thread_name")
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<std::string, std::string>::const_iterator string_it =
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this_event.arg_strings.find("name");
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (string_it != this_event.arg_strings.end())
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_names_[this_event.thread] = string_it->second;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceEventVector utility functions.
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetRateStats(const TraceEventVector& events,
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  RateStats* stats,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const RateStatsOptions* options) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(stats);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need at least 3 events to calculate rate stats.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kMinEvents = 3;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.size() < kMinEvents) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Not enough events: " << events.size();
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<double> deltas;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_deltas = events.size() - 1;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i) {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delta < 0.0) {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Events are out of order";
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.push_back(delta);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(deltas.begin(), deltas.end());
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Attempt to trim too many events";
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.erase(deltas.begin(), deltas.begin() + options->trim_min);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deltas.erase(deltas.end() - options->trim_max, deltas.end());
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_deltas = deltas.size();
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double delta_sum = 0.0;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delta_sum += deltas[i];
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->min_us = *std::min_element(deltas.begin(), deltas.end());
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->max_us = *std::max_element(deltas.begin(), deltas.end());
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->mean_us = delta_sum / static_cast<double>(num_deltas);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double sum_mean_offsets_squared = 0.0;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < num_deltas; ++i) {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double offset = fabs(deltas[i] - stats->mean_us);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sum_mean_offsets_squared += offset * offset;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stats->standard_deviation_us =
8863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1));
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindFirstOf(const TraceEventVector& events,
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Query& query,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t position,
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_index) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(return_index);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = position; i < events.size(); ++i) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(*events.at(i))) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *return_index = i;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindLastOf(const TraceEventVector& events,
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const Query& query,
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                size_t position,
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                size_t* return_index) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(return_index);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.empty())
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position = (position < events.size()) ? position : events.size() - 1;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(*events.at(position))) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *return_index = position;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (position == 0)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --position;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindClosest(const TraceEventVector& events,
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const Query& query,
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t position,
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_closest,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 size_t* return_second_closest) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(return_closest);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events.empty() || position >= events.size())
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t closest = events.size();
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t second_closest = events.size();
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < events.size(); ++i) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!query.Evaluate(*events.at(i)))
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (closest == events.size()) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closest = i;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) <
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      second_closest = closest;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closest = i;
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (second_closest == events.size()) {
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      second_closest = i;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (closest < events.size() &&
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (!return_second_closest || second_closest < events.size())) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *return_closest = closest;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (return_second_closest)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *return_second_closest = second_closest;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t CountMatches(const TraceEventVector& events,
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const Query& query,
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t begin_position,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t end_position) {
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (begin_position >= events.size())
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0u;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  end_position = (end_position < events.size()) ? end_position : events.size();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = 0u;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = begin_position; i < end_position; ++i) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (query.Evaluate(*events.at(i)))
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++count;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return count;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace trace_analyzer
978