status.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // Copyright 2019 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "y_absl/status/status.h"
  15. #include <errno.h>
  16. #include <atomic>
  17. #include <cstddef>
  18. #include <cstdint>
  19. #include <cstring>
  20. #include <memory>
  21. #include <ostream>
  22. #include <util/generic/string.h>
  23. #include "y_absl/base/attributes.h"
  24. #include "y_absl/base/config.h"
  25. #include "y_absl/base/internal/raw_logging.h"
  26. #include "y_absl/base/internal/strerror.h"
  27. #include "y_absl/base/macros.h"
  28. #include "y_absl/base/no_destructor.h"
  29. #include "y_absl/base/nullability.h"
  30. #include "y_absl/debugging/stacktrace.h"
  31. #include "y_absl/debugging/symbolize.h"
  32. #include "y_absl/status/internal/status_internal.h"
  33. #include "y_absl/strings/str_cat.h"
  34. #include "y_absl/strings/str_format.h"
  35. #include "y_absl/strings/str_split.h"
  36. #include "y_absl/strings/string_view.h"
  37. #include "y_absl/types/optional.h"
  38. namespace y_absl {
  39. Y_ABSL_NAMESPACE_BEGIN
  40. static_assert(
  41. alignof(status_internal::StatusRep) >= 4,
  42. "y_absl::Status assumes it can use the bottom 2 bits of a StatusRep*.");
  43. TString StatusCodeToString(StatusCode code) {
  44. switch (code) {
  45. case StatusCode::kOk:
  46. return "OK";
  47. case StatusCode::kCancelled:
  48. return "CANCELLED";
  49. case StatusCode::kUnknown:
  50. return "UNKNOWN";
  51. case StatusCode::kInvalidArgument:
  52. return "INVALID_ARGUMENT";
  53. case StatusCode::kDeadlineExceeded:
  54. return "DEADLINE_EXCEEDED";
  55. case StatusCode::kNotFound:
  56. return "NOT_FOUND";
  57. case StatusCode::kAlreadyExists:
  58. return "ALREADY_EXISTS";
  59. case StatusCode::kPermissionDenied:
  60. return "PERMISSION_DENIED";
  61. case StatusCode::kUnauthenticated:
  62. return "UNAUTHENTICATED";
  63. case StatusCode::kResourceExhausted:
  64. return "RESOURCE_EXHAUSTED";
  65. case StatusCode::kFailedPrecondition:
  66. return "FAILED_PRECONDITION";
  67. case StatusCode::kAborted:
  68. return "ABORTED";
  69. case StatusCode::kOutOfRange:
  70. return "OUT_OF_RANGE";
  71. case StatusCode::kUnimplemented:
  72. return "UNIMPLEMENTED";
  73. case StatusCode::kInternal:
  74. return "INTERNAL";
  75. case StatusCode::kUnavailable:
  76. return "UNAVAILABLE";
  77. case StatusCode::kDataLoss:
  78. return "DATA_LOSS";
  79. default:
  80. return "";
  81. }
  82. }
  83. std::ostream& operator<<(std::ostream& os, StatusCode code) {
  84. return os << StatusCodeToString(code);
  85. }
  86. y_absl::Nonnull<const TString*> Status::EmptyString() {
  87. static const y_absl::NoDestructor<TString> kEmpty;
  88. return kEmpty.get();
  89. }
  90. #ifdef Y_ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
  91. constexpr const char Status::kMovedFromString[];
  92. #endif
  93. y_absl::Nonnull<const TString*> Status::MovedFromString() {
  94. static const y_absl::NoDestructor<TString> kMovedFrom(kMovedFromString);
  95. return kMovedFrom.get();
  96. }
  97. Status::Status(y_absl::StatusCode code, y_absl::string_view msg)
  98. : rep_(CodeToInlinedRep(code)) {
  99. if (code != y_absl::StatusCode::kOk && !msg.empty()) {
  100. rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
  101. }
  102. }
  103. y_absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify(
  104. uintptr_t rep) {
  105. if (IsInlined(rep)) {
  106. return new status_internal::StatusRep(InlinedRepToCode(rep),
  107. y_absl::string_view(), nullptr);
  108. }
  109. return RepToPointer(rep)->CloneAndUnref();
  110. }
  111. TString Status::ToStringSlow(uintptr_t rep, StatusToStringMode mode) {
  112. if (IsInlined(rep)) {
  113. return y_absl::StrCat(y_absl::StatusCodeToString(InlinedRepToCode(rep)), ": ");
  114. }
  115. return RepToPointer(rep)->ToString(mode);
  116. }
  117. std::ostream& operator<<(std::ostream& os, const Status& x) {
  118. os << x.ToString(StatusToStringMode::kWithEverything);
  119. return os;
  120. }
  121. Status AbortedError(y_absl::string_view message) {
  122. return Status(y_absl::StatusCode::kAborted, message);
  123. }
  124. Status AlreadyExistsError(y_absl::string_view message) {
  125. return Status(y_absl::StatusCode::kAlreadyExists, message);
  126. }
  127. Status CancelledError(y_absl::string_view message) {
  128. return Status(y_absl::StatusCode::kCancelled, message);
  129. }
  130. Status DataLossError(y_absl::string_view message) {
  131. return Status(y_absl::StatusCode::kDataLoss, message);
  132. }
  133. Status DeadlineExceededError(y_absl::string_view message) {
  134. return Status(y_absl::StatusCode::kDeadlineExceeded, message);
  135. }
  136. Status FailedPreconditionError(y_absl::string_view message) {
  137. return Status(y_absl::StatusCode::kFailedPrecondition, message);
  138. }
  139. Status InternalError(y_absl::string_view message) {
  140. return Status(y_absl::StatusCode::kInternal, message);
  141. }
  142. Status InvalidArgumentError(y_absl::string_view message) {
  143. return Status(y_absl::StatusCode::kInvalidArgument, message);
  144. }
  145. Status NotFoundError(y_absl::string_view message) {
  146. return Status(y_absl::StatusCode::kNotFound, message);
  147. }
  148. Status OutOfRangeError(y_absl::string_view message) {
  149. return Status(y_absl::StatusCode::kOutOfRange, message);
  150. }
  151. Status PermissionDeniedError(y_absl::string_view message) {
  152. return Status(y_absl::StatusCode::kPermissionDenied, message);
  153. }
  154. Status ResourceExhaustedError(y_absl::string_view message) {
  155. return Status(y_absl::StatusCode::kResourceExhausted, message);
  156. }
  157. Status UnauthenticatedError(y_absl::string_view message) {
  158. return Status(y_absl::StatusCode::kUnauthenticated, message);
  159. }
  160. Status UnavailableError(y_absl::string_view message) {
  161. return Status(y_absl::StatusCode::kUnavailable, message);
  162. }
  163. Status UnimplementedError(y_absl::string_view message) {
  164. return Status(y_absl::StatusCode::kUnimplemented, message);
  165. }
  166. Status UnknownError(y_absl::string_view message) {
  167. return Status(y_absl::StatusCode::kUnknown, message);
  168. }
  169. bool IsAborted(const Status& status) {
  170. return status.code() == y_absl::StatusCode::kAborted;
  171. }
  172. bool IsAlreadyExists(const Status& status) {
  173. return status.code() == y_absl::StatusCode::kAlreadyExists;
  174. }
  175. bool IsCancelled(const Status& status) {
  176. return status.code() == y_absl::StatusCode::kCancelled;
  177. }
  178. bool IsDataLoss(const Status& status) {
  179. return status.code() == y_absl::StatusCode::kDataLoss;
  180. }
  181. bool IsDeadlineExceeded(const Status& status) {
  182. return status.code() == y_absl::StatusCode::kDeadlineExceeded;
  183. }
  184. bool IsFailedPrecondition(const Status& status) {
  185. return status.code() == y_absl::StatusCode::kFailedPrecondition;
  186. }
  187. bool IsInternal(const Status& status) {
  188. return status.code() == y_absl::StatusCode::kInternal;
  189. }
  190. bool IsInvalidArgument(const Status& status) {
  191. return status.code() == y_absl::StatusCode::kInvalidArgument;
  192. }
  193. bool IsNotFound(const Status& status) {
  194. return status.code() == y_absl::StatusCode::kNotFound;
  195. }
  196. bool IsOutOfRange(const Status& status) {
  197. return status.code() == y_absl::StatusCode::kOutOfRange;
  198. }
  199. bool IsPermissionDenied(const Status& status) {
  200. return status.code() == y_absl::StatusCode::kPermissionDenied;
  201. }
  202. bool IsResourceExhausted(const Status& status) {
  203. return status.code() == y_absl::StatusCode::kResourceExhausted;
  204. }
  205. bool IsUnauthenticated(const Status& status) {
  206. return status.code() == y_absl::StatusCode::kUnauthenticated;
  207. }
  208. bool IsUnavailable(const Status& status) {
  209. return status.code() == y_absl::StatusCode::kUnavailable;
  210. }
  211. bool IsUnimplemented(const Status& status) {
  212. return status.code() == y_absl::StatusCode::kUnimplemented;
  213. }
  214. bool IsUnknown(const Status& status) {
  215. return status.code() == y_absl::StatusCode::kUnknown;
  216. }
  217. StatusCode ErrnoToStatusCode(int error_number) {
  218. switch (error_number) {
  219. case 0:
  220. return StatusCode::kOk;
  221. case EINVAL: // Invalid argument
  222. case ENAMETOOLONG: // Filename too long
  223. case E2BIG: // Argument list too long
  224. case EDESTADDRREQ: // Destination address required
  225. case EDOM: // Mathematics argument out of domain of function
  226. case EFAULT: // Bad address
  227. case EILSEQ: // Illegal byte sequence
  228. case ENOPROTOOPT: // Protocol not available
  229. case ENOSTR: // Not a STREAM
  230. case ENOTSOCK: // Not a socket
  231. case ENOTTY: // Inappropriate I/O control operation
  232. case EPROTOTYPE: // Protocol wrong type for socket
  233. case ESPIPE: // Invalid seek
  234. return StatusCode::kInvalidArgument;
  235. case ETIMEDOUT: // Connection timed out
  236. case ETIME: // Timer expired
  237. return StatusCode::kDeadlineExceeded;
  238. case ENODEV: // No such device
  239. case ENOENT: // No such file or directory
  240. #ifdef ENOMEDIUM
  241. case ENOMEDIUM: // No medium found
  242. #endif
  243. case ENXIO: // No such device or address
  244. case ESRCH: // No such process
  245. return StatusCode::kNotFound;
  246. case EEXIST: // File exists
  247. case EADDRNOTAVAIL: // Address not available
  248. case EALREADY: // Connection already in progress
  249. #ifdef ENOTUNIQ
  250. case ENOTUNIQ: // Name not unique on network
  251. #endif
  252. return StatusCode::kAlreadyExists;
  253. case EPERM: // Operation not permitted
  254. case EACCES: // Permission denied
  255. #ifdef ENOKEY
  256. case ENOKEY: // Required key not available
  257. #endif
  258. case EROFS: // Read only file system
  259. return StatusCode::kPermissionDenied;
  260. case ENOTEMPTY: // Directory not empty
  261. case EISDIR: // Is a directory
  262. case ENOTDIR: // Not a directory
  263. case EADDRINUSE: // Address already in use
  264. case EBADF: // Invalid file descriptor
  265. #ifdef EBADFD
  266. case EBADFD: // File descriptor in bad state
  267. #endif
  268. case EBUSY: // Device or resource busy
  269. case ECHILD: // No child processes
  270. case EISCONN: // Socket is connected
  271. #ifdef EISNAM
  272. case EISNAM: // Is a named type file
  273. #endif
  274. #ifdef ENOTBLK
  275. case ENOTBLK: // Block device required
  276. #endif
  277. case ENOTCONN: // The socket is not connected
  278. case EPIPE: // Broken pipe
  279. #ifdef ESHUTDOWN
  280. case ESHUTDOWN: // Cannot send after transport endpoint shutdown
  281. #endif
  282. case ETXTBSY: // Text file busy
  283. #ifdef EUNATCH
  284. case EUNATCH: // Protocol driver not attached
  285. #endif
  286. return StatusCode::kFailedPrecondition;
  287. case ENOSPC: // No space left on device
  288. #ifdef EDQUOT
  289. case EDQUOT: // Disk quota exceeded
  290. #endif
  291. case EMFILE: // Too many open files
  292. case EMLINK: // Too many links
  293. case ENFILE: // Too many open files in system
  294. case ENOBUFS: // No buffer space available
  295. case ENODATA: // No message is available on the STREAM read queue
  296. case ENOMEM: // Not enough space
  297. case ENOSR: // No STREAM resources
  298. #ifdef EUSERS
  299. case EUSERS: // Too many users
  300. #endif
  301. return StatusCode::kResourceExhausted;
  302. #ifdef ECHRNG
  303. case ECHRNG: // Channel number out of range
  304. #endif
  305. case EFBIG: // File too large
  306. case EOVERFLOW: // Value too large to be stored in data type
  307. case ERANGE: // Result too large
  308. return StatusCode::kOutOfRange;
  309. #ifdef ENOPKG
  310. case ENOPKG: // Package not installed
  311. #endif
  312. case ENOSYS: // Function not implemented
  313. case ENOTSUP: // Operation not supported
  314. case EAFNOSUPPORT: // Address family not supported
  315. #ifdef EPFNOSUPPORT
  316. case EPFNOSUPPORT: // Protocol family not supported
  317. #endif
  318. case EPROTONOSUPPORT: // Protocol not supported
  319. #ifdef ESOCKTNOSUPPORT
  320. case ESOCKTNOSUPPORT: // Socket type not supported
  321. #endif
  322. case EXDEV: // Improper link
  323. return StatusCode::kUnimplemented;
  324. case EAGAIN: // Resource temporarily unavailable
  325. #ifdef ECOMM
  326. case ECOMM: // Communication error on send
  327. #endif
  328. case ECONNREFUSED: // Connection refused
  329. case ECONNABORTED: // Connection aborted
  330. case ECONNRESET: // Connection reset
  331. case EINTR: // Interrupted function call
  332. #ifdef EHOSTDOWN
  333. case EHOSTDOWN: // Host is down
  334. #endif
  335. case EHOSTUNREACH: // Host is unreachable
  336. case ENETDOWN: // Network is down
  337. case ENETRESET: // Connection aborted by network
  338. case ENETUNREACH: // Network unreachable
  339. case ENOLCK: // No locks available
  340. case ENOLINK: // Link has been severed
  341. #ifdef ENONET
  342. case ENONET: // Machine is not on the network
  343. #endif
  344. return StatusCode::kUnavailable;
  345. case EDEADLK: // Resource deadlock avoided
  346. #ifdef ESTALE
  347. case ESTALE: // Stale file handle
  348. #endif
  349. return StatusCode::kAborted;
  350. case ECANCELED: // Operation cancelled
  351. return StatusCode::kCancelled;
  352. default:
  353. return StatusCode::kUnknown;
  354. }
  355. }
  356. namespace {
  357. TString MessageForErrnoToStatus(int error_number,
  358. y_absl::string_view message) {
  359. return y_absl::StrCat(message, ": ",
  360. y_absl::base_internal::StrError(error_number));
  361. }
  362. } // namespace
  363. Status ErrnoToStatus(int error_number, y_absl::string_view message) {
  364. return Status(ErrnoToStatusCode(error_number),
  365. MessageForErrnoToStatus(error_number, message));
  366. }
  367. y_absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) {
  368. // As an internal implementation detail, we guarantee that if status.message()
  369. // is non-empty, then the resulting string_view is null terminated.
  370. auto sv_message = status.message();
  371. return sv_message.empty() ? "" : sv_message.data();
  372. }
  373. Y_ABSL_NAMESPACE_END
  374. } // namespace y_absl