// 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.
//
// Imported from Impala. Changes include:
// - Namespace and imports.
// - Replaced GetStrErrMsg with ErrnoToString.
// - Replaced StringParser with strings/numbers.
// - Fixes for cpplint.
// - Fixed parsing when thread names have spaces.

#include "kudu/util/os-util.h"

#include <fcntl.h>
#include <sys/resource.h>
#include <unistd.h>

#include <cstddef>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include <glog/logging.h>

#include "kudu/gutil/macros.h"
#include "kudu/gutil/strings/numbers.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/stringpiece.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/gutil/strings/util.h"
#include "kudu/util/env.h"
#include "kudu/util/faststring.h"
#include "kudu/util/logging.h"
#include "kudu/util/status.h"

using std::string;
using std::vector;
using strings::Split;
using strings::Substitute;

namespace kudu {

// Ensure that Impala compiles on earlier kernels. If the target kernel does not support
// _SC_CLK_TCK, sysconf(_SC_CLK_TCK) will return -1.
#ifndef _SC_CLK_TCK
#define _SC_CLK_TCK 2
#endif

static const int64_t kTicksPerSec = sysconf(_SC_CLK_TCK);

// Offsets into the ../stat file array of per-thread statistics.
//
// They are themselves offset by two because the pid and comm fields of the
// file are parsed separately.
static const int64_t kUserTicks = 13 - 2;
static const int64_t kKernelTicks = 14 - 2;
static const int64_t kIoWait = 41 - 2;

// Largest offset we are interested in, to check we get a well formed stat file.
static const int64_t kMaxOffset = kIoWait;

Status ParseStat(const string& buffer, string* name, ThreadStats* stats) {
  DCHECK(stats != nullptr);

  // The thread name should be the only field with parentheses. But the name
  // itself may contain parentheses.
  size_t open_paren = buffer.find('(');
  size_t close_paren = buffer.rfind(')');
  if (open_paren == string::npos  ||      // '(' must exist
      close_paren == string::npos ||      // ')' must exist
      open_paren >= close_paren   ||      // '(' must come before ')'
      close_paren + 2 == buffer.size()) { // there must be at least two chars after ')'
    return Status::IOError("Unrecognised /proc format");
  }
  string extracted_name = buffer.substr(open_paren + 1, close_paren - (open_paren + 1));
  string rest = buffer.substr(close_paren + 2);
  vector<string> splits = Split(rest, " ", strings::SkipEmpty());
  if (splits.size() < kMaxOffset) {
    return Status::IOError("Unrecognised /proc format");
  }

  int64_t tmp;
  if (safe_strto64(splits[kUserTicks], &tmp)) {
    stats->user_ns = tmp * (1e9 / kTicksPerSec);
  }
  if (safe_strto64(splits[kKernelTicks], &tmp)) {
    stats->kernel_ns = tmp * (1e9 / kTicksPerSec);
  }
  if (safe_strto64(splits[kIoWait], &tmp)) {
    stats->iowait_ns = tmp * (1e9 / kTicksPerSec);
  }
  if (name != nullptr) {
    *name = extracted_name;
  }
  return Status::OK();

}

Status GetThreadStats(int64_t tid, ThreadStats* stats) {
  DCHECK(stats != nullptr);
  if (kTicksPerSec <= 0) {
    return Status::NotSupported("ThreadStats not supported");
  }
  faststring buf;
  RETURN_NOT_OK(ReadFileToString(
      Env::Default(), Substitute("/proc/self/task/$0/stat", tid), &buf));

  return ParseStat(buf.ToString(), nullptr, stats);
}

void DisableCoreDumps() {
  struct rlimit lim;
  PCHECK(getrlimit(RLIMIT_CORE, &lim) == 0);
  lim.rlim_cur = 0;
  PCHECK(setrlimit(RLIMIT_CORE, &lim) == 0);

  // Set coredump_filter to not dump any parts of the address space.
  // Although the above disables core dumps to files, if core_pattern
  // is set to a pipe rather than a file, it's not sufficient. Setting
  // this pattern results in piping a very minimal dump into the core
  // processor (eg abrtd), thus speeding up the crash.
  int f;
  RETRY_ON_EINTR(f, open("/proc/self/coredump_filter", O_WRONLY));
  if (f >= 0) {
    ssize_t ret;
    RETRY_ON_EINTR(ret, write(f, "00000000", 8));
    int close_ret;
    RETRY_ON_EINTR(close_ret, close(f));
  }
}

bool IsBeingDebugged() {
#ifndef __linux__
  return false;
#else
  // Look for the TracerPid line in /proc/self/status.
  // If this is non-zero, we are being ptraced, which is indicative of gdb or strace
  // being attached.
  faststring buf;
  Status s = ReadFileToString(Env::Default(), "/proc/self/status", &buf);
  if (!s.ok()) {
    KLOG_FIRST_N(WARNING, 1) << "could not read /proc/self/status: " << s.ToString();
    return false;
  }
  StringPiece buf_sp(reinterpret_cast<const char*>(buf.data()), buf.size());
  vector<StringPiece> lines = Split(buf_sp, "\n");
  for (const auto& l : lines) {
    if (!HasPrefixString(l, "TracerPid:")) continue;
    std::pair<StringPiece, StringPiece> key_val = Split(l, "\t");
    int64_t tracer_pid = -1;
    if (!safe_strto64(key_val.second.data(), key_val.second.size(), &tracer_pid)) {
      KLOG_FIRST_N(WARNING, 1) << "Invalid line in /proc/self/status: " << l;
      return false;
    }
    return tracer_pid != 0;
  }
  KLOG_FIRST_N(WARNING, 1) << "Could not find TracerPid line in /proc/self/status";
  return false;
#endif // __linux__
}

} // namespace kudu
