/*
 * 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.
 */

// Tool that takes in a stream of allocations from stdin and outputs samples
//
// Input format is code_location size tuples, output format is iteration number
// code_location sample_size tuples. The sum of all allocations in the input is
// echoed back in the special iteration 'g'
//
// Example input:
// foo 1
// bar 10
// foo 1000
// baz 1
//
// Example output;
// g foo 1001
// g bar 10
// g baz 1
// 1 foo 1000
// 1 bar 100

#include <iostream>
#include <string>
#include <thread>

#include <unistd.h>

#include "src/profiling/memory/client.h"
#include "src/profiling/memory/sampler.h"

#include "perfetto/base/logging.h"

namespace perfetto {
namespace profiling {
namespace {

constexpr uint64_t kDefaultSamplingInterval = 128000;

int ProfilingSampleDistributionMain(int argc, char** argv) {
  int opt;
  uint64_t sampling_interval = kDefaultSamplingInterval;
  uint64_t times = 1;
  uint64_t init_seed = 1;

  while ((opt = getopt(argc, argv, "t:i:s:")) != -1) {
    switch (opt) {
      case 'i': {
        char* end;
        long long sampling_interval_arg = strtoll(optarg, &end, 10);
        if (*end != '\0' || *optarg == '\0')
          PERFETTO_FATAL("Invalid sampling interval: %s", optarg);
        PERFETTO_CHECK(sampling_interval_arg > 0);
        sampling_interval = static_cast<uint64_t>(sampling_interval_arg);
        break;
      }
      case 't': {
        char* end;
        long long times_arg = strtoll(optarg, &end, 10);
        if (*end != '\0' || *optarg == '\0')
          PERFETTO_FATAL("Invalid times: %s", optarg);
        PERFETTO_CHECK(times_arg > 0);
        times = static_cast<uint64_t>(times_arg);
        break;
      }
      case 's': {
        char* end;
        init_seed = static_cast<uint64_t>(strtoll(optarg, &end, 10));
        if (*end != '\0' || *optarg == '\0')
          PERFETTO_FATAL("Invalid seed: %s", optarg);
        break;
      }

      default:
        PERFETTO_FATAL("%s [-t times] [-i interval] [-s seed]", argv[0]);
    }
  }

  std::vector<std::pair<std::string, uint64_t>> allocations;

  while (std::cin) {
    std::string callsite;
    uint64_t size;
    std::cin >> callsite;
    if (std::cin.fail()) {
      // Skip trailing newline.
      if (std::cin.eof())
        break;
      PERFETTO_FATAL("Could not read callsite");
    }
    std::cin >> size;
    if (std::cin.fail())
      PERFETTO_FATAL("Could not read size");
    allocations.emplace_back(std::move(callsite), size);
  }
  std::map<std::string, uint64_t> total_ground_truth;
  for (const auto& pair : allocations)
    total_ground_truth[pair.first] += pair.second;

  for (const auto& pair : total_ground_truth)
    std::cout << "g " << pair.first << " " << pair.second << std::endl;

  std::default_random_engine seed_engine(init_seed);

  while (times-- > 0) {
    PThreadKey key(ThreadLocalSamplingData::KeyDestructor);
    ThreadLocalSamplingData::seed = seed_engine();
    // We want to use the same API here that the client uses, which involves
    // TLS. In order to destruct that TLS, we need to spawn a thread because
    // pthread_key_delete does not delete any associated data, but rather it
    // gets deleted when the owning thread terminates.
    //
    // Sad times.
    std::thread th([&] {
      if (!key.valid())
        PERFETTO_FATAL("Failed to initialize TLS.");

      std::map<std::string, uint64_t> totals;
      for (const auto& pair : allocations) {
        size_t sample_size =
            SampleSize(key.get(), pair.second, sampling_interval, malloc, free);
        // We also want to add 0 to make downstream processing easier, making
        // sure every iteration has an entry for every key, even if it is
        // zero.
        totals[pair.first] += sample_size;
      }

      for (const auto& pair : totals)
        std::cout << times << " " << pair.first << " " << pair.second
                  << std::endl;
    });
    th.join();
  }

  return 0;
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto

int main(int argc, char** argv) {
  return perfetto::profiling::ProfilingSampleDistributionMain(argc, argv);
}
