/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.
 */

#ifndef SIMPLE_PERF_SAMPLE_TREE_H_
#define SIMPLE_PERF_SAMPLE_TREE_H_

#include <unordered_map>

#include "callchain.h"
#include "dwarf_unwind.h"
#include "perf_regs.h"
#include "record.h"
#include "SampleComparator.h"
#include "SampleDisplayer.h"
#include "thread_tree.h"

// A SampleTree is a collection of samples. A profiling report is mainly about
// constructing a SampleTree and display it. There are three steps involved:
// build the tree, sort the tree, and display it. For example, if we want to
// show how many cpu-cycles are spent in different functions, we should do as
// follows:
// 1. Build a SampleTree from SampleRecords with each sample containing
//    (cpu-cycles, function name). When building the tree, we should merge
//    samples containing the same function name.
// 2. Sort the SampleTree by cpu-cycles in the sample. As we want to display the
//    samples in a decreasing order of cpu-cycles, we should sort it like this.
// 3. Display the SampleTree, each sample prints its (cpu-cycles, function name)
//    pair.
//
// We represent the three steps with three template classes.
// 1. A SampleTree is built by SampleTreeBuilder. The comparator passed in
//    SampleTreeBuilder's constructor decides the property of samples should be
//    merged together.
// 2. After a SampleTree is built and got from SampleTreeBuilder, it should be
//    sorted by SampleTreeSorter. The sort result decides the order to show
//    samples.
// 3. At last, the sorted SampleTree is passed to SampleTreeDisplayer, which
//    displays each sample in the SampleTree.

template <typename EntryT, typename AccumulateInfoT>
class SampleTreeBuilder {
 public:
  explicit SampleTreeBuilder(const SampleComparator<EntryT>& comparator)
      : sample_set_(comparator),
        accumulate_callchain_(false),
        sample_comparator_(comparator),
        callchain_sample_set_(comparator),
        use_branch_address_(false),
        build_callchain_(false),
        use_caller_as_callchain_root_(false),
        strict_unwind_arch_check_(false) {}

  virtual ~SampleTreeBuilder() {}

  void SetBranchSampleOption(bool use_branch_address) {
    use_branch_address_ = use_branch_address;
  }

  void SetCallChainSampleOptions(bool accumulate_callchain,
                                 bool build_callchain,
                                 bool use_caller_as_callchain_root,
                                 bool strict_unwind_arch_check) {
    accumulate_callchain_ = accumulate_callchain;
    build_callchain_ = build_callchain;
    use_caller_as_callchain_root_ = use_caller_as_callchain_root;
    strict_unwind_arch_check_ = strict_unwind_arch_check;
  }

  void ProcessSampleRecord(const SampleRecord& r) {
    if (use_branch_address_ && (r.sample_type & PERF_SAMPLE_BRANCH_STACK)) {
      for (uint64_t i = 0; i < r.branch_stack_data.stack_nr; ++i) {
        auto& item = r.branch_stack_data.stack[i];
        if (item.from != 0 && item.to != 0) {
          CreateBranchSample(r, item);
        }
      }
      return;
    }
    bool in_kernel = r.InKernel();
    AccumulateInfoT acc_info;
    EntryT* sample = CreateSample(r, in_kernel, &acc_info);
    if (sample == nullptr) {
      return;
    }
    if (accumulate_callchain_) {
      std::vector<uint64_t> ips;
      if (r.sample_type & PERF_SAMPLE_CALLCHAIN) {
        ips.insert(ips.end(), r.callchain_data.ips,
                   r.callchain_data.ips + r.callchain_data.ip_nr);
      }
      const ThreadEntry* thread = GetThreadOfSample(sample);
      // Use stack_user_data.data.size() instead of stack_user_data.dyn_size, to
      // make up for the missing kernel patch in N9. See b/22612370.
      if (thread != nullptr && (r.sample_type & PERF_SAMPLE_REGS_USER) &&
          (r.regs_user_data.reg_mask != 0) &&
          (r.sample_type & PERF_SAMPLE_STACK_USER) &&
          (r.GetValidStackSize() > 0)) {
        RegSet regs = CreateRegSet(r.regs_user_data.abi,
                                   r.regs_user_data.reg_mask,
                                   r.regs_user_data.regs);
        std::vector<uint64_t> unwind_ips =
            UnwindCallChain(r.regs_user_data.abi, *thread, regs,
                            r.stack_user_data.data,
                            r.GetValidStackSize(), strict_unwind_arch_check_);
        if (!unwind_ips.empty()) {
          ips.push_back(PERF_CONTEXT_USER);
          ips.insert(ips.end(), unwind_ips.begin(), unwind_ips.end());
        }
      }

      std::vector<EntryT*> callchain;
      callchain.push_back(sample);

      bool first_ip = true;
      for (auto& ip : ips) {
        if (ip >= PERF_CONTEXT_MAX) {
          switch (ip) {
            case PERF_CONTEXT_KERNEL:
              in_kernel = true;
              break;
            case PERF_CONTEXT_USER:
              in_kernel = false;
              break;
            default:
              LOG(DEBUG) << "Unexpected perf_context in callchain: " << ip;
          }
        } else {
          if (first_ip) {
            first_ip = false;
            // Remove duplication with sampled ip.
            if (ip == r.ip_data.ip) {
              continue;
            }
          }
          EntryT* callchain_sample =
              CreateCallChainSample(sample, ip, in_kernel, callchain, acc_info);
          if (callchain_sample == nullptr) {
            break;
          }
          callchain.push_back(callchain_sample);
        }
      }

      if (build_callchain_) {
        std::set<EntryT*> added_set;
        if (use_caller_as_callchain_root_) {
          std::reverse(callchain.begin(), callchain.end());
        }
        EntryT* parent = nullptr;
        while (callchain.size() >= 2) {
          EntryT* sample = callchain[0];
          callchain.erase(callchain.begin());
          // Add only once for recursive calls on callchain.
          if (added_set.find(sample) != added_set.end()) {
            continue;
          }
          added_set.insert(sample);
          InsertCallChainForSample(sample, callchain, acc_info);
          UpdateCallChainParentInfo(sample, parent);
          parent = sample;
        }
      }
    }
  }

  std::vector<EntryT*> GetSamples() const {
    std::vector<EntryT*> result;
    for (auto& entry : sample_set_) {
      result.push_back(entry);
    }
    return result;
  }

 protected:
  virtual EntryT* CreateSample(const SampleRecord& r, bool in_kernel,
                               AccumulateInfoT* acc_info) = 0;
  virtual EntryT* CreateBranchSample(const SampleRecord& r,
                                     const BranchStackItemType& item) = 0;
  virtual EntryT* CreateCallChainSample(const EntryT* sample, uint64_t ip,
                                        bool in_kernel,
                                        const std::vector<EntryT*>& callchain,
                                        const AccumulateInfoT& acc_info) = 0;
  virtual const ThreadEntry* GetThreadOfSample(EntryT*) = 0;
  virtual uint64_t GetPeriodForCallChain(const AccumulateInfoT& acc_info) = 0;
  virtual bool FilterSample(const EntryT*) { return true; }

  virtual void UpdateSummary(const EntryT*) {}

  virtual void MergeSample(EntryT* sample1, EntryT* sample2) = 0;

  EntryT* InsertSample(std::unique_ptr<EntryT> sample) {
    if (sample == nullptr || !FilterSample(sample.get())) {
      return nullptr;
    }
    UpdateSummary(sample.get());
    EntryT* result;
    auto it = sample_set_.find(sample.get());
    if (it == sample_set_.end()) {
      result = sample.get();
      sample_set_.insert(sample.get());
      sample_storage_.push_back(std::move(sample));
    } else {
      result = *it;
      MergeSample(*it, sample.get());
    }
    return result;
  }

  EntryT* InsertCallChainSample(std::unique_ptr<EntryT> sample,
                                const std::vector<EntryT*>& callchain) {
    if (sample == nullptr) {
      return nullptr;
    }
    if (!FilterSample(sample.get())) {
      // Store in callchain_sample_set_ for use in other EntryT's callchain.
      auto it = callchain_sample_set_.find(sample.get());
      if (it != callchain_sample_set_.end()) {
        return *it;
      }
      EntryT* result = sample.get();
      callchain_sample_set_.insert(sample.get());
      sample_storage_.push_back(std::move(sample));
      return result;
    }

    auto it = sample_set_.find(sample.get());
    if (it != sample_set_.end()) {
      EntryT* sample = *it;
      // Process only once for recursive function call.
      if (std::find(callchain.begin(), callchain.end(), sample) !=
          callchain.end()) {
        return sample;
      }
    }
    return InsertSample(std::move(sample));
  }

  void InsertCallChainForSample(EntryT* sample,
                                const std::vector<EntryT*>& callchain,
                                const AccumulateInfoT& acc_info) {
    uint64_t period = GetPeriodForCallChain(acc_info);
    sample->callchain.AddCallChain(
        callchain, period, [&](const EntryT* s1, const EntryT* s2) {
          return sample_comparator_.IsSameSample(s1, s2);
        });
  }

  void AddCallChainDuplicateInfo() {
    if (build_callchain_) {
      for (EntryT* sample : sample_set_) {
        auto it = callchain_parent_map_.find(sample);
        if (it != callchain_parent_map_.end() && !it->second.has_multiple_parents) {
          sample->callchain.duplicated = true;
        }
      }
    }
  }

  std::set<EntryT*, SampleComparator<EntryT>> sample_set_;
  bool accumulate_callchain_;

 private:
  void UpdateCallChainParentInfo(EntryT* sample, EntryT* parent) {
    if (parent == nullptr) {
      return;
    }
    auto it = callchain_parent_map_.find(sample);
    if (it == callchain_parent_map_.end()) {
      CallChainParentInfo info;
      info.parent = parent;
      info.has_multiple_parents = false;
      callchain_parent_map_[sample] = info;
    } else if (it->second.parent != parent) {
      it->second.has_multiple_parents = true;
    }
  }

  const SampleComparator<EntryT> sample_comparator_;
  // If a CallChainSample is filtered out, it is stored in callchain_sample_set_
  // and only used in other EntryT's callchain.
  std::set<EntryT*, SampleComparator<EntryT>> callchain_sample_set_;
  std::vector<std::unique_ptr<EntryT>> sample_storage_;

  struct CallChainParentInfo {
    EntryT* parent;
    bool has_multiple_parents;
  };
  std::unordered_map<EntryT*, CallChainParentInfo> callchain_parent_map_;

  bool use_branch_address_;
  bool build_callchain_;
  bool use_caller_as_callchain_root_;
  bool strict_unwind_arch_check_;
};

template <typename EntryT>
class SampleTreeSorter {
 public:
  explicit SampleTreeSorter(SampleComparator<EntryT> comparator)
      : comparator_(comparator) {}

  virtual ~SampleTreeSorter() {}

  void Sort(std::vector<EntryT*>& v, bool sort_callchain) {
    if (sort_callchain) {
      for (auto& sample : v) {
        SortCallChain(sample);
      }
    }
    if (!comparator_.empty()) {
      std::sort(v.begin(), v.end(), [this](const EntryT* s1, const EntryT* s2) {
        return comparator_(s1, s2);
      });
    }
  }

 protected:
  void SortCallChain(EntryT* sample) { sample->callchain.SortByPeriod(); }

 private:
  SampleComparator<EntryT> comparator_;
};

template <typename EntryT, typename InfoT>
class SampleTreeDisplayer {
 public:
  explicit SampleTreeDisplayer(SampleDisplayer<EntryT, InfoT> displayer)
      : displayer_(displayer) {}

  virtual ~SampleTreeDisplayer() {}

  void DisplaySamples(FILE* fp, const std::vector<EntryT*>& samples,
                      const InfoT* info) {
    displayer_.SetInfo(info);
    for (const auto& sample : samples) {
      displayer_.AdjustWidth(sample);
    }
    displayer_.PrintNames(fp);
    for (const auto& sample : samples) {
      displayer_.PrintSample(fp, sample);
    }
  }

 private:
  SampleDisplayer<EntryT, InfoT> displayer_;
};

#endif  // SIMPLE_PERF_SAMPLE_TREE_H_
