// 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 "kudu/server/pprof_path_handlers.h"

#include <unistd.h>

#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <functional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <gflags/gflags_declare.h>
#include <glog/logging.h>
#ifdef TCMALLOC_ENABLED
#include <gperftools/heap-profiler.h>
#include <gperftools/malloc_extension.h>
#include <gperftools/profiler.h>
#endif

#include "kudu/gutil/map-util.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/stringpiece.h"
#include "kudu/gutil/strings/strip.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/gutil/sysinfo.h"
#include "kudu/server/webserver.h"
#include "kudu/util/env.h"
#include "kudu/util/faststring.h"
#include "kudu/util/monotime.h"
#include "kudu/util/spinlock_profiling.h"
#include "kudu/util/status.h"
#include "kudu/util/web_callback_registry.h"

DECLARE_bool(enable_process_lifetime_heap_profiling);
DECLARE_string(heap_profile_path);


using std::endl;
using std::ifstream;
using std::ostringstream;
using std::string;
using std::vector;

// GLog already implements symbolization. Just import their hidden symbol.
namespace google {
// Symbolizes a program counter.  On success, returns true and write the
// symbol name to "out".  The symbol name is demangled if possible
// (supports symbols generated by GCC 3.x or newer).  Otherwise,
// returns false.
bool Symbolize(void *pc, char *out, size_t out_size);
}

namespace kudu {

const int kPprofDefaultSampleSecs = 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 sending the executable path.
static void PprofCmdLineHandler(const Webserver::WebRequest& /*req*/,
                                Webserver::PrerenderedWebResponse* resp) {
  string executable_path;
  Env* env = Env::Default();
  WARN_NOT_OK(env->GetExecutablePath(&executable_path), "Failed to get executable path");
  resp->output << executable_path;
}

// 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().
static void PprofHeapHandler(const Webserver::WebRequest& /*req*/,
                             Webserver::PrerenderedWebResponse* resp) {
  ostringstream* output = &resp->output;
#ifndef TCMALLOC_ENABLED
  *output << "%warn Heap profiling is not available without tcmalloc.\n";
#else
  // If we've started the process with heap profiling then dump the full profile.
  if (IsHeapProfilerRunning()) {
    char* profile = GetHeapProfile();
    *output << profile;
    free(profile);
    return;
  }

  // Otherwise dump the sample.
  string buf;
  MallocExtension::instance()->GetHeapSample(&buf);
  if (buf.find("This heap profile does not have any data") != string::npos) {
    // If sampling is disabled, tcmalloc prints a nice message with instructions
    // how to enable it. However, it only describes the environment variable method
    // and not our own gflag-based method, so we'll replace it with our own message.
    buf = "%warn\n"
        "%warn This heap profile does not have any data in it, because\n"
        "%warn the application was run with heap sampling turned off.\n"
        "%warn To obtain a heap sample, you must set the environment\n"
        "%warn variable TCMALLOC_SAMPLE_PARAMETER or the flag\n"
        "%warn --heap-sample-every-n-bytes to a positive sampling period,\n"
        "%warn such as 524288.\n"
        "%warn\n";
  }
  *output << buf;
#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().
static void PprofCpuProfileHandler(const Webserver::WebRequest& req,
                                   Webserver::PrerenderedWebResponse* resp) {
  ostringstream* output = &resp->output;
#ifndef TCMALLOC_ENABLED
  *output << "%warn CPU profiling is not available without tcmalloc.\n";
#else
  auto it = req.parsed_args.find("seconds");
  int seconds = kPprofDefaultSampleSecs;
  if (it != req.parsed_args.end()) {
    seconds = atoi(it->second.c_str());
  }
  // Build a temporary file name that is hopefully unique.
  string tmp_prof_file_name = strings::Substitute("/tmp/kudu_cpu_profile.$0.$1", getpid(), rand());
  ProfilerStart(tmp_prof_file_name.c_str());
  SleepFor(MonoDelta::FromSeconds(seconds));
  ProfilerStop();
  ifstream prof_file(tmp_prof_file_name.c_str(), std::ios::in);
  if (!prof_file.is_open()) {
    *output << "Unable to open cpu profile: " << tmp_prof_file_name;
    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);
static void PprofGrowthHandler(const Webserver::WebRequest& /*req*/,
                               Webserver::PrerenderedWebResponse* resp) {
#ifndef TCMALLOC_ENABLED
  resp->output << "%warn Growth profiling is not available without tcmalloc.\n";
#else
  string heap_growth_stack;
  MallocExtension::instance()->GetHeapGrowthStacks(&heap_growth_stack);
  resp->output << heap_growth_stack;
#endif
}

// Lock contention profiling
static void PprofContentionHandler(const Webserver::WebRequest& req,
                                   Webserver::PrerenderedWebResponse* resp) {
  string secs_str = FindWithDefault(req.parsed_args, "seconds", "");
  int32_t seconds = ParseLeadingInt32Value(secs_str.c_str(), kPprofDefaultSampleSecs);
  int64_t discarded_samples = 0;

  MonoTime end = MonoTime::Now() + MonoDelta::FromSeconds(seconds);
  ostringstream profile;
  StartSynchronizationProfiling();
  while (MonoTime::Now() < end) {
    SleepFor(MonoDelta::FromMilliseconds(500));
    FlushSynchronizationProfile(&profile, &discarded_samples);
  }
  StopSynchronizationProfiling();
  FlushSynchronizationProfile(&profile, &discarded_samples);

  ostringstream* output = &resp->output;
  *output << "--- contention:" << endl;
  *output << "sampling period = 1" << endl;
  *output << "cycles/second = " << static_cast<int64_t>(base::CyclesPerSecond()) << endl;
  // pprof itself ignores this value, but we can at least look at it in the textual
  // output.
  *output << "discarded samples = " << discarded_samples << std::endl;
  *output << profile.str();

#if defined(__linux__)
  // procfs only exists on Linux.
  faststring maps;
  ReadFileToString(Env::Default(), "/proc/self/maps", &maps);
  *output << "--- Memory map: ---" << endl;
  *output << maps.ToString();
#endif // defined(__linux__)
}


// 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).
//
// 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
static void PprofSymbolHandler(const Webserver::WebRequest& req,
                               Webserver::PrerenderedWebResponse* resp) {
  if (req.request_method == "GET") {
    // Per the above comment, pprof doesn't expect to know the actual number of symbols.
    // Any non-zero value indicates that we support symbol lookup.
    resp->output << "num_symbols: 1";
    return;
  }

  int missing_symbols = 0;
  int invalid_addrs = 0;

  // Symbolization request.
  vector<StringPiece> pieces = strings::Split(req.post_data, "+");
  for (StringPiece p : pieces) {
    string hex_addr;
    if (!TryStripPrefixString(p, "0x", &hex_addr)) {
      invalid_addrs++;
      continue;
    }
    uint64_t addr;
    if (!safe_strtou64_base(hex_addr.c_str(), &addr, 16)) {
      invalid_addrs++;
      continue;
    }
    char symbol_buf[1024];
    if (google::Symbolize(reinterpret_cast<void*>(addr), symbol_buf, sizeof(symbol_buf))) {
      resp->output << p << "\t" << symbol_buf << std::endl;
    } else {
      missing_symbols++;
    }
  }

  LOG(INFO) << strings::Substitute(
      "Handled request for /pprof/symbol: requested=$0 invalid_addrs=$1 missing=$2",
      pieces.size(), invalid_addrs, missing_symbols);
}

void AddPprofPathHandlers(Webserver* webserver) {
  // Path handlers for remote pprof profiling. For information see:
  // https://gperftools.googlecode.com/svn/trunk/doc/pprof_remote_servers.html
  webserver->RegisterPrerenderedPathHandler("/pprof/cmdline", "", PprofCmdLineHandler,
                                            false, false);
  webserver->RegisterPrerenderedPathHandler("/pprof/heap", "", PprofHeapHandler, false, false);
  webserver->RegisterPrerenderedPathHandler("/pprof/growth", "", PprofGrowthHandler, false, false);
  webserver->RegisterPrerenderedPathHandler("/pprof/profile", "", PprofCpuProfileHandler,
                                            false, false);
  webserver->RegisterPrerenderedPathHandler("/pprof/symbol", "", PprofSymbolHandler, false, false);
  webserver->RegisterPrerenderedPathHandler("/pprof/contention", "", PprofContentionHandler,
                                            false, false);
}

} // namespace kudu
