* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* Licensed 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 "status.h"
#include <iostream>
#include <map>
#include <thread>
#include <vector>
namespace functionsystem {
std::map<enum StatusCode, std::string> Status::statusInfoMap_ = {
{ FAILED, "Common error code" },
{ SUCCESS, "Ok" },
{ RESERVED, "Reserved error code" },
{ LOG_CONFIG_ERROR, "Log config error" },
{ PARAMETER_ERROR, "Parameter error" },
{ ENV_CONFIG_ERROR, "Env config error" },
{ REQUEST_TIME_OUT, "Request timeout error" },
{ RESOURCE_NOT_ENOUGH, "Instance schedule with resource not enough error" },
{ SCHEDULE_CONFLICTED, "Instance schedule conflict error" },
{ INSTANCE_ALLOCATED, "Instance was already been scheduled error" },
{ FILE_NOT_FOUND, "File not found error" },
{ JSON_PARSE_ERROR, "Json parse error" },
{ REGISTER_ERROR, "Register error" },
{ INVALID_RESOURCE_PARAMETER,
"invalid resource parameter, request resource is greater than each node's max resource" },
{ AFFINITY_SCHEDULE_FAILED, "affinity schedule failed"},
{ SYNC_GRPC_CALL_ERROR, "Failed to call grpc interface Sync" },
{ GRPC_CQ_ERROR, "Grpc completion queue return error" },
{ GRPC_CALL_OBJ_ERROR, "Failed to allocate grpc call object memory" },
{ GRPC_OK, "grpc OK" },
{ GRPC_CANCELLED, "grpc error cancel" },
{ GRPC_UNKNOWN, "grpc error unknown" },
{ GRPC_INVALID_ARGUMENT, "grpc error invalid argument" },
{ GRPC_DEADLINE_EXCEEDED, "grpc error deadline exceeded" },
{ GRPC_NOT_FOUND, "grpc error not found" },
{ GRPC_ALREADY_EXISTS, "grpc error already exists" },
{ GRPC_PERMISSION_DENIED, "grpc error permission denied" },
{ GRPC_RESOURCE_EXHAUSTED, "grpc error resource exhausted" },
{ GRPC_FAILED_PRECONDITION, "grpc error failed precondition" },
{ GRPC_ABORTED, "grpc error aborted" },
{ GRPC_OUT_OF_RANGE, "grpc error out of range" },
{ GRPC_UNIMPLEMENTED, "grpc error unimplemented" },
{ GRPC_INTERNAL, "grpc error internal" },
{ GRPC_UNAVAILABLE, "grpc error unavailable" },
{ GRPC_DATA_LOSS, "grpc error data loss" },
{ GRPC_UNAUTHENTICATED, "grpc error unauthenticated" },
{ BP_DATASYSTEM_ERROR, "Datasystem error in busproxy" },
{ BP_INSTANCE_NOT_FOUND, "Instance not found in busproxy" },
{ BP_META_STORAGE_PUT_ERROR, "Meta storage put error in busproxy" },
{ BP_META_STORAGE_DELETE_ERROR, "Meta storage delete error in busproxy" },
{ BP_META_STORAGE_REVOKE_ERROR, "Meta storage revoke error in busproxy" },
{ BP_LEASE_ID_NOT_FOUND, "Lease ID not found in busproxy" },
{ BP_PROXYACTOR_NULL, "Null proxy actor in client" },
{ BP_META_STORAGE_GRANT_ERROR, "Meta storage grant error in busproxy" },
{ INSTANCE_HEARTBEAT_LOST, "instance heart beat lost"},
{ INSTANCE_HEALTH_CHECK_ERROR, "instance heart beat check health failed" },
{ INSTANCE_SUB_HEALTH, "instance heart beat sub health" },
{ FA_HTTP_REGISTER_HANDLER_NULL_ERROR, "Try to register null handler" },
{ FA_HTTP_REGISTER_REPEAT_URL_ERROR, "Try to register the same url again" },
{ FA_REQUIRED_CPU_SIZE_INVALID, "Required CPU resource size is invalid" },
{ FA_REQUIRED_MEMORY_SIZE_INVALID, "Required memory resource size is invalid" },
{ FA_CPU_NOT_ENOUGH, "CPU resource not enough" },
{ FA_MEMORY_NOT_ENOUGH, "Memory resources not enough" },
{ FA_CUSTOM_RESOURCE_NOT_ENOUGH, "Custom resources not enough" },
{ FA_FUNCTION_META_NOT_EXISTED, "Function not existed in meta" },
{ FA_FUNCTION_META_EMPTY_CPU, "Function meta not contain CPU resources" },
{ FA_FUNCTION_META_EMPTY_MEMORY, "Function meta not contain memory resources" },
{ GS_GET_FROM_METASTORE_FAILED, "Failed to get from MetaStore in GlobalScheduler" },
{ GS_PUT_TO_METASTORE_FAILED, "Failed to put into MetaStore in GlobalScheduler" },
{ GS_SCHED_TOPOLOGY_BROKEN, "Scheduler topology stored in MetaStore is broken" },
{ GS_ACTIVATE_DOMAIN_FAILED, "Failed to activate domain scheduler" },
{ LS_DOMAIN_SCHEDULER_AID_EMPTY, "Domain scheduler aid is empty in local scheduler when registering" },
{ LS_GLOBAL_SCHEDULER_AID_EMPTY, "Global scheduler aid is empty in local scheduler when registering" },
{ LS_INSTANCE_CTRL_IS_NULL, "instance control is null in local scheduler" },
{ LS_META_STORE_ACCESSOR_IS_NULL, "meta store accessor is null in local scheduler" },
{ LS_SYNC_KILL_INSTANCE_FAIL, "instance ctrl failed to kill instance when sync instances" },
{ LS_SYNC_DEPLOY_INSTANCE_FAIL, "instance ctrl failed to deploy instance when sync instances" },
{ LS_SYNC_INSTANCE_FAIL, "instance ctrl failed to sync instances" },
{ LS_DEPLOY_INSTANCE_FAILED, "Failed to deploy instance in local scheduler" },
{ LS_RESOURCE_VIEW_IS_NULL, "resource view is null in local scheduler" },
{ LS_SYNC_INSTANCE_COMPLETE, "The sync instance has been completed" },
{ LS_REQUEST_NOT_FOUND, "The request of create not found" },
{ LS_UPDATE_INSTANCE_FAIL, "failed to update instance info to MetaStore" },
{ LS_AGENT_EVICTED, "failed to register, agent has been evicted" },
{ FUNC_AGENT_OBS_OPEN_FILE_ERROR, "Function agent failed to open obs file" },
{ FUNC_AGENT_OBS_GET_OBJECT_ERROR, "Function agent failed to get object from obs" },
{ FUNC_AGENT_PING_PONG_IS_NULL, "Function agent's ping pong driver is null" },
{ FUNC_AGENT_RESOURCE_UNIT_IS_NULL, "Function agent's resource unit is null" },
{ FUNC_AGENT_FAILED_DEPLOY, "Function agent failed to deploy code" },
{ FUNC_AGENT_DEPLOYMENT_CONFIG_NOT_FOUND, "Function agent failed to find deployment config for this request" },
{ FUNC_AGENT_START_HEARTBEAT_FAILED, "Function agent faield to start heartbeat observer" },
{ FUNC_AGENT_STATUS_VPC_PROBE_FAILED, "Function agent failed to probe network" },
{ FUNC_AGENT_OBS_CONNECTION_ERROR, "Function agent failed to connect to obs" },
{ RUNTIME_MANAGER_DISK_USAGE_EXCEED_LIMIT, "runtime manager disk usage exceed limit" },
};
std::map<enum StatusCode, enum StatusCode> Status::codeToPosix_ = {
{ PARAMETER_ERROR, ERR_PARAM_INVALID },
{ RESOURCE_NOT_ENOUGH, ERR_RESOURCE_NOT_ENOUGH },
{ SCHEDULE_CONFLICTED, ERR_RESOURCE_NOT_ENOUGH },
{ REQUEST_TIME_OUT, ERR_INNER_COMMUNICATION },
{ INSTANCE_SUB_HEALTH, ERR_INSTANCE_SUB_HEALTH },
{ AFFINITY_SCHEDULE_FAILED, ERR_RESOURCE_CONFIG_ERROR },
{ BP_INSTANCE_NOT_FOUND, ERR_INSTANCE_NOT_FOUND },
{ BP_META_STORAGE_PUT_ERROR, ERR_ETCD_OPERATION_ERROR },
{ INSTANCE_TRANSACTION_WRONG_VERSION, ERR_ETCD_OPERATION_ERROR },
{ BP_META_STORAGE_DELETE_ERROR, ERR_ETCD_OPERATION_ERROR },
{ BP_META_STORAGE_REVOKE_ERROR, ERR_ETCD_OPERATION_ERROR },
{ LS_UPDATE_INSTANCE_FAIL, ERR_ETCD_OPERATION_ERROR },
{ LS_DEPLOY_INSTANCE_FAILED, ERR_INNER_COMMUNICATION},
{ LS_FORWARD_INSTANCE_MANAGER_TIMEOUT, ERR_INNER_COMMUNICATION },
{ FUNC_AGENT_REQUEST_ID_ILLEGAL_ERROR, ERR_PARAM_INVALID },
{ FUNC_AGENT_INVALID_DEPLOYER_ERROR, ERR_PARAM_INVALID },
{ FUNC_AGENT_INVALID_TOKEN_ERROR, ERR_PARAM_INVALID },
{ FUNC_AGENT_INVALID_ACCESS_KEY_ERROR, ERR_PARAM_INVALID },
{ FUNC_AGENT_INVALID_SECRET_ACCESS_KEY_ERROR, ERR_PARAM_INVALID },
{ FUNC_AGENT_INVALID_WORKING_DIR_FILE, ERR_PARAM_INVALID },
{ FUNC_AGENT_UNSUPPORTED_WORKING_DIR_SCHEMA, ERR_PARAM_INVALID },
{ FUNC_AGENT_MKDIR_DEST_WORKING_DIR_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_SET_NETWORK_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_NETWORK_WORK_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_GET_OBJECT_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_INIT_OPTIONS_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_OPEN_FILE_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_ADD_BUCKET_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_DEL_BUCKET_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_PUT_OBJECT_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_GET_OBJECT_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_RENAME_TMP_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ FUNC_AGENT_OBS_CONNECTION_ERROR, ERR_FUNCTION_AGENT_OPERATION_ERROR },
{ RUNTIME_MANAGER_PARAMS_INVALID, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_BUILD_ARGS_INVALID, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_POST_START_EXEC_FAILED, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_MOUNT_VOLUME_FAILED, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_PORT_UNAVAILABLE, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_EXEC_PATH_NOT_FOUND, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_CREATE_EXEC_FAILED, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_EXECUTABLE_PATH_INVALID, ERR_PARAM_INVALID },
{ INVALID_RESOURCE_PARAMETER, ERR_RESOURCE_CONFIG_ERROR },
{ RUNTIME_MANAGER_STOP_INSTANCE_FAILED, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_START_INSTANCE_FAILED, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_WORKING_DIR_FOR_APP_NOTFOUND, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_DEPLOY_DIR_IS_EMPTY, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_DEBUG_SERVER_NOTFOUND, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_CONDA_PARAMS_INVALID, ERR_PARAM_INVALID },
{ RUNTIME_MANAGER_CONDA_ENV_FILE_WRITE_FAILED, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
{ RUNTIME_MANAGER_CONDA_ENV_NOT_EXIST, ERR_RUNTIME_MANAGER_OPERATION_ERROR },
};
common::ErrorCode Status::GetPosixErrorCode(enum StatusCode code)
{
if (NeedKeepStatusCode(code)) {
return static_cast<common::ErrorCode>(code);
}
const auto iter = codeToPosix_.find(code);
return static_cast<common::ErrorCode>(iter == codeToPosix_.end() ? StatusCode::ERR_INNER_SYSTEM_ERROR
: iter->second);
}
common::ErrorCode Status::GetPosixErrorCode(common::ErrorCode code)
{
return GetPosixErrorCode(static_cast<enum StatusCode>(code));
}
common::ErrorCode Status::GetPosixErrorCode(int32_t code)
{
return GetPosixErrorCode(static_cast<enum StatusCode>(code));
}
StatusCode Status::GrpcCode2StatusCode(int grpcErrCode)
{
return static_cast<enum StatusCode>(static_cast<int>(GRPC_OK) + grpcErrCode);
}
bool Status::NeedKeepStatusCode(enum StatusCode code)
{
const auto minPosixCode = static_cast<enum StatusCode>(1000);
const auto maxPosixCode = static_cast<enum StatusCode>(10000);
return code == SUCCESS || (code >= minPosixCode && code < maxPosixCode);
}
std::string Status::GetStatusInfo(enum StatusCode code)
{
const auto iter = statusInfoMap_.find(code);
return iter == statusInfoMap_.end() ? "" : iter->second;
}
struct Status::Data {
enum StatusCode statusCode = SUCCESS;
std::string statusInfo = GetStatusInfo(statusCode);
std::vector<std::string> detailInfo;
int lineOfCode = -1;
std::string fileName;
};
Status::Status() : data_(std::make_shared<Data>())
{
}
Status::Status(enum StatusCode statusCode, const std::string &errMsg) : data_(std::make_shared<Data>())
{
if (data_ == nullptr) {
return;
}
data_->statusCode = statusCode;
std::ostringstream ss;
#ifdef __DEBUG__
ss << "Thread ID " << std::this_thread::get_id() << " " << GetStatusInfo(statusCode);
#else
ss << GetStatusInfo(statusCode);
#endif
data_->statusInfo = ss.str();
if (!errMsg.empty()) {
data_->detailInfo.push_back(errMsg);
}
}
Status::Status(const enum StatusCode code, int lineOfCode, const char *fileName, const std::string &errMsg)
: data_(std::make_shared<Data>())
{
if (data_ == nullptr) {
return;
}
data_->statusCode = code;
data_->lineOfCode = lineOfCode;
if (!errMsg.empty()) {
data_->detailInfo.push_back(errMsg);
}
if (fileName != nullptr) {
data_->fileName = fileName;
}
std::ostringstream ss;
#ifdef __DEBUG__
ss << "Thread ID " << std::this_thread::get_id() << " " << GetStatusInfo(code);
#else
ss << GetStatusInfo(code);
#endif
ss << "\n";
ss << "Line of code : " << lineOfCode << "\n";
if (fileName != nullptr) {
ss << "File : " << fileName;
}
data_->statusInfo = ss.str();
}
std::string Status::ToString() const
{
if (data_ == nullptr) {
return "";
}
std::ostringstream ss;
ss << "[code: " << static_cast<int>(data_->statusCode) << ", status: " << data_->statusInfo;
if (data_->detailInfo.empty()) {
ss << "]";
return ss.str();
}
ss << "], detail: ";
for (auto &info : data_->detailInfo) {
ss << "[" << info << "]";
}
ss << "]";
return ss.str();
}
std::string Status::GetMessage() const
{
if (data_->detailInfo.empty()) {
return "[]";
}
std::ostringstream ss;
for (auto &info : data_->detailInfo) {
ss << "[" << info << "]";
}
return ss.str();
}
const std::string &Status::RawMessage() const
{
if (data_->detailInfo.empty()) {
static std::string nullStr;
return nullStr;
}
return data_->detailInfo[0];
}
bool Status::MultipleErr() const
{
if (data_->detailInfo.empty()) {
return false;
}
return data_->detailInfo.size() > 1;
}
void Status::AppendMessage(const std::string &errMsg)
{
if (data_ == nullptr) {
return;
}
data_->detailInfo.push_back(errMsg);
}
enum StatusCode Status::StatusCode() const
{
if (data_ == nullptr) {
return SUCCESS;
}
return data_->statusCode;
}
int Status::GetLineOfCode() const
{
if (data_ == nullptr) {
return -1;
}
return data_->lineOfCode;
}
std::ostream &operator<<(std::ostream &os, const Status &s)
{
os << s.ToString();
return os;
}
bool Status::operator==(const Status &other) const
{
if (data_ == nullptr || other.data_ == nullptr) {
return false;
}
if (data_ == nullptr && other.data_ == nullptr) {
return true;
}
return data_->statusCode == other.data_->statusCode;
}
bool Status::operator==(enum StatusCode otherCode) const
{
return StatusCode() == otherCode;
}
bool Status::operator!=(const Status &other) const
{
return !operator==(other);
}
bool Status::operator!=(enum StatusCode otherCode) const
{
return !operator==(otherCode);
}
Status::operator bool() const
{
return (StatusCode() == SUCCESS);
}
Status::operator int() const
{
return static_cast<int>(StatusCode());
}
Status Status::OK()
{
return {};
}
bool Status::IsOk() const
{
return (StatusCode() == StatusCode::SUCCESS);
}
bool Status::IsError() const
{
return !IsOk();
}
}