// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "util/pprof-path-handlers.h"

#include <boost/bind.hpp>
#include <fstream>
#include <sys/stat.h>
#include <gperftools/profiler.h>
#include <gperftools/heap-profiler.h>
#include <gperftools/malloc_extension.h>

#include "common/logging.h"
#include "util/webserver.h"

#include "common/names.h"

using namespace google;
using namespace impala;
using namespace rapidjson;

DECLARE_string(heap_profile_dir);

static const int PPROF_DEFAULT_SAMPLE_SECS = 30; // pprof default sample time in seconds.

// pprof asks for the url /pprof/cmdline to figure out what application it's profiling.
// The server should respond by reading the contents of /proc/self/cmdline.
void PprofCmdLineHandler(const Webserver::WebRequest& req, stringstream* output) {
  ifstream cmd_line_file("/proc/self/cmdline", ios::in);
  if (!cmd_line_file.is_open()) {
    (*output) << "Unable to open file: /proc/self/cmdline";
    return;
  } else {
    (*output) << cmd_line_file.rdbuf();
    cmd_line_file.close();
  }
}

// pprof asks for the url /pprof/heap to get heap information. This should be implemented
// by calling HeapProfileStart(filename), continue to do work, and then, some number of
// seconds later, call GetHeapProfile() followed by HeapProfilerStop().
void PprofHeapHandler(const Webserver::WebRequest& req, stringstream* output) {
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
  (void)PPROF_DEFAULT_SAMPLE_SECS; // Avoid unused variable warning.
  (*output) << "Heap profiling is not available with address/thread sanitizer builds.";
#else
  const auto& args = req.parsed_args;
  Webserver::ArgumentMap::const_iterator it = args.find("seconds");
  int seconds = PPROF_DEFAULT_SAMPLE_SECS;
  if (it != args.end()) {
    seconds = atoi(it->second.c_str());
  }

  HeapProfilerStart(FLAGS_heap_profile_dir.c_str());
  // Sleep to allow for some samples to be collected.
  sleep(seconds);
  const char* profile = GetHeapProfile();
  HeapProfilerStop();
  (*output) << profile;
  delete profile;
#endif
}

// pprof asks for the url /pprof/profile?seconds=XX to get cpu-profiling information.
// The server should respond by calling ProfilerStart(), continuing to do its work,
// and then, XX seconds later, calling ProfilerStop().
void PprofCpuProfileHandler(const Webserver::WebRequest& req, stringstream* output) {
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
  (*output) << "CPU profiling is not available with address/thread sanitizer builds.";
#else
  const auto& args = req.parsed_args;
  Webserver::ArgumentMap::const_iterator it = args.find("seconds");
  int seconds = PPROF_DEFAULT_SAMPLE_SECS;
  if (it != args.end()) {
    seconds = atoi(it->second.c_str());
  }
  ostringstream tmp_prof_file_name;
  // Build a temporary file name that is hopefully unique.
  tmp_prof_file_name << "/tmp/impala_cpu_profile." << getpid() << "." << rand();
  ProfilerStart(tmp_prof_file_name.str().c_str());
  sleep(seconds);
  ProfilerStop();
  ifstream prof_file(tmp_prof_file_name.str().c_str(), ios::in);
  if (!prof_file.is_open()) {
    (*output) << "Unable to open cpu profile: " << tmp_prof_file_name.str();
    return;
  }
  (*output) << prof_file.rdbuf();
  prof_file.close();
#endif
}

// pprof asks for the url /pprof/growth to get heap-profiling delta (growth) information.
// The server should respond by calling:
// MallocExtension::instance()->GetHeapGrowthStacks(&output);
void PprofGrowthHandler(const Webserver::WebRequest& req, stringstream* output) {
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
  (*output) << "Growth profiling is not available with address/thread sanitizer builds.";
#else
  string heap_growth_stack;
  MallocExtension::instance()->GetHeapGrowthStacks(&heap_growth_stack);
  (*output) << heap_growth_stack;
#endif
}

// pprof asks for the url /pprof/symbol to map from hex addresses to variable names.
// When the server receives a GET request for /pprof/symbol, it should return a line
// formatted like: num_symbols: ###
// where ### is the number of symbols found in the binary. For now, the only important
// distinction is whether the value is 0, which it is for executables that lack debug
// information, or not-0).
//
// TODO: This part is not implemented:
// In addition to the GET request for this url, the server must accept POST requests.
// This means that after the HTTP headers, pprof will pass in a list of hex addresses
// connected by +, like:
//   curl -d '0x0824d061+0x0824d1cf' http://remote_host:80/pprof/symbol
// The server should read the POST data, which will be in one line, and for each hex value
// should write one line of output to the output stream, like so:
// <hex address><tab><function name>
// For instance:
// 0x08b2dabd    _Update
void PprofSymbolHandler(const Webserver::WebRequest& req, stringstream* output) {
  // TODO: Implement symbol resolution. Without this, the binary needs to be passed
  // to pprof to resolve all symbols.
  (*output) << "num_symbols: 0";
}

void impala::AddPprofUrlCallbacks(Webserver* webserver) {
  // Path handlers for remote pprof profiling. For information see:
  // https://gperftools.googlecode.com/svn/trunk/doc/pprof_remote_servers.html
  webserver->RegisterUrlCallback("/pprof/cmdline",
      bind<void>(PprofCmdLineHandler, _1, _2));
  webserver->RegisterUrlCallback("/pprof/heap", bind<void>(PprofHeapHandler, _1, _2));
  webserver->RegisterUrlCallback("/pprof/growth", bind<void>(PprofGrowthHandler, _1, _2));
  webserver->RegisterUrlCallback("/pprof/profile",
      bind<void>(PprofCpuProfileHandler, _1, _2));
  webserver->RegisterUrlCallback("/pprof/symbol", bind<void>(PprofSymbolHandler, _1, _2));
}
