// 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 "arrow/util/logging.h"

#ifdef ARROW_WITH_BACKTRACE
#include <execinfo.h>
#endif
#include <cstdlib>
#include <iostream>

#ifdef ARROW_USE_GLOG

#include <signal.h>
#include <vector>

#include "glog/logging.h"

// Restore our versions of DCHECK and friends, as GLog defines its own
#undef DCHECK
#undef DCHECK_OK
#undef DCHECK_EQ
#undef DCHECK_NE
#undef DCHECK_LE
#undef DCHECK_LT
#undef DCHECK_GE
#undef DCHECK_GT

#define DCHECK ARROW_DCHECK
#define DCHECK_OK ARROW_DCHECK_OK
#define DCHECK_EQ ARROW_DCHECK_EQ
#define DCHECK_NE ARROW_DCHECK_NE
#define DCHECK_LE ARROW_DCHECK_LE
#define DCHECK_LT ARROW_DCHECK_LT
#define DCHECK_GE ARROW_DCHECK_GE
#define DCHECK_GT ARROW_DCHECK_GT

#endif

namespace arrow {
namespace util {

// This code is adapted from
// https://github.com/ray-project/ray/blob/master/src/ray/util/logging.cc.

// This is the default implementation of arrow log,
// which is independent of any libs.
class CerrLog {
 public:
  explicit CerrLog(ArrowLogLevel severity) : severity_(severity), has_logged_(false) {}

  virtual ~CerrLog() {
    if (has_logged_) {
      std::cerr << std::endl;
    }
    if (severity_ == ArrowLogLevel::ARROW_FATAL) {
      PrintBackTrace();
      std::abort();
    }
  }

  std::ostream& Stream() {
    has_logged_ = true;
    return std::cerr;
  }

  template <class T>
  CerrLog& operator<<(const T& t) {
    if (severity_ != ArrowLogLevel::ARROW_DEBUG) {
      has_logged_ = true;
      std::cerr << t;
    }
    return *this;
  }

 protected:
  const ArrowLogLevel severity_;
  bool has_logged_;

  void PrintBackTrace() {
#ifdef ARROW_WITH_BACKTRACE
    void* buffer[255];
    const int calls = backtrace(buffer, static_cast<int>(sizeof(buffer) / sizeof(void*)));
    backtrace_symbols_fd(buffer, calls, 1);
#endif
  }
};

#ifdef ARROW_USE_GLOG
typedef google::LogMessage LoggingProvider;
#else
typedef CerrLog LoggingProvider;
#endif

ArrowLogLevel ArrowLog::severity_threshold_ = ArrowLogLevel::ARROW_INFO;
// Keep the log directory.
static std::unique_ptr<std::string> log_dir_;

#ifdef ARROW_USE_GLOG

// Glog's severity map.
static int GetMappedSeverity(ArrowLogLevel severity) {
  switch (severity) {
    case ArrowLogLevel::ARROW_DEBUG:
      return google::GLOG_INFO;
    case ArrowLogLevel::ARROW_INFO:
      return google::GLOG_INFO;
    case ArrowLogLevel::ARROW_WARNING:
      return google::GLOG_WARNING;
    case ArrowLogLevel::ARROW_ERROR:
      return google::GLOG_ERROR;
    case ArrowLogLevel::ARROW_FATAL:
      return google::GLOG_FATAL;
    default:
      ARROW_LOG(FATAL) << "Unsupported logging level: " << static_cast<int>(severity);
      // This return won't be hit but compiler needs it.
      return google::GLOG_FATAL;
  }
}

#endif

void ArrowLog::StartArrowLog(const std::string& app_name,
                             ArrowLogLevel severity_threshold,
                             const std::string& log_dir) {
  severity_threshold_ = severity_threshold;
  // In InitGoogleLogging, it simply keeps the pointer.
  // We need to make sure the app name passed to InitGoogleLogging exist.
  // We should avoid using static string is a dynamic lib.
  static std::unique_ptr<std::string> app_name_;
  app_name_.reset(new std::string(app_name));
  log_dir_.reset(new std::string(log_dir));
#ifdef ARROW_USE_GLOG
  int mapped_severity_threshold = GetMappedSeverity(severity_threshold_);
  google::SetStderrLogging(mapped_severity_threshold);
  // Enble log file if log_dir is not empty.
  if (!log_dir.empty()) {
    auto dir_ends_with_slash = log_dir;
    if (log_dir[log_dir.length() - 1] != '/') {
      dir_ends_with_slash += "/";
    }
    auto app_name_without_path = app_name;
    if (app_name.empty()) {
      app_name_without_path = "DefaultApp";
    } else {
      // Find the app name without the path.
      size_t pos = app_name.rfind('/');
      if (pos != app_name.npos && pos + 1 < app_name.length()) {
        app_name_without_path = app_name.substr(pos + 1);
      }
    }
    // If InitGoogleLogging is called but SetLogDestination is not called,
    // the log will be output to /tmp besides stderr. If log_dir is not
    // provided, we'd better not call InitGoogleLogging.
    google::InitGoogleLogging(app_name_->c_str());
    google::SetLogFilenameExtension(app_name_without_path.c_str());
    for (int i = static_cast<int>(severity_threshold_);
         i <= static_cast<int>(ArrowLogLevel::ARROW_FATAL); ++i) {
      int level = GetMappedSeverity(static_cast<ArrowLogLevel>(i));
      google::SetLogDestination(level, dir_ends_with_slash.c_str());
    }
  }
#endif
}

void ArrowLog::UninstallSignalAction() {
#ifdef ARROW_USE_GLOG
  ARROW_LOG(DEBUG) << "Uninstall signal handlers.";
  // This signal list comes from glog's signalhandler.cc.
  // https://github.com/google/glog/blob/master/src/signalhandler.cc#L58-L70
  std::vector<int> installed_signals({SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGTERM});
#ifdef WIN32
  for (int signal_num : installed_signals) {
    ARROW_CHECK(signal(signal_num, SIG_DFL) != SIG_ERR);
  }
#else
  struct sigaction sig_action;
  memset(&sig_action, 0, sizeof(sig_action));
  sigemptyset(&sig_action.sa_mask);
  sig_action.sa_handler = SIG_DFL;
  for (int signal_num : installed_signals) {
    ARROW_CHECK(sigaction(signal_num, &sig_action, NULL) == 0);
  }
#endif
#endif
}

void ArrowLog::ShutDownArrowLog() {
#ifdef ARROW_USE_GLOG
  if (!log_dir_->empty()) {
    google::ShutdownGoogleLogging();
  }
#endif
}

void ArrowLog::InstallFailureSignalHandler() {
#ifdef ARROW_USE_GLOG
  google::InstallFailureSignalHandler();
#endif
}

bool ArrowLog::IsLevelEnabled(ArrowLogLevel log_level) {
  return log_level >= severity_threshold_;
}

ArrowLog::ArrowLog(const char* file_name, int line_number, ArrowLogLevel severity)
    // glog does not have DEBUG level, we can handle it using is_enabled_.
    : logging_provider_(nullptr), is_enabled_(severity >= severity_threshold_) {
#ifdef ARROW_USE_GLOG
  if (is_enabled_) {
    logging_provider_ =
        new google::LogMessage(file_name, line_number, GetMappedSeverity(severity));
  }
#else
  auto logging_provider = new CerrLog(severity);
  *logging_provider << file_name << ":" << line_number << ": ";
  logging_provider_ = logging_provider;
#endif
}

std::ostream& ArrowLog::Stream() {
  auto logging_provider = reinterpret_cast<LoggingProvider*>(logging_provider_);
#ifdef ARROW_USE_GLOG
  // Before calling this function, user should check IsEnabled.
  // When IsEnabled == false, logging_provider_ will be empty.
  return logging_provider->stream();
#else
  return logging_provider->Stream();
#endif
}

bool ArrowLog::IsEnabled() const { return is_enabled_; }

ArrowLog::~ArrowLog() {
  if (logging_provider_ != nullptr) {
    delete reinterpret_cast<LoggingProvider*>(logging_provider_);
    logging_provider_ = nullptr;
  }
}

}  // namespace util
}  // namespace arrow
