blob: 11976820bb87c30a0e169272aa192b2a3c608ef1 [file] [log] [blame]
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "kudu/util/status.h"
#include <cstdio>
#include <cstring>
#include <glog/logging.h>
#include "kudu/gutil/strings/fastmem.h"
#include "kudu/util/malloc.h"
namespace kudu {
const char* Status::CopyState(const char* state) {
uint32_t size;
strings::memcpy_inlined(&size, state, sizeof(size));
auto result = new char[size + 7];
strings::memcpy_inlined(result, state, size + 7);
return result;
}
Status::Status(Code code, const Slice& msg, const Slice& msg2,
int16_t posix_code) {
DCHECK(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = msg2.size();
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
auto result = new char[size + 7];
memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code);
memcpy(result + 5, &posix_code, sizeof(posix_code));
memcpy(result + 7, msg.data(), len1);
if (len2) {
result[7 + len1] = ':';
result[8 + len1] = ' ';
memcpy(result + 9 + len1, msg2.data(), len2);
}
state_ = result;
}
std::string Status::CodeAsString() const {
if (state_ == nullptr) {
return "OK";
}
const char* type;
switch (code()) {
case kOk:
type = "OK";
break;
case kNotFound:
type = "Not found";
break;
case kCorruption:
type = "Corruption";
break;
case kNotSupported:
type = "Not implemented";
break;
case kInvalidArgument:
type = "Invalid argument";
break;
case kIOError:
type = "IO error";
break;
case kAlreadyPresent:
type = "Already present";
break;
case kRuntimeError:
type = "Runtime error";
break;
case kNetworkError:
type = "Network error";
break;
case kIllegalState:
type = "Illegal state";
break;
case kNotAuthorized:
type = "Not authorized";
break;
case kAborted:
type = "Aborted";
break;
case kRemoteError:
type = "Remote error";
break;
case kServiceUnavailable:
type = "Service unavailable";
break;
case kTimedOut:
type = "Timed out";
break;
case kUninitialized:
type = "Uninitialized";
break;
case kConfigurationError:
type = "Configuration error";
break;
case kIncomplete:
type = "Incomplete";
break;
case kEndOfFile:
type = "End of file";
break;
}
return std::string(type);
}
std::string Status::ToString() const {
std::string result(CodeAsString());
if (state_ == nullptr) {
return result;
}
result.append(": ");
Slice msg = message();
result.append(reinterpret_cast<const char*>(msg.data()), msg.size());
int16_t posix = posix_code();
if (posix != -1) {
char buf[64];
snprintf(buf, sizeof(buf), " (error %d)", posix);
result.append(buf);
}
return result;
}
Slice Status::message() const {
if (state_ == nullptr) {
return Slice();
}
uint32_t length;
memcpy(&length, state_, sizeof(length));
return Slice(state_ + 7, length);
}
int16_t Status::posix_code() const {
if (state_ == nullptr) {
return 0;
}
int16_t posix_code;
memcpy(&posix_code, state_ + 5, sizeof(posix_code));
return posix_code;
}
Status Status::CloneAndPrepend(const Slice& msg) const {
if (ok()) {
return *this;
}
return Status(code(), msg, message(), posix_code());
}
Status Status::CloneAndAppend(const Slice& msg) const {
if (ok()) {
return *this;
}
return Status(code(), message(), msg, posix_code());
}
size_t Status::memory_footprint_excluding_this() const {
return state_ ? kudu_malloc_usable_size(state_) : 0;
}
size_t Status::memory_footprint_including_this() const {
return kudu_malloc_usable_size(this) + memory_footprint_excluding_this();
}
} // namespace kudu