| // 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 <boost/algorithm/string/join.hpp> |
| #include <ostream> |
| |
| #include "common/status.h" |
| |
| #include "util/debug-util.h" |
| #include "common/names.h" |
| #include "gen-cpp/common.pb.h" |
| #include "gen-cpp/ErrorCodes_types.h" |
| |
| using namespace apache::hive::service::cli::thrift; |
| |
| namespace impala { |
| |
| const char* Status::LLVM_CLASS_NAME = "class.impala::Status"; |
| |
| // NOTE: this is statically initialized and we must be very careful what |
| // functions these constructors call. In particular, we cannot call |
| // glog functions which also rely on static initializations. |
| // TODO: is there a more controlled way to do this. |
| const Status Status::CANCELLED(ErrorMsg::Init(TErrorCode::CANCELLED)); |
| |
| const Status Status::DEPRECATED_RPC(ErrorMsg::Init( |
| TErrorCode::NOT_IMPLEMENTED_ERROR, "Deprecated RPC; please update your client")); |
| |
| Status Status::MemLimitExceeded() { |
| return Status(ErrorMsg(TErrorCode::MEM_LIMIT_EXCEEDED, "Memory limit exceeded"), true); |
| } |
| |
| Status Status::MemLimitExceeded(const std::string& details) { |
| return Status(ErrorMsg(TErrorCode::MEM_LIMIT_EXCEEDED, |
| Substitute("Memory limit exceeded: $0", details)), true); |
| } |
| |
| Status Status::CancelledInternal(const char* subsystem) { |
| return Status(ErrorMsg::Init(TErrorCode::CANCELLED_INTERNALLY, subsystem)); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code) : msg_(new ErrorMsg(code)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0) |
| : msg_(new ErrorMsg(code, arg0)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status( |
| bool silent, TErrorCode::type code, const ArgType& arg0, const ArgType& arg1) |
| : msg_(new ErrorMsg(code, arg0, arg1)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, |
| const ArgType& arg5) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4, arg5)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, |
| const ArgType& arg5, const ArgType& arg6) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4, arg5, arg6)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, |
| const ArgType& arg5, const ArgType& arg6, const ArgType& arg7) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, |
| const ArgType& arg5, const ArgType& arg6, const ArgType& arg7, const ArgType& arg8) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(bool silent, TErrorCode::type code, const ArgType& arg0, |
| const ArgType& arg1, const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, |
| const ArgType& arg5, const ArgType& arg6, const ArgType& arg7, const ArgType& arg8, |
| const ArgType& arg9) |
| : msg_(new ErrorMsg(code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)) { |
| if (!silent) VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(const string& error_msg) |
| : msg_(new ErrorMsg(TErrorCode::GENERAL, error_msg)) { |
| VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| |
| Status::Status(const ErrorMsg& error_msg, bool silent) |
| : msg_(new ErrorMsg(error_msg)) { |
| if (!silent) { |
| VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| } |
| |
| Status::Status(const string& error_msg, bool silent) |
| : msg_(new ErrorMsg(TErrorCode::GENERAL, error_msg)) { |
| if (!silent) { |
| VLOG(1) << msg_->msg() << "\n" << GetStackTrace(); |
| } |
| } |
| |
| Status::Status(const ErrorMsg& message) |
| : msg_(new ErrorMsg(message)) { } |
| |
| Status::Status(const TStatus& status) { |
| FromThrift(status); |
| } |
| |
| Status::Status(const StatusPB& status) { |
| FromProto(status); |
| } |
| |
| Status& Status::operator=(const TStatus& status) { |
| delete msg_; |
| FromThrift(status); |
| return *this; |
| } |
| |
| Status::Status(const apache::hive::service::cli::thrift::TStatus& hs2_status) |
| : msg_(hs2_status.statusCode == TStatusCode::SUCCESS_STATUS |
| || hs2_status.statusCode == TStatusCode::STILL_EXECUTING_STATUS ? |
| NULL : |
| new ErrorMsg(HS2TStatusCodeToTErrorCode(hs2_status.statusCode), |
| hs2_status.errorMessage)) {} |
| |
| Status Status::Expected(const ErrorMsg& error_msg) { |
| return Status(error_msg, true); |
| } |
| |
| Status Status::Expected(const std::string& error_msg) { |
| return Status(error_msg, true); |
| } |
| |
| Status Status::Expected(TErrorCode::type code) { |
| return Status(true, code); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0) { |
| return Status(true, code, arg0); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1) { |
| return Status(true, code, arg0, arg1); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2) { |
| return Status(true, code, arg0, arg1, arg2); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3) { |
| return Status(true, code, arg0, arg1, arg2, arg3); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, const ArgType& arg5) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4, arg5); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, const ArgType& arg5, |
| const ArgType& arg6) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4, arg5, arg6); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, const ArgType& arg5, |
| const ArgType& arg6, const ArgType& arg7) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, const ArgType& arg5, |
| const ArgType& arg6, const ArgType& arg7, const ArgType& arg8) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); |
| } |
| |
| Status Status::Expected(TErrorCode::type code, const ArgType& arg0, const ArgType& arg1, |
| const ArgType& arg2, const ArgType& arg3, const ArgType& arg4, const ArgType& arg5, |
| const ArgType& arg6, const ArgType& arg7, const ArgType& arg8, const ArgType& arg9) { |
| return Status(true, code, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); |
| } |
| |
| void Status::AddDetail(const std::string& msg) { |
| DCHECK(msg_ != NULL); |
| msg_->AddDetail(msg); |
| VLOG(2) << msg; |
| } |
| |
| void Status::MergeStatus(const Status& status) { |
| if (status.ok()) return; |
| if (msg_ == NULL) { |
| msg_ = new ErrorMsg(*status.msg_); |
| } else { |
| msg_->AddDetail(status.msg().msg()); |
| for (const string& s: status.msg_->details()) msg_->AddDetail(s); |
| } |
| } |
| |
| const string Status::GetDetail() const { |
| return msg_ != NULL ? msg_->GetFullMessageDetails() : ""; |
| } |
| |
| void Status::ToThrift(TStatus* status) const { |
| status->error_msgs.clear(); |
| if (msg_ == nullptr) { |
| status->status_code = TErrorCode::OK; |
| } else { |
| status->status_code = msg_->error(); |
| status->error_msgs.push_back(msg_->msg()); |
| for (const string& s: msg_->details()) status->error_msgs.push_back(s); |
| status->__isset.error_msgs = true; |
| } |
| } |
| |
| void Status::ToProto(StatusPB* status) const { |
| status->Clear(); |
| if (msg_ == nullptr) { |
| status->set_status_code(TErrorCode::OK); |
| } else { |
| status->set_status_code(msg_->error()); |
| status->add_error_msgs(msg_->msg()); |
| for (const string& s : msg_->details()) status->add_error_msgs(s); |
| } |
| } |
| |
| void Status::FromThrift(const TStatus& status) { |
| if (status.status_code == TErrorCode::OK) { |
| msg_ = NULL; |
| } else { |
| msg_ = new ErrorMsg(); |
| msg_->SetErrorCode(status.status_code); |
| if (status.error_msgs.size() > 0) { |
| // The first message is the actual error message. (See Status::ToThrift()). |
| msg_->SetErrorMsg(status.error_msgs.front()); |
| // The following messages are details. |
| std::for_each(status.error_msgs.begin() + 1, status.error_msgs.end(), |
| [&](string const& detail) { msg_->AddDetail(detail); }); |
| } |
| } |
| } |
| |
| void Status::FromProto(const StatusPB& status) { |
| if (status.status_code() == TErrorCode::OK) { |
| msg_ = nullptr; |
| } else { |
| msg_ = new ErrorMsg(); |
| msg_->SetErrorCode(static_cast<TErrorCode::type>(status.status_code())); |
| if (status.error_msgs().size() > 0) { |
| // The first message is the actual error message. (See Status::ToThrift()). |
| msg_->SetErrorMsg(status.error_msgs().Get(0)); |
| // The following messages are details. |
| std::for_each(status.error_msgs().begin() + 1, status.error_msgs().end(), |
| [&](string const& detail) { msg_->AddDetail(detail); }); |
| } |
| } |
| } |
| |
| void Status::FreeMessage() noexcept { |
| delete msg_; |
| } |
| |
| void Status::CopyMessageFrom(const Status& status) noexcept { |
| delete msg_; |
| msg_ = status.msg_ == NULL ? NULL : new ErrorMsg(*status.msg_); |
| } |
| |
| ostream& operator<<(ostream& os, const Status& status) { |
| os << _TErrorCode_VALUES_TO_NAMES.at(status.code()); |
| if (!status.ok()) os << ": " << status.GetDetail(); |
| return os; |
| } |
| |
| } |