text: #include <errno.h>
  #include <string.h>
  #include <cxxabi.h>
  
  #include <Poco/String.h>
  
  #include <common/logger_useful.h>
  
  #include <IO/WriteHelpers.h>
  #include <IO/Operators.h>
  #include <IO/ReadBufferFromString.h>
  
  #include <Common/Exception.h>
  #include <common/demangle.h>
  
  
  namespace DB
  {
  
  namespace ErrorCodes
  {
      extern const int POCO_EXCEPTION;
      extern const int STD_EXCEPTION;
      extern const int UNKNOWN_EXCEPTION;
      extern const int CANNOT_TRUNCATE_FILE;
  }
  
  
  void throwFromErrno(const std::string & s, int code, int e)
  {
      const size_t buf_size = 128;
      char buf[buf_size];
  #ifndef _GNU_SOURCE
      int rc = strerror_r(e, buf, buf_size);
  #ifdef __APPLE__
      if (rc != 0 && rc != EINVAL)
  #else
      if (rc != 0)
  #endif
      {
          std::string tmp = std::to_string(code);
          const char * code = tmp.c_str();
          const char * unknown_message = "Unknown error ";
          strcpy(buf, unknown_message);
          strcpy(buf + strlen(unknown_message), code);
      }
      throw ErrnoException(s + ", errno: " + toString(e) + ", strerror: " + std::string(buf), code, e);
  #else
      throw ErrnoException(s + ", errno: " + toString(e) + ", strerror: " + std::string(strerror_r(e, buf, sizeof(buf))), code, e);
  #endif
  }
  
  
  void tryLogCurrentException(const char * log_name, const std::string & start_of_message)
  {
      tryLogCurrentException(&Logger::get(log_name), start_of_message);
  }
  
  void tryLogCurrentException(Poco::Logger * logger, const std::string & start_of_message)
  {
      try
      {
          LOG_ERROR(logger, start_of_message << (start_of_message.empty() ? "" : ": ") << getCurrentExceptionMessage(true));
      }
      catch (...)
      {
      }
  }
  
  std::string getCurrentExceptionMessage(bool with_stacktrace, bool check_embedded_stacktrace)
  {
      std::stringstream stream;
  
      try
      {
          throw;
      }
      catch (const Exception & e)
      {
          stream << getExceptionMessage(e, with_stacktrace, check_embedded_stacktrace);
      }
      catch (const Poco::Exception & e)
      {
          try
          {
              stream << "Poco::Exception. Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code()
                  << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what();
          }
          catch (...) {}
      }
      catch (const std::exception & e)
      {
          try
          {
              int status = 0;
              auto name = demangle(typeid(e).name(), status);
  
              if (status)
                  name += " (demangling status: " + toString(status) + ")";
  
              stream << "std::exception. Code: " << ErrorCodes::STD_EXCEPTION << ", type: " << name << ", e.what() = " << e.what();
          }
          catch (...) {}
      }
      catch (...)
      {
          try
          {
              int status = 0;
              auto name = demangle(abi::__cxa_current_exception_type()->name(), status);
  
              if (status)
                  name += " (demangling status: " + toString(status) + ")";
  
              stream << "Unknown exception. Code: " << ErrorCodes::UNKNOWN_EXCEPTION << ", type: " << name;
          }
          catch (...) {}
      }
  
      return stream.str();
  }
  
  
  int getCurrentExceptionCode()
  {
      try
      {
          throw;
      }
      catch (const Exception & e)
      {
          return e.code();
      }
      catch (const Poco::Exception & e)
      {
          return ErrorCodes::POCO_EXCEPTION;
      }
      catch (const std::exception & e)
      {
          return ErrorCodes::STD_EXCEPTION;
      }
      catch (...)
      {
          return ErrorCodes::UNKNOWN_EXCEPTION;
      }
  }
  
  
  void rethrowFirstException(const Exceptions & exceptions)
  {
      for (size_t i = 0, size = exceptions.size(); i < size; ++i)
          if (exceptions[i])
              std::rethrow_exception(exceptions[i]);
  }
  
  
  void tryLogException(std::exception_ptr e, const char * log_name, const std::string & start_of_message)
  {
      try
      {
          std::rethrow_exception(std::move(e));
      }
      catch (...)
      {
          tryLogCurrentException(log_name, start_of_message);
      }
  }
  
  void tryLogException(std::exception_ptr e, Poco::Logger * logger, const std::string & start_of_message)
  {
      try
      {
          std::rethrow_exception(std::move(e));
      }
      catch (...)
      {
          tryLogCurrentException(logger, start_of_message);
      }
  }
  
  std::string getExceptionMessage(const Exception & e, bool with_stacktrace, bool check_embedded_stacktrace)
  {
      std::stringstream stream;
  
      try
      {
          std::string text = e.displayText();
  
          bool has_embedded_stack_trace = false;
          if (check_embedded_stacktrace)
          {
              auto embedded_stack_trace_pos = text.find("Stack trace");
              has_embedded_stack_trace = embedded_stack_trace_pos != std::string::npos;
              if (!with_stacktrace && has_embedded_stack_trace)
              {
                  text.resize(embedded_stack_trace_pos);
                  Poco::trimRightInPlace(text);
              }
          }
  
          stream << "Code: " << e.code() << ", e.displayText() = " << text << ", e.what() = " << e.what();
  
          if (with_stacktrace && !has_embedded_stack_trace)
              stream << ", Stack trace:\n\n" << e.getStackTrace().toString();
      }
      catch (...) {}
  
      return stream.str();
  }
  
  std::string getExceptionMessage(std::exception_ptr e, bool with_stacktrace)
  {
      try
      {
          std::rethrow_exception(std::move(e));
      }
      catch (...)
      {
          return getCurrentExceptionMessage(with_stacktrace);
      }
  }
  
  
  std::string ExecutionStatus::serializeText() const
  {
      WriteBufferFromOwnString wb;
      wb << code << "\n" << escape << message;
      return wb.str();
  }
  
  void ExecutionStatus::deserializeText(const std::string & data)
  {
      ReadBufferFromString rb(data);
      rb >> code >> "\n" >> escape >> message;
  }
  
  bool ExecutionStatus::tryDeserializeText(const std::string & data)
  {
      try
      {
          deserializeText(data);
      }
      catch (...)
      {
          return false;
      }
  
      return true;
  }
  
  ExecutionStatus ExecutionStatus::fromCurrentException(const std::string & start_of_message)
  {
      String msg = (start_of_message.empty() ? "" : (start_of_message + ": ")) + getCurrentExceptionMessage(false, true);
      return ExecutionStatus(getCurrentExceptionCode(), msg);
  }
  
  
  }
  