/*
 * Copyright (C) 2018 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.
 */

#include "src/trace_processor/trace_storage.h"

#include <string.h>
#include <algorithm>
#include <limits>

#include "perfetto/ext/base/no_destructor.h"

namespace perfetto {
namespace trace_processor {

namespace {

template <typename T>
void MaybeUpdateMinMax(T begin_it,
                       T end_it,
                       int64_t* min_value,
                       int64_t* max_value) {
  if (begin_it == end_it) {
    return;
  }
  std::pair<T, T> minmax = std::minmax_element(begin_it, end_it);
  *min_value = std::min(*min_value, *minmax.first);
  *max_value = std::max(*max_value, *minmax.second);
}

std::vector<const char*> CreateRefTypeStringMap() {
  std::vector<const char*> map(RefType::kRefMax);
  map[RefType::kRefNoRef] = nullptr;
  map[RefType::kRefUtid] = "utid";
  map[RefType::kRefCpuId] = "cpu";
  map[RefType::kRefIrq] = "irq";
  map[RefType::kRefSoftIrq] = "softirq";
  map[RefType::kRefUpid] = "upid";
  return map;
}

}  // namespace

const std::vector<const char*>& GetRefTypeStringMap() {
  static const base::NoDestructor<std::vector<const char*>> map(
      CreateRefTypeStringMap());
  return map.ref();
}

TraceStorage::TraceStorage() {
  // Upid/utid 0 is reserved for idle processes/threads.
  unique_processes_.emplace_back(0);
  unique_threads_.emplace_back(0);
}

TraceStorage::~TraceStorage() {}

void TraceStorage::ResetStorage() {
  *this = TraceStorage();
}

uint32_t TraceStorage::SqlStats::RecordQueryBegin(const std::string& query,
                                                  int64_t time_queued,
                                                  int64_t time_started) {
  if (queries_.size() >= kMaxLogEntries) {
    queries_.pop_front();
    times_queued_.pop_front();
    times_started_.pop_front();
    times_first_next_.pop_front();
    times_ended_.pop_front();
    popped_queries_++;
  }
  queries_.push_back(query);
  times_queued_.push_back(time_queued);
  times_started_.push_back(time_started);
  times_first_next_.push_back(0);
  times_ended_.push_back(0);
  return static_cast<uint32_t>(popped_queries_ + queries_.size() - 1);
}

void TraceStorage::SqlStats::RecordQueryFirstNext(uint32_t row,
                                                  int64_t time_first_next) {
  // This means we've popped this query off the queue of queries before it had
  // a chance to finish. Just silently drop this number.
  if (popped_queries_ > row)
    return;
  uint32_t queue_row = row - popped_queries_;
  PERFETTO_DCHECK(queue_row < queries_.size());
  times_first_next_[queue_row] = time_first_next;
}

void TraceStorage::SqlStats::RecordQueryEnd(uint32_t row, int64_t time_ended) {
  // This means we've popped this query off the queue of queries before it had
  // a chance to finish. Just silently drop this number.
  if (popped_queries_ > row)
    return;
  uint32_t queue_row = row - popped_queries_;
  PERFETTO_DCHECK(queue_row < queries_.size());
  times_ended_[queue_row] = time_ended;
}

std::pair<int64_t, int64_t> TraceStorage::GetTraceTimestampBoundsNs() const {
  int64_t start_ns = std::numeric_limits<int64_t>::max();
  int64_t end_ns = std::numeric_limits<int64_t>::min();
  MaybeUpdateMinMax(slices_.start_ns().begin(), slices_.start_ns().end(),
                    &start_ns, &end_ns);
  MaybeUpdateMinMax(counter_values_.timestamps().begin(),
                    counter_values_.timestamps().end(), &start_ns, &end_ns);
  MaybeUpdateMinMax(instants_.timestamps().begin(),
                    instants_.timestamps().end(), &start_ns, &end_ns);
  MaybeUpdateMinMax(nestable_slices_.start_ns().begin(),
                    nestable_slices_.start_ns().end(), &start_ns, &end_ns);
  MaybeUpdateMinMax(android_log_.timestamps().begin(),
                    android_log_.timestamps().end(), &start_ns, &end_ns);
  MaybeUpdateMinMax(raw_events_.timestamps().begin(),
                    raw_events_.timestamps().end(), &start_ns, &end_ns);

  if (start_ns == std::numeric_limits<int64_t>::max()) {
    return std::make_pair(0, 0);
  }
  return std::make_pair(start_ns, end_ns);
}

}  // namespace trace_processor
}  // namespace perfetto
