status.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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 <cassert>
  17. #include <utility>
  18. #include "y_absl/base/internal/raw_logging.h"
  19. #include "y_absl/base/internal/strerror.h"
  20. #include "y_absl/base/macros.h"
  21. #include "y_absl/debugging/stacktrace.h"
  22. #include "y_absl/debugging/symbolize.h"
  23. #include "y_absl/status/status_payload_printer.h"
  24. #include "y_absl/strings/escaping.h"
  25. #include "y_absl/strings/str_cat.h"
  26. #include "y_absl/strings/str_format.h"
  27. #include "y_absl/strings/str_split.h"
  28. namespace y_absl {
  29. Y_ABSL_NAMESPACE_BEGIN
  30. TString StatusCodeToString(StatusCode code) {
  31. switch (code) {
  32. case StatusCode::kOk:
  33. return "OK";
  34. case StatusCode::kCancelled:
  35. return "CANCELLED";
  36. case StatusCode::kUnknown:
  37. return "UNKNOWN";
  38. case StatusCode::kInvalidArgument:
  39. return "INVALID_ARGUMENT";
  40. case StatusCode::kDeadlineExceeded:
  41. return "DEADLINE_EXCEEDED";
  42. case StatusCode::kNotFound:
  43. return "NOT_FOUND";
  44. case StatusCode::kAlreadyExists:
  45. return "ALREADY_EXISTS";
  46. case StatusCode::kPermissionDenied:
  47. return "PERMISSION_DENIED";
  48. case StatusCode::kUnauthenticated:
  49. return "UNAUTHENTICATED";
  50. case StatusCode::kResourceExhausted:
  51. return "RESOURCE_EXHAUSTED";
  52. case StatusCode::kFailedPrecondition:
  53. return "FAILED_PRECONDITION";
  54. case StatusCode::kAborted:
  55. return "ABORTED";
  56. case StatusCode::kOutOfRange:
  57. return "OUT_OF_RANGE";
  58. case StatusCode::kUnimplemented:
  59. return "UNIMPLEMENTED";
  60. case StatusCode::kInternal:
  61. return "INTERNAL";
  62. case StatusCode::kUnavailable:
  63. return "UNAVAILABLE";
  64. case StatusCode::kDataLoss:
  65. return "DATA_LOSS";
  66. default:
  67. return "";
  68. }
  69. }
  70. std::ostream& operator<<(std::ostream& os, StatusCode code) {
  71. return os << StatusCodeToString(code);
  72. }
  73. namespace status_internal {
  74. static y_absl::optional<size_t> FindPayloadIndexByUrl(
  75. const Payloads* payloads, y_absl::string_view type_url) {
  76. if (payloads == nullptr) return y_absl::nullopt;
  77. for (size_t i = 0; i < payloads->size(); ++i) {
  78. if ((*payloads)[i].type_url == type_url) return i;
  79. }
  80. return y_absl::nullopt;
  81. }
  82. // Convert canonical code to a value known to this binary.
  83. y_absl::StatusCode MapToLocalCode(int value) {
  84. y_absl::StatusCode code = static_cast<y_absl::StatusCode>(value);
  85. switch (code) {
  86. case y_absl::StatusCode::kOk:
  87. case y_absl::StatusCode::kCancelled:
  88. case y_absl::StatusCode::kUnknown:
  89. case y_absl::StatusCode::kInvalidArgument:
  90. case y_absl::StatusCode::kDeadlineExceeded:
  91. case y_absl::StatusCode::kNotFound:
  92. case y_absl::StatusCode::kAlreadyExists:
  93. case y_absl::StatusCode::kPermissionDenied:
  94. case y_absl::StatusCode::kResourceExhausted:
  95. case y_absl::StatusCode::kFailedPrecondition:
  96. case y_absl::StatusCode::kAborted:
  97. case y_absl::StatusCode::kOutOfRange:
  98. case y_absl::StatusCode::kUnimplemented:
  99. case y_absl::StatusCode::kInternal:
  100. case y_absl::StatusCode::kUnavailable:
  101. case y_absl::StatusCode::kDataLoss:
  102. case y_absl::StatusCode::kUnauthenticated:
  103. return code;
  104. default:
  105. return y_absl::StatusCode::kUnknown;
  106. }
  107. }
  108. } // namespace status_internal
  109. y_absl::optional<y_absl::Cord> Status::GetPayload(
  110. y_absl::string_view type_url) const {
  111. const auto* payloads = GetPayloads();
  112. y_absl::optional<size_t> index =
  113. status_internal::FindPayloadIndexByUrl(payloads, type_url);
  114. if (index.has_value()) return (*payloads)[index.value()].payload;
  115. return y_absl::nullopt;
  116. }
  117. void Status::SetPayload(y_absl::string_view type_url, y_absl::Cord payload) {
  118. if (ok()) return;
  119. PrepareToModify();
  120. status_internal::StatusRep* rep = RepToPointer(rep_);
  121. if (!rep->payloads) {
  122. rep->payloads = y_absl::make_unique<status_internal::Payloads>();
  123. }
  124. y_absl::optional<size_t> index =
  125. status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url);
  126. if (index.has_value()) {
  127. (*rep->payloads)[index.value()].payload = std::move(payload);
  128. return;
  129. }
  130. rep->payloads->push_back({TString(type_url), std::move(payload)});
  131. }
  132. bool Status::ErasePayload(y_absl::string_view type_url) {
  133. y_absl::optional<size_t> index =
  134. status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
  135. if (index.has_value()) {
  136. PrepareToModify();
  137. GetPayloads()->erase(GetPayloads()->begin() + index.value());
  138. if (GetPayloads()->empty() && message().empty()) {
  139. // Special case: If this can be represented inlined, it MUST be
  140. // inlined (EqualsSlow depends on this behavior).
  141. StatusCode c = static_cast<StatusCode>(raw_code());
  142. Unref(rep_);
  143. rep_ = CodeToInlinedRep(c);
  144. }
  145. return true;
  146. }
  147. return false;
  148. }
  149. void Status::ForEachPayload(
  150. y_absl::FunctionRef<void(y_absl::string_view, const y_absl::Cord&)> visitor)
  151. const {
  152. if (auto* payloads = GetPayloads()) {
  153. bool in_reverse =
  154. payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
  155. for (size_t index = 0; index < payloads->size(); ++index) {
  156. const auto& elem =
  157. (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
  158. #ifdef NDEBUG
  159. visitor(elem.type_url, elem.payload);
  160. #else
  161. // In debug mode invalidate the type url to prevent users from relying on
  162. // this string lifetime.
  163. // NOLINTNEXTLINE intentional extra conversion to force temporary.
  164. visitor(TString(elem.type_url), elem.payload);
  165. #endif // NDEBUG
  166. }
  167. }
  168. }
  169. const TString* Status::EmptyString() {
  170. static union EmptyString {
  171. TString str;
  172. ~EmptyString() {}
  173. } empty = {{}};
  174. return &empty.str;
  175. }
  176. #ifdef Y_ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
  177. constexpr const char Status::kMovedFromString[];
  178. #endif
  179. const TString* Status::MovedFromString() {
  180. static TString* moved_from_string = new TString(kMovedFromString);
  181. return moved_from_string;
  182. }
  183. void Status::UnrefNonInlined(uintptr_t rep) {
  184. status_internal::StatusRep* r = RepToPointer(rep);
  185. // Fast path: if ref==1, there is no need for a RefCountDec (since
  186. // this is the only reference and therefore no other thread is
  187. // allowed to be mucking with r).
  188. if (r->ref.load(std::memory_order_acquire) == 1 ||
  189. r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) {
  190. delete r;
  191. }
  192. }
  193. Status::Status(y_absl::StatusCode code, y_absl::string_view msg)
  194. : rep_(CodeToInlinedRep(code)) {
  195. if (code != y_absl::StatusCode::kOk && !msg.empty()) {
  196. rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
  197. }
  198. }
  199. int Status::raw_code() const {
  200. if (IsInlined(rep_)) {
  201. return static_cast<int>(InlinedRepToCode(rep_));
  202. }
  203. status_internal::StatusRep* rep = RepToPointer(rep_);
  204. return static_cast<int>(rep->code);
  205. }
  206. y_absl::StatusCode Status::code() const {
  207. return status_internal::MapToLocalCode(raw_code());
  208. }
  209. void Status::PrepareToModify() {
  210. Y_ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
  211. if (IsInlined(rep_)) {
  212. rep_ = PointerToRep(new status_internal::StatusRep(
  213. static_cast<y_absl::StatusCode>(raw_code()), y_absl::string_view(),
  214. nullptr));
  215. return;
  216. }
  217. uintptr_t rep_i = rep_;
  218. status_internal::StatusRep* rep = RepToPointer(rep_);
  219. if (rep->ref.load(std::memory_order_acquire) != 1) {
  220. std::unique_ptr<status_internal::Payloads> payloads;
  221. if (rep->payloads) {
  222. payloads = y_absl::make_unique<status_internal::Payloads>(*rep->payloads);
  223. }
  224. status_internal::StatusRep* const new_rep = new status_internal::StatusRep(
  225. rep->code, message(), std::move(payloads));
  226. rep_ = PointerToRep(new_rep);
  227. UnrefNonInlined(rep_i);
  228. }
  229. }
  230. bool Status::EqualsSlow(const y_absl::Status& a, const y_absl::Status& b) {
  231. if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false;
  232. if (a.message() != b.message()) return false;
  233. if (a.raw_code() != b.raw_code()) return false;
  234. if (a.GetPayloads() == b.GetPayloads()) return true;
  235. const status_internal::Payloads no_payloads;
  236. const status_internal::Payloads* larger_payloads =
  237. a.GetPayloads() ? a.GetPayloads() : &no_payloads;
  238. const status_internal::Payloads* smaller_payloads =
  239. b.GetPayloads() ? b.GetPayloads() : &no_payloads;
  240. if (larger_payloads->size() < smaller_payloads->size()) {
  241. std::swap(larger_payloads, smaller_payloads);
  242. }
  243. if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false;
  244. // Payloads can be ordered differently, so we can't just compare payload
  245. // vectors.
  246. for (const auto& payload : *larger_payloads) {
  247. bool found = false;
  248. for (const auto& other_payload : *smaller_payloads) {
  249. if (payload.type_url == other_payload.type_url) {
  250. if (payload.payload != other_payload.payload) {
  251. return false;
  252. }
  253. found = true;
  254. break;
  255. }
  256. }
  257. if (!found) return false;
  258. }
  259. return true;
  260. }
  261. TString Status::ToStringSlow(StatusToStringMode mode) const {
  262. TString text;
  263. y_absl::StrAppend(&text, y_absl::StatusCodeToString(code()), ": ", message());
  264. const bool with_payload = (mode & StatusToStringMode::kWithPayload) ==
  265. StatusToStringMode::kWithPayload;
  266. if (with_payload) {
  267. status_internal::StatusPayloadPrinter printer =
  268. status_internal::GetStatusPayloadPrinter();
  269. this->ForEachPayload([&](y_absl::string_view type_url,
  270. const y_absl::Cord& payload) {
  271. y_absl::optional<TString> result;
  272. if (printer) result = printer(type_url, payload);
  273. y_absl::StrAppend(
  274. &text, " [", type_url, "='",
  275. result.has_value() ? *result : y_absl::CHexEscape(TString(payload)),
  276. "']");
  277. });
  278. }
  279. return text;
  280. }
  281. std::ostream& operator<<(std::ostream& os, const Status& x) {
  282. os << x.ToString(StatusToStringMode::kWithEverything);
  283. return os;
  284. }
  285. Status AbortedError(y_absl::string_view message) {
  286. return Status(y_absl::StatusCode::kAborted, message);
  287. }
  288. Status AlreadyExistsError(y_absl::string_view message) {
  289. return Status(y_absl::StatusCode::kAlreadyExists, message);
  290. }
  291. Status CancelledError(y_absl::string_view message) {
  292. return Status(y_absl::StatusCode::kCancelled, message);
  293. }
  294. Status DataLossError(y_absl::string_view message) {
  295. return Status(y_absl::StatusCode::kDataLoss, message);
  296. }
  297. Status DeadlineExceededError(y_absl::string_view message) {
  298. return Status(y_absl::StatusCode::kDeadlineExceeded, message);
  299. }
  300. Status FailedPreconditionError(y_absl::string_view message) {
  301. return Status(y_absl::StatusCode::kFailedPrecondition, message);
  302. }
  303. Status InternalError(y_absl::string_view message) {
  304. return Status(y_absl::StatusCode::kInternal, message);
  305. }
  306. Status InvalidArgumentError(y_absl::string_view message) {
  307. return Status(y_absl::StatusCode::kInvalidArgument, message);
  308. }
  309. Status NotFoundError(y_absl::string_view message) {
  310. return Status(y_absl::StatusCode::kNotFound, message);
  311. }
  312. Status OutOfRangeError(y_absl::string_view message) {
  313. return Status(y_absl::StatusCode::kOutOfRange, message);
  314. }
  315. Status PermissionDeniedError(y_absl::string_view message) {
  316. return Status(y_absl::StatusCode::kPermissionDenied, message);
  317. }
  318. Status ResourceExhaustedError(y_absl::string_view message) {
  319. return Status(y_absl::StatusCode::kResourceExhausted, message);
  320. }
  321. Status UnauthenticatedError(y_absl::string_view message) {
  322. return Status(y_absl::StatusCode::kUnauthenticated, message);
  323. }
  324. Status UnavailableError(y_absl::string_view message) {
  325. return Status(y_absl::StatusCode::kUnavailable, message);
  326. }
  327. Status UnimplementedError(y_absl::string_view message) {
  328. return Status(y_absl::StatusCode::kUnimplemented, message);
  329. }
  330. Status UnknownError(y_absl::string_view message) {
  331. return Status(y_absl::StatusCode::kUnknown, message);
  332. }
  333. bool IsAborted(const Status& status) {
  334. return status.code() == y_absl::StatusCode::kAborted;
  335. }
  336. bool IsAlreadyExists(const Status& status) {
  337. return status.code() == y_absl::StatusCode::kAlreadyExists;
  338. }
  339. bool IsCancelled(const Status& status) {
  340. return status.code() == y_absl::StatusCode::kCancelled;
  341. }
  342. bool IsDataLoss(const Status& status) {
  343. return status.code() == y_absl::StatusCode::kDataLoss;
  344. }
  345. bool IsDeadlineExceeded(const Status& status) {
  346. return status.code() == y_absl::StatusCode::kDeadlineExceeded;
  347. }
  348. bool IsFailedPrecondition(const Status& status) {
  349. return status.code() == y_absl::StatusCode::kFailedPrecondition;
  350. }
  351. bool IsInternal(const Status& status) {
  352. return status.code() == y_absl::StatusCode::kInternal;
  353. }
  354. bool IsInvalidArgument(const Status& status) {
  355. return status.code() == y_absl::StatusCode::kInvalidArgument;
  356. }
  357. bool IsNotFound(const Status& status) {
  358. return status.code() == y_absl::StatusCode::kNotFound;
  359. }
  360. bool IsOutOfRange(const Status& status) {
  361. return status.code() == y_absl::StatusCode::kOutOfRange;
  362. }
  363. bool IsPermissionDenied(const Status& status) {
  364. return status.code() == y_absl::StatusCode::kPermissionDenied;
  365. }
  366. bool IsResourceExhausted(const Status& status) {
  367. return status.code() == y_absl::StatusCode::kResourceExhausted;
  368. }
  369. bool IsUnauthenticated(const Status& status) {
  370. return status.code() == y_absl::StatusCode::kUnauthenticated;
  371. }
  372. bool IsUnavailable(const Status& status) {
  373. return status.code() == y_absl::StatusCode::kUnavailable;
  374. }
  375. bool IsUnimplemented(const Status& status) {
  376. return status.code() == y_absl::StatusCode::kUnimplemented;
  377. }
  378. bool IsUnknown(const Status& status) {
  379. return status.code() == y_absl::StatusCode::kUnknown;
  380. }
  381. StatusCode ErrnoToStatusCode(int error_number) {
  382. switch (error_number) {
  383. case 0:
  384. return StatusCode::kOk;
  385. case EINVAL: // Invalid argument
  386. case ENAMETOOLONG: // Filename too long
  387. case E2BIG: // Argument list too long
  388. case EDESTADDRREQ: // Destination address required
  389. case EDOM: // Mathematics argument out of domain of function
  390. case EFAULT: // Bad address
  391. case EILSEQ: // Illegal byte sequence
  392. case ENOPROTOOPT: // Protocol not available
  393. case ENOSTR: // Not a STREAM
  394. case ENOTSOCK: // Not a socket
  395. case ENOTTY: // Inappropriate I/O control operation
  396. case EPROTOTYPE: // Protocol wrong type for socket
  397. case ESPIPE: // Invalid seek
  398. return StatusCode::kInvalidArgument;
  399. case ETIMEDOUT: // Connection timed out
  400. case ETIME: // Timer expired
  401. return StatusCode::kDeadlineExceeded;
  402. case ENODEV: // No such device
  403. case ENOENT: // No such file or directory
  404. #ifdef ENOMEDIUM
  405. case ENOMEDIUM: // No medium found
  406. #endif
  407. case ENXIO: // No such device or address
  408. case ESRCH: // No such process
  409. return StatusCode::kNotFound;
  410. case EEXIST: // File exists
  411. case EADDRNOTAVAIL: // Address not available
  412. case EALREADY: // Connection already in progress
  413. #ifdef ENOTUNIQ
  414. case ENOTUNIQ: // Name not unique on network
  415. #endif
  416. return StatusCode::kAlreadyExists;
  417. case EPERM: // Operation not permitted
  418. case EACCES: // Permission denied
  419. #ifdef ENOKEY
  420. case ENOKEY: // Required key not available
  421. #endif
  422. case EROFS: // Read only file system
  423. return StatusCode::kPermissionDenied;
  424. case ENOTEMPTY: // Directory not empty
  425. case EISDIR: // Is a directory
  426. case ENOTDIR: // Not a directory
  427. case EADDRINUSE: // Address already in use
  428. case EBADF: // Invalid file descriptor
  429. #ifdef EBADFD
  430. case EBADFD: // File descriptor in bad state
  431. #endif
  432. case EBUSY: // Device or resource busy
  433. case ECHILD: // No child processes
  434. case EISCONN: // Socket is connected
  435. #ifdef EISNAM
  436. case EISNAM: // Is a named type file
  437. #endif
  438. #ifdef ENOTBLK
  439. case ENOTBLK: // Block device required
  440. #endif
  441. case ENOTCONN: // The socket is not connected
  442. case EPIPE: // Broken pipe
  443. #ifdef ESHUTDOWN
  444. case ESHUTDOWN: // Cannot send after transport endpoint shutdown
  445. #endif
  446. case ETXTBSY: // Text file busy
  447. #ifdef EUNATCH
  448. case EUNATCH: // Protocol driver not attached
  449. #endif
  450. return StatusCode::kFailedPrecondition;
  451. case ENOSPC: // No space left on device
  452. #ifdef EDQUOT
  453. case EDQUOT: // Disk quota exceeded
  454. #endif
  455. case EMFILE: // Too many open files
  456. case EMLINK: // Too many links
  457. case ENFILE: // Too many open files in system
  458. case ENOBUFS: // No buffer space available
  459. case ENODATA: // No message is available on the STREAM read queue
  460. case ENOMEM: // Not enough space
  461. case ENOSR: // No STREAM resources
  462. #ifdef EUSERS
  463. case EUSERS: // Too many users
  464. #endif
  465. return StatusCode::kResourceExhausted;
  466. #ifdef ECHRNG
  467. case ECHRNG: // Channel number out of range
  468. #endif
  469. case EFBIG: // File too large
  470. case EOVERFLOW: // Value too large to be stored in data type
  471. case ERANGE: // Result too large
  472. return StatusCode::kOutOfRange;
  473. #ifdef ENOPKG
  474. case ENOPKG: // Package not installed
  475. #endif
  476. case ENOSYS: // Function not implemented
  477. case ENOTSUP: // Operation not supported
  478. case EAFNOSUPPORT: // Address family not supported
  479. #ifdef EPFNOSUPPORT
  480. case EPFNOSUPPORT: // Protocol family not supported
  481. #endif
  482. case EPROTONOSUPPORT: // Protocol not supported
  483. #ifdef ESOCKTNOSUPPORT
  484. case ESOCKTNOSUPPORT: // Socket type not supported
  485. #endif
  486. case EXDEV: // Improper link
  487. return StatusCode::kUnimplemented;
  488. case EAGAIN: // Resource temporarily unavailable
  489. #ifdef ECOMM
  490. case ECOMM: // Communication error on send
  491. #endif
  492. case ECONNREFUSED: // Connection refused
  493. case ECONNABORTED: // Connection aborted
  494. case ECONNRESET: // Connection reset
  495. case EINTR: // Interrupted function call
  496. #ifdef EHOSTDOWN
  497. case EHOSTDOWN: // Host is down
  498. #endif
  499. case EHOSTUNREACH: // Host is unreachable
  500. case ENETDOWN: // Network is down
  501. case ENETRESET: // Connection aborted by network
  502. case ENETUNREACH: // Network unreachable
  503. case ENOLCK: // No locks available
  504. case ENOLINK: // Link has been severed
  505. #ifdef ENONET
  506. case ENONET: // Machine is not on the network
  507. #endif
  508. return StatusCode::kUnavailable;
  509. case EDEADLK: // Resource deadlock avoided
  510. #ifdef ESTALE
  511. case ESTALE: // Stale file handle
  512. #endif
  513. return StatusCode::kAborted;
  514. case ECANCELED: // Operation cancelled
  515. return StatusCode::kCancelled;
  516. default:
  517. return StatusCode::kUnknown;
  518. }
  519. }
  520. namespace {
  521. TString MessageForErrnoToStatus(int error_number,
  522. y_absl::string_view message) {
  523. return y_absl::StrCat(message, ": ",
  524. y_absl::base_internal::StrError(error_number));
  525. }
  526. } // namespace
  527. Status ErrnoToStatus(int error_number, y_absl::string_view message) {
  528. return Status(ErrnoToStatusCode(error_number),
  529. MessageForErrnoToStatus(error_number, message));
  530. }
  531. namespace status_internal {
  532. TString* MakeCheckFailString(const y_absl::Status* status,
  533. const char* prefix) {
  534. return new TString(
  535. y_absl::StrCat(prefix, " (",
  536. status->ToString(StatusToStringMode::kWithEverything), ")"));
  537. }
  538. } // namespace status_internal
  539. const char* StatusMessageAsCStr(const Status& status) {
  540. // As an internal implementation detail, we guarantee that if status.message()
  541. // is non-empty, then the resulting string_view is null terminated.
  542. auto sv_message = status.message();
  543. return sv_message.empty() ? "" : sv_message.data();
  544. }
  545. Y_ABSL_NAMESPACE_END
  546. } // namespace y_absl