// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "base/hash.h"
#include "cobalt/trace_event/event_parser.h"

namespace cobalt {
namespace trace_event {

EventParser::ScopedEvent::ScopedEvent(
    const scoped_refptr<ScopedEvent>& parent,
    const base::debug::TraceEvent& begin_event, EventParser* event_parser) {
  event_parser_ = event_parser;
  begin_event_ = begin_event;

  parent_ = parent;
  if (parent_) {
    parent_->children_.push_back(make_scoped_refptr(this));
    ++parent_->flow_active_children_;
  }
  flow_active_children_ = 0;

  state_ = kActiveState;
}

EventParser::ScopedEvent::~ScopedEvent() {}

void EventParser::ScopedEvent::Abort() {
  scoped_refptr<ScopedEvent> abort_event(this);

  // We maintain a list of all events ended so that we can prevent the
  // destructors from recursively calling itself and causing a stack overflow
  // in long chains of flow events.
  std::vector<scoped_refptr<ScopedEvent> > flow_events_aborted;

  while (abort_event) {
    if (abort_event->state_ == kFlowEndedState) {
      break;
    }

    // Report the event as complete, even though we aborted it.  The callee here
    // is responsible for checking if the event values it is interested in are
    // actually available before accessing them.  It is useful to report aborted
    // events because events are only reported as ended when their entire flow
    // has ended, but a benchmark may only be interested in the
    // in-scope-duration, and thus events that are aborted can still provide
    // information to benchmarks.
    abort_event->event_parser_->scoped_event_flow_end_callback_.Run(
        abort_event);

    flow_events_aborted.push_back(abort_event);

    scoped_refptr<ScopedEvent> next_abort_event;
    if (abort_event->parent_) {
      DCHECK_GT(abort_event->parent_->flow_active_children_, 0);
      --abort_event->parent_->flow_active_children_;
      if (abort_event->parent_->flow_active_children_ == 0) {
        next_abort_event = abort_event->parent_;
      }
    }

    abort_event->parent_ = NULL;
    abort_event->state_ = kAbortedState;

    abort_event = next_abort_event;
  }

  // Release our references in last-in-first-out order.  This results in the
  // parents being freed before the children, but it prevents all nodes from
  // recursively being freed when the root node (the top node on the stack
  // here) is released, which can prevent a stack overflow if the ancestry
  // chain is very long.
  while (!flow_events_aborted.empty()) {
    flow_events_aborted.pop_back();
  }
}

const base::debug::TraceEvent& EventParser::ScopedEvent::LastTraceEvent()
    const {
  if (end_event_) return *end_event_;
  if (!instant_events_.empty()) {
    return instant_events_.back();
  }
  return begin_event_;
}

void EventParser::ScopedEvent::OnEnd(
    const base::debug::TraceEvent& end_event) {
  DCHECK(!end_event_);
  DCHECK(end_event.timestamp() >= LastTraceEvent().timestamp());
  end_event_ = end_event;
  if (end_event.phase() == TRACE_EVENT_PHASE_FLOW_END) {
    // If we're ending a flow, it is possible that the flow may still be linked
    // with a TRACE_EVENT that immediately follows it (e.g. like in
    // MessageLoop::RunTask()).  Thus, we have to keep it alive only until
    // another trace event is encountered.  During this time, we leave it in
    // the kEndedAndLastTouchedState state.
    state_ = kEndedAndLastTouchedState;
  } else {
    // Mark the event as ended, and if the conditions are met for this event's
    // flow to also be ended that, trigger the OnEndFlow() processing as well.
    state_ = kEndedState;
    if (AreEndFlowConditionsMet()) {
      OnEndFlow(end_event.timestamp());
    }
  }
}

void EventParser::ScopedEvent::OnEndFlow(const base::TimeTicks& timestamp) {
  scoped_refptr<ScopedEvent> flow_end_event(this);

  // We maintain a list of all events ended so that we can prevent the
  // destructors from recursively calling itself and causing a stack overflow
  // in long chains of flow events.
  std::vector<scoped_refptr<ScopedEvent> > flow_events_ended;

  while (flow_end_event) {
    DCHECK(flow_end_event->AreEndFlowConditionsMet());

    // This ScopedEvent has ended and so have all of its descendants.  Update
    // the end flow timestamp and fire a flow end event to our clients so that
    // they may analyze this completed flow.
    flow_end_event->end_flow_time_ = timestamp;
    flow_end_event->event_parser_->scoped_event_flow_end_callback_.Run(
        flow_end_event);
    flow_events_ended.push_back(flow_end_event);

    // If we have a parent, we should properly decrement its active child count
    // since we are no longer active.  If we are the parent's last active child,
    // we may need to setup the parent as the next |flow_end_event| so that
    // its flow end can also be processed.  This is *not* done recursively on
    // purpose because these flows can end up quite long and we wish to avoid
    // stack overflows.
    scoped_refptr<ScopedEvent> next_flow_end_event;
    if (flow_end_event->parent_) {
      DCHECK_GT(flow_end_event->parent_->flow_active_children_, 0);
      --flow_end_event->parent_->flow_active_children_;
      if (flow_end_event->parent_->AreEndFlowConditionsMet()) {
        next_flow_end_event = flow_end_event->parent_;
      }
    }

    // Mark the parent_ as NULL to clear our reference to it.  This is more
    // a technicality to remove the cyclical dependency between child and parent
    // node once the child has ended its flow.
    flow_end_event->parent_ = NULL;
    flow_end_event->state_ = kFlowEndedState;

    flow_end_event = next_flow_end_event;
  }

  // Release our references in last-in-first-out order.  This results in the
  // parents being freed before the children, but it prevents all nodes from
  // recursively being freed when the root node (the top node on the stack
  // here) is released, which can prevent a stack overflow if the ancestry
  // chain is very long.
  while (!flow_events_ended.empty()) {
    flow_events_ended.pop_back();
  }
}

void EventParser::ScopedEvent::OnNotLastTouched() {
  if (state_ == kEndedAndLastTouchedState) {
    if (AreEndFlowConditionsMet()) {
      OnEndFlow(end_event_->timestamp());
    }
  }
}

void EventParser::ScopedEvent::AddInstantEvent(
    const base::debug::TraceEvent& event) {
  DCHECK(event.timestamp() >= LastTraceEvent().timestamp());
  instant_events_.push_back(event);
}

bool EventParser::ScopedEvent::AreEndFlowConditionsMet() const {
  // These conditions represent when we are able to begin the OnEndFlow()
  // processing to mark our flow as ended.
  return state_ != kFlowEndedState && state_ != kActiveState &&
         flow_active_children_ == 0 && end_event_;
}

std::set<scoped_refptr<EventParser::ScopedEvent> >
EventParser::ScopedEvent::GetLeafEvents() {
  std::set<scoped_refptr<ScopedEvent> > results;
  if (children_.empty()) {
    results.insert(this);
  } else {
    for (size_t i = 0; i < children_.size(); ++i) {
      std::set<scoped_refptr<ScopedEvent> > sub_results =
          children_[i]->GetLeafEvents();
      results.insert(sub_results.begin(), sub_results.end());
    }
  }
  return results;
}

EventParser::EventParser(
    const ScopedEventFlowEndCallback& scoped_event_flow_end_callback) {
  scoped_event_flow_end_callback_ = scoped_event_flow_end_callback;
}

EventParser::~EventParser() {
  // Knowing that there will be no future events, clear all existing events of
  // "last touched" status as this may permit them to end normally.
  for (ThreadMap::iterator thread_iter = thread_id_to_info_map_.begin();
       thread_iter != thread_id_to_info_map_.end(); ++thread_iter) {
    UpdateLastTouchedEvent(&thread_iter->second, NULL);
  }

  // Abort all leaf events.  When the last of a parent node's children is
  // aborted, the parent node will itself be aborted and thus aborting all
  // the leaf nodes will result in all nodes being aborted.
  std::set<scoped_refptr<ScopedEvent> > leaf_events =
      EventParser::GetLeafEvents();

  for (std::set<scoped_refptr<ScopedEvent> >::const_iterator iter =
           leaf_events.begin();
       iter != leaf_events.end(); ++iter) {
    (*iter)->Abort();
  }
}

std::set<scoped_refptr<EventParser::ScopedEvent> >
EventParser::GetLeafEvents() {
  // Go through all root event handles we have and obtain the leaf nodes from
  // each of their event flow trees.  Combine them all together into a set
  // and return this set of all leaf event nodes.
  std::set<scoped_refptr<ScopedEvent> > leaf_events;

  // First go through all flow event handles.
  for (FlowEventMap::iterator flow_iter = flow_id_to_event_map_.begin();
       flow_iter != flow_id_to_event_map_.end(); ++flow_iter) {
    scoped_refptr<ScopedEvent> current_flow_event = flow_iter->second;
    std::set<scoped_refptr<ScopedEvent> > current_leaf_events =
        current_flow_event->GetLeafEvents();
    leaf_events.insert(current_leaf_events.begin(), current_leaf_events.end());
  }

  // Then go through all thread stacks.
  for (ThreadMap::iterator thread_iter = thread_id_to_info_map_.begin();
       thread_iter != thread_id_to_info_map_.end(); ++thread_iter) {
    std::vector<scoped_refptr<ScopedEvent> >* current_event_stack =
        &thread_iter->second.event_stack_;
    if (!current_event_stack->empty()) {
      // We only need to look at the last element of each stack, since we know
      // that everything on top of that element is a parent of the element under
      // it (and hence not a leaf node).
      std::set<scoped_refptr<ScopedEvent> > current_leaf_events =
          current_event_stack->back()->GetLeafEvents();
      leaf_events.insert(current_leaf_events.begin(),
                         current_leaf_events.end());
    }
  }

  return leaf_events;
}

namespace {

// This function mangles the event's specified Id with the event name in order
// to produce a new id that is unique to both name and user-provided id.  It is
// specified by trace_event.h that flow events should only be linked together
// when both their name and user provided ids match.
uint64_t MakeFlowId(const base::debug::TraceEvent& event) {
  // The least significant end of both the event id and event name typically
  // change more than the most significant end, so mix the most significant
  // end of one with the least significant end of the other to better ensure
  // uniqueness.
  return static_cast<uint64_t>(event.id() << 32) ^
         (static_cast<uint64_t>(event.id() >> 32) & 0xFFFFFFFF) ^
         static_cast<uint64_t>(base::SuperFastHash(
             event.name(), strlen(event.name())));
}

}  // namespace

void EventParser::ParseEvent(const base::debug::TraceEvent& event) {
  // Get a reference to the thread context we are maintaining for the thread
  // this incoming event is linked to.
  ThreadInfo* thread_info = &thread_id_to_info_map_[event.thread_id()];

  switch (event.phase()) {
    case TRACE_EVENT_PHASE_BEGIN: {
      // Handle the case of a call to TRACE_EVENT occurring.  First, figure
      // out who its parent should be.  If this call follows a TRACE_EVENT_FLOW
      // call and matches in name, it will be parented to to that
      // TRACE_EVENT_FLOW allowing flow chains to cross multiple thread
      // boundaries.  Othewrise, it will be parented to the top TRACE_EVENT
      // on the event thread's event stack.
      scoped_refptr<ScopedEvent> parent;
      if (thread_info->last_touched_event_) {
        // Check if we should link this TRACE_EVENT log event with a directly
        // preceding TRACE_EVENT_FLOW log event.
        const base::debug::TraceEvent& trace_event =
            thread_info->last_touched_event_->LastTraceEvent();

        switch (trace_event.phase()) {
          case TRACE_EVENT_PHASE_FLOW_STEP: {
            // We would like to be able to scope TRACE_EVENT_FLOW_STEP calls,
            // so we do this by linking together a scoped TRACE_EVENT that
            // immediately follows a TRACE_EVENT_FLOW_STOP call.
            if (strcmp(trace_event.arg_values()[0].as_string, event.name()) ==
                0) {
              parent = thread_info->last_touched_event_;
            }
          } break;
          case TRACE_EVENT_PHASE_FLOW_END: {
            // This is a special case to support linking together MessageLoop
            // messages.  In particular, it is catered to the pattern of
            // trace event calls found in MessageLoop::RunTask.
            if (strcmp(trace_event.name(), "MessageLoop::PostTask") == 0 &&
                strcmp(event.name(), "MessageLoop::RunTask") == 0) {
              parent = thread_info->last_touched_event_;
            }
          } break;
        }
      }
      if (!parent && !thread_info->event_stack_.empty()) {
        // Setup our parent as the top event on the current thread's event
        // stack.
        parent = thread_info->event_stack_.back();
      }
      scoped_refptr<ScopedEvent> new_event =
          make_scoped_refptr(new ScopedEvent(parent, event, this));
      UpdateLastTouchedEvent(thread_info, new_event);
      // Make this the top event on the current thread's event stack
      thread_info->event_stack_.push_back(new_event);
    } break;

    case TRACE_EVENT_PHASE_END: {
      // If the thread's stack is empty, we were not tracking when the currently
      // ending scope had begun, so we ignore it.
      if (!thread_info->event_stack_.empty()) {
        // A TRACE_EVENT's scope has closed, ending the event.
        scoped_refptr<ScopedEvent> ended_event =
            thread_info->event_stack_.back();
        UpdateLastTouchedEvent(thread_info, ended_event);
        DCHECK_EQ(std::string(event.name()), ended_event->begin_event().name());

        // Mark the event as ended.
        ended_event->OnEnd(event);
        thread_info->event_stack_.pop_back();
      }
    } break;

    case TRACE_EVENT_PHASE_FLOW_BEGIN: {
      // A call to TRACE_EVENT_FLOW_BEGIN has been made.  Here we create a new
      // flow identified by a unique id.  It is only associated with the
      // current thread by it being parented to the top TRACE_EVENT on the
      // current thread's event stack, if there are any.
      scoped_refptr<ScopedEvent> parent;
      if (!thread_info->event_stack_.empty()) {
        parent = thread_info->event_stack_.back();
      }
      scoped_refptr<ScopedEvent> new_event =
          make_scoped_refptr(new ScopedEvent(parent, event, this));
      UpdateLastTouchedEvent(thread_info, new_event);
      DCHECK(flow_id_to_event_map_.find(MakeFlowId(event)) ==
                 flow_id_to_event_map_.end());
      // Save the event in the event map.
      flow_id_to_event_map_[MakeFlowId(event)] = new_event;
    } break;

    case TRACE_EVENT_PHASE_FLOW_STEP: {
      // Respond to a TRACE_EVENT_FLOW_STEP call.  When UpdateLastTouchedEvent()
      // is called for this event, it may end up being a parent if the next
      // call to TRACE_EVENT shares the same name as this event's step's name.
      // We only process this event if we have tracked the beginning of the
      // event.
      if (flow_id_to_event_map_.find(MakeFlowId(event)) !=
          flow_id_to_event_map_.end()) {
        scoped_refptr<ScopedEvent> flow_event =
            flow_id_to_event_map_[MakeFlowId(event)];
        UpdateLastTouchedEvent(thread_info, flow_event);
        DCHECK_EQ(std::string(event.name()), flow_event->begin_event().name());
        flow_event->AddInstantEvent(event);
      }
    } break;

    case TRACE_EVENT_PHASE_FLOW_END: {
      // Respond to TRACE_EVENT_FLOW_END.  When UpdateLastTouchedEvent() is
      // called, it may result in this flow being a parent if the next
      // call to TRACE_EVENT is "MessageLoop::RunTask" and this flow's name
      // is "MessageLoop::PostTask".  This allows linking flows across
      // message loops.
      FlowEventMap::iterator found =
          flow_id_to_event_map_.find(MakeFlowId(event));
      // Only process this flow end event if we were tracking when the beginning
      // of the flow took place.
      if (found != flow_id_to_event_map_.end()) {
        scoped_refptr<ScopedEvent> flow_event = found->second;
        UpdateLastTouchedEvent(thread_info, flow_event);
        DCHECK_EQ(std::string(event.name()), flow_event->begin_event().name());
        flow_event->OnEnd(event);
        flow_id_to_event_map_.erase(found);
      }
    } break;
  }
}

void EventParser::UpdateLastTouchedEvent(
    ThreadInfo* thread_info, const scoped_refptr<ScopedEvent>& event) {
  // Reset the provided thread's last touched event.  A last touched event
  // is whatever event was last processed (e.g. a TRACE_EVENT start or end or
  // a TRACE_EVENT_FLOW start, step or end.)
  if (thread_info->last_touched_event_) {
    thread_info->last_touched_event_->OnNotLastTouched();
  }
  thread_info->last_touched_event_ = event;
}

}  // namespace trace_event
}  // namespace cobalt
