#include "call_graph.hpp" #include namespace HawkTracer { namespace client { std::vector, int>> CallGraph::make(std::vector& events) { std::sort(events.begin(), events.end(), [](const NodeData& e1, const NodeData& e2){ return e1.start_ts < e2.start_ts; }); for (const auto& event : events) { _add_event(event); } return _root_calls; } std::shared_ptr CallGraph::_add_new_call(const NodeData& node_data, const std::shared_ptr& parent, std::vector, int>>& calls) { std::string label = node_data.label; auto call = std::find_if(calls.begin(), calls.end(), [&label](const std::pair, int>& call) { return call.first->data.label == label; }); if (call != calls.end()) { call->first->total_duration += node_data.get_duration(); call->first->data = node_data; ++call->second; return call->first; } else { std::shared_ptr event_node = std::make_shared(node_data); event_node->parent = parent; calls.emplace_back(event_node, 1); return event_node; } } void CallGraph::_add_new_calltree(const NodeData& node_data) { _current_call = _add_new_call(node_data, nullptr, _root_calls); } void CallGraph::_add_new_event_call(const std::shared_ptr& caller, const NodeData& node_data) { caller->total_children_duration += node_data.get_duration(); _current_call = _add_new_call(node_data, caller, caller->children); } bool CallGraph::_try_add_event_to_existing_calltree(const NodeData& node_data) { while(_current_call) { bool current_call_contains_new_event = _current_call->data.start_ts <= node_data.start_ts && node_data.stop_ts <= _current_call->data.stop_ts; if (current_call_contains_new_event) { _add_new_event_call(_current_call, node_data); return true; } else { _current_call = _current_call->parent.lock(); } } return false; } void CallGraph::_add_event(const NodeData& node_data) { bool added = _try_add_event_to_existing_calltree(node_data); if (!added) { _add_new_calltree(node_data); } } } // namespace client } // namespace HawkTracer