/*
 * Copyright (C) 2020 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/importers/common/async_track_set_tracker.h"

#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"

namespace perfetto {
namespace trace_processor {

AsyncTrackSetTracker::AsyncTrackSetTracker(TraceProcessorContext* context)
    : android_source_(context->storage->InternString("android")),
      context_(context) {}

AsyncTrackSetTracker::TrackSetId AsyncTrackSetTracker::InternGlobalTrackSet(
    StringId name) {
  auto it = global_track_set_ids_.find(name);
  if (it != global_track_set_ids_.end()) {
    return it->second;
  }

  uint32_t id = static_cast<uint32_t>(track_sets_.size());
  TrackSet set;
  set.global_track_name = name;
  set.scope = TrackSetScope::kGlobal;
  set.nesting_behaviour = NestingBehaviour::kNestable;
  track_sets_.emplace_back(set);

  return global_track_set_ids_[name] = id;
}

AsyncTrackSetTracker::TrackSetId AsyncTrackSetTracker::InternProcessTrackSet(
    UniquePid upid,
    StringId name) {
  ProcessTuple tuple{upid, name};

  auto it = process_track_set_ids_.find(tuple);
  if (it != process_track_set_ids_.end())
    return it->second;

  uint32_t id = static_cast<uint32_t>(track_sets_.size());

  TrackSet set;
  set.process_tuple = tuple;
  set.scope = TrackSetScope::kProcess;
  set.nesting_behaviour = NestingBehaviour::kNestable;
  track_sets_.emplace_back(set);

  process_track_set_ids_[tuple] = id;
  return id;
}

AsyncTrackSetTracker::TrackSetId
AsyncTrackSetTracker::InternAndroidLegacyUnnestableTrackSet(UniquePid upid,
                                                            StringId name) {
  ProcessTuple tuple{upid, name};

  auto it = android_legacy_unnestable_track_set_ids_.find(tuple);
  if (it != android_legacy_unnestable_track_set_ids_.end())
    return it->second;

  uint32_t id = static_cast<uint32_t>(track_sets_.size());

  TrackSet set;
  set.process_tuple = tuple;
  set.scope = TrackSetScope::kProcess;
  set.nesting_behaviour = NestingBehaviour::kLegacySaturatingUnnestable;
  track_sets_.emplace_back(set);

  android_legacy_unnestable_track_set_ids_[tuple] = id;
  return id;
}

TrackId AsyncTrackSetTracker::Begin(TrackSetId id, int64_t cookie) {
  PERFETTO_DCHECK(id < track_sets_.size());

  TrackSet& set = track_sets_[id];
  TrackState& state = GetOrCreateTrackForCookie(set, cookie);
  switch (set.nesting_behaviour) {
    case NestingBehaviour::kNestable:
      state.nest_count++;
      break;
    case NestingBehaviour::kLegacySaturatingUnnestable:
      PERFETTO_DCHECK(state.nest_count <= 1);
      state.nest_count = 1;
      break;
  }
  return state.id;
}

TrackId AsyncTrackSetTracker::End(TrackSetId id, int64_t cookie) {
  PERFETTO_DCHECK(id < track_sets_.size());

  TrackSet& set = track_sets_[id];
  TrackState& state = GetOrCreateTrackForCookie(set, cookie);

  // It's possible to have a nest count of 0 even when we know about the track.
  // Suppose the following sequence of events for some |id| and |cookie|:
  //   Begin
  //   (trace starts)
  //   Begin
  //   End
  //   End <- nest count == 0 here even though we have a record of this track.
  if (state.nest_count > 0)
    state.nest_count--;
  return state.id;
}

TrackId AsyncTrackSetTracker::Scoped(TrackSetId id, int64_t ts, int64_t dur) {
  PERFETTO_DCHECK(id < track_sets_.size());

  TrackSet& set = track_sets_[id];
  PERFETTO_DCHECK(set.nesting_behaviour !=
                  NestingBehaviour::kLegacySaturatingUnnestable);

  auto it = std::find_if(
      set.tracks.begin(), set.tracks.end(), [ts](const TrackState& state) {
        return state.slice_type == TrackState::SliceType::kTimestamp &&
               state.ts_end <= ts;
      });
  if (it != set.tracks.end()) {
    it->ts_end = ts + dur;
    return it->id;
  }

  TrackState state;
  state.slice_type = TrackState::SliceType::kTimestamp;
  state.ts_end = ts + dur;
  state.id = CreateTrackForSet(set);
  set.tracks.emplace_back(state);

  return state.id;
}

AsyncTrackSetTracker::TrackState&
AsyncTrackSetTracker::GetOrCreateTrackForCookie(TrackSet& set, int64_t cookie) {
  auto it = std::find_if(
      set.tracks.begin(), set.tracks.end(), [cookie](const TrackState& state) {
        return state.slice_type == TrackState::SliceType::kCookie &&
               state.cookie == cookie;
      });
  if (it != set.tracks.end())
    return *it;

  it = std::find_if(
      set.tracks.begin(), set.tracks.end(), [](const TrackState& state) {
        return state.slice_type == TrackState::SliceType::kCookie &&
               state.nest_count == 0;
      });
  if (it != set.tracks.end()) {
    // Adopt this track for the cookie to make sure future slices with this
    // cookie also get associated to this track.
    it->cookie = cookie;
    return *it;
  }

  TrackState state;
  state.id = CreateTrackForSet(set);
  state.slice_type = TrackState::SliceType::kCookie;
  state.cookie = cookie;
  state.nest_count = 0;
  set.tracks.emplace_back(state);

  return set.tracks.back();
}

TrackId AsyncTrackSetTracker::CreateTrackForSet(const TrackSet& set) {
  switch (set.scope) {
    case TrackSetScope::kGlobal:
      // TODO(lalitm): propogate source from callers rather than just passing
      // kNullStringId here.
      return context_->track_tracker->CreateGlobalAsyncTrack(
          set.global_track_name, kNullStringId);
    case TrackSetScope::kProcess:
      // TODO(lalitm): propogate source from callers rather than just passing
      // kNullStringId here.
      StringId source =
          set.nesting_behaviour == NestingBehaviour::kLegacySaturatingUnnestable
              ? android_source_
              : kNullStringId;
      return context_->track_tracker->CreateProcessAsyncTrack(
          set.process_tuple.name, set.process_tuple.upid, source);
  }
  PERFETTO_FATAL("For GCC");
}

}  // namespace trace_processor
}  // namespace perfetto
