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