Kudu C++ client API
Loading...
Searching...
No Matches
status.h
Go to the documentation of this file.
1// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file. See the AUTHORS file for names of contributors.
4//
5// A Status encapsulates the result of an operation. It may indicate success,
6// or it may indicate an error with an associated error message.
7//
8// Multiple threads can invoke const methods on a Status without
9// external synchronization, but if any of the threads may call a
10// non-const method, all threads accessing the same Status must use
11// external synchronization.
12
13#ifndef KUDU_UTIL_STATUS_H_
14#define KUDU_UTIL_STATUS_H_
15
16// NOTE: using stdint.h instead of cstdint and errno.h instead of cerrno because
17// this file is supposed to be processed by a compiler lacking C++11 support.
18#include <errno.h>
19#include <stdint.h>
20
21#include <cstddef>
22#include <string>
23
24// This macro is not defined when status.h is consumed by third party applications.
25#ifdef KUDU_HEADERS_USE_SHORT_STATUS_MACROS
26#include <glog/logging.h>
27#endif
28
29#ifdef KUDU_HEADERS_NO_STUBS
30#include "kudu/gutil/macros.h"
31#include "kudu/gutil/port.h"
32#else
33#include "kudu/client/stubs.h"
34#endif
35
36#include "kudu/util/kudu_export.h"
37#include "kudu/util/slice.h"
38
40#define KUDU_RETURN_NOT_OK(s) do { \
41 const ::kudu::Status& _s = (s); \
42 if (PREDICT_FALSE(!_s.ok())) return _s; \
43 } while (0)
44
47#define KUDU_RETURN_NOT_OK_PREPEND(s, msg) do { \
48 const ::kudu::Status& _s = (s); \
49 if (PREDICT_FALSE(!_s.ok())) return _s.CloneAndPrepend(msg); \
50 } while (0)
51
55#define KUDU_RETURN_NOT_OK_RET(to_call, to_return) do { \
56 const ::kudu::Status& s = (to_call); \
57 if (PREDICT_FALSE(!s.ok())) return (to_return); \
58 } while (0)
59
61#define KUDU_RETURN_NOT_OK_EVAL(s, on_error) do { \
62 const ::kudu::Status& _s = (s); \
63 if (PREDICT_FALSE(!_s.ok())) { \
64 (on_error); \
65 return _s; \
66 } \
67 } while (0)
68
70#define KUDU_WARN_NOT_OK(to_call, warning_prefix) do { \
71 const ::kudu::Status& _s = (to_call); \
72 if (PREDICT_FALSE(!_s.ok())) { \
73 KUDU_LOG(WARNING) << (warning_prefix) << ": " << _s.ToString(); \
74 } \
75 } while (0)
76
78#define KUDU_LOG_AND_RETURN(level, status) do { \
79 const ::kudu::Status& _s = (status); \
80 KUDU_LOG(level) << _s.ToString(); \
81 return _s; \
82 } while (0)
83
85#define KUDU_RETURN_NOT_OK_LOG(s, level, msg) do { \
86 const ::kudu::Status& _s = (s); \
87 if (PREDICT_FALSE(!_s.ok())) { \
88 KUDU_LOG(level) << "Status: " << _s.ToString() << " " << (msg); \
89 return _s; \
90 } \
91 } while (0)
92
95#define KUDU_CHECK_OK_PREPEND(to_call, msg) do { \
96 const ::kudu::Status& _s = (to_call); \
97 KUDU_CHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
98 } while (0)
99
102#define KUDU_CHECK_OK(s) KUDU_CHECK_OK_PREPEND(s, "Bad status")
103
106#define KUDU_DCHECK_OK_PREPEND(to_call, msg) do { \
107 const ::kudu::Status& _s = (to_call); \
108 KUDU_DCHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
109 } while (0)
110
113#define KUDU_DCHECK_OK(s) KUDU_DCHECK_OK_PREPEND(s, "Bad status")
114
119#define KUDU_RETURN_MAIN_NOT_OK(to_call, msg, ret_code) do { \
120 DCHECK_NE(0, (ret_code)) << "non-OK return code should not be 0"; \
121 const ::kudu::Status& _s = (to_call); \
122 if (!_s.ok()) { \
123 const ::kudu::Status& _ss = _s.CloneAndPrepend((msg)); \
124 LOG(ERROR) << _ss.ToString(); \
125 return (ret_code); \
126 } \
127 } while (0)
128
129// Introduce [[nodiscard]] attribute if compiling with the C++17 or newer.
130#if __cplusplus >= 201703L
131 // This works as intended with KUDU_EXPORT and other attributes for LLVM/CLANG
132 // (at least starting version 11.0.0 that's current version in thirdparty),
133 // but GCC prior to version 13.0 is touchy if mixing attributes of different
134 // types/styles, see [1] for details. So, enable this only if compiling with
135 // CLANG or GCC version 13 and newer.
136 //
137 // [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69585 for details).
138 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 13)
147 #define KUDU_ATTR_NODISCARD [[nodiscard]] // NOLINT(whitespace/braces)
148 #else
149 #define KUDU_ATTR_NODISCARD
150 #endif
151#else // #if __cplusplus >= 201703L ...
152 #define KUDU_ATTR_NODISCARD
153#endif // #if __cplusplus >= 201703L ... #else ...
154
168#ifdef KUDU_HEADERS_USE_SHORT_STATUS_MACROS
169#define RETURN_NOT_OK KUDU_RETURN_NOT_OK
170#define RETURN_NOT_OK_PREPEND KUDU_RETURN_NOT_OK_PREPEND
171#define RETURN_NOT_OK_RET KUDU_RETURN_NOT_OK_RET
172#define RETURN_NOT_OK_EVAL KUDU_RETURN_NOT_OK_EVAL
173#define WARN_NOT_OK KUDU_WARN_NOT_OK
174#define LOG_AND_RETURN KUDU_LOG_AND_RETURN
175#define RETURN_NOT_OK_LOG KUDU_RETURN_NOT_OK_LOG
176#define CHECK_OK_PREPEND KUDU_CHECK_OK_PREPEND
177#define CHECK_OK KUDU_CHECK_OK
178#define DCHECK_OK_PREPEND KUDU_DCHECK_OK_PREPEND
179#define DCHECK_OK KUDU_DCHECK_OK
180#define RETURN_MAIN_NOT_OK KUDU_RETURN_MAIN_NOT_OK
181
182// These are standard glog macros.
183#define KUDU_LOG LOG
184#define KUDU_CHECK CHECK
185#define KUDU_DCHECK DCHECK
186#endif
187
188namespace kudu {
189
191class KUDU_EXPORT KUDU_ATTR_NODISCARD Status {
192 public:
194 Status() : state_(NULL) { }
195
196 ~Status() { delete[] state_; }
197
202 Status(const Status& s);
203
209 Status& operator=(const Status& s);
210
211#if __cplusplus >= 201103L
216 Status(Status&& s) noexcept;
217
223 Status& operator=(Status&& s) noexcept;
224
246 template<typename F>
247 Status AndThen(F op) {
248 if (ok()) {
249 return op();
250 }
251 return *this;
252 }
253#endif
254
256 static Status OK() { return Status(); }
257
260
268 static Status NotFound(const Slice& msg, const Slice& msg2 = Slice(),
269 int16_t posix_code = -1) {
270 return Status(kNotFound, msg, msg2, posix_code);
271 }
272 static Status Corruption(const Slice& msg, const Slice& msg2 = Slice(),
273 int16_t posix_code = -1) {
274 return Status(kCorruption, msg, msg2, posix_code);
275 }
276 static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice(),
277 int16_t posix_code = -1) {
278 return Status(kNotSupported, msg, msg2, posix_code);
279 }
280 static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice(),
281 int16_t posix_code = -1) {
282 return Status(kInvalidArgument, msg, msg2, posix_code);
283 }
284 static Status IOError(const Slice& msg, const Slice& msg2 = Slice(),
285 int16_t posix_code = -1) {
286 return Status(kIOError, msg, msg2, posix_code);
287 }
288 static Status AlreadyPresent(const Slice& msg, const Slice& msg2 = Slice(),
289 int16_t posix_code = -1) {
290 return Status(kAlreadyPresent, msg, msg2, posix_code);
291 }
292 static Status RuntimeError(const Slice& msg, const Slice& msg2 = Slice(),
293 int16_t posix_code = -1) {
294 return Status(kRuntimeError, msg, msg2, posix_code);
295 }
296 static Status NetworkError(const Slice& msg, const Slice& msg2 = Slice(),
297 int16_t posix_code = -1) {
298 return Status(kNetworkError, msg, msg2, posix_code);
299 }
300 static Status IllegalState(const Slice& msg, const Slice& msg2 = Slice(),
301 int16_t posix_code = -1) {
302 return Status(kIllegalState, msg, msg2, posix_code);
303 }
304 static Status NotAuthorized(const Slice& msg, const Slice& msg2 = Slice(),
305 int16_t posix_code = -1) {
306 return Status(kNotAuthorized, msg, msg2, posix_code);
307 }
308 static Status Aborted(const Slice& msg, const Slice& msg2 = Slice(),
309 int16_t posix_code = -1) {
310 return Status(kAborted, msg, msg2, posix_code);
311 }
312 static Status RemoteError(const Slice& msg, const Slice& msg2 = Slice(),
313 int16_t posix_code = -1) {
314 return Status(kRemoteError, msg, msg2, posix_code);
315 }
316 static Status ServiceUnavailable(const Slice& msg, const Slice& msg2 = Slice(),
317 int16_t posix_code = -1) {
318 return Status(kServiceUnavailable, msg, msg2, posix_code);
319 }
320 static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice(),
321 int16_t posix_code = -1) {
322 return Status(kTimedOut, msg, msg2, posix_code);
323 }
324 static Status Uninitialized(const Slice& msg, const Slice& msg2 = Slice(),
325 int16_t posix_code = -1) {
326 return Status(kUninitialized, msg, msg2, posix_code);
327 }
328 static Status ConfigurationError(const Slice& msg, const Slice& msg2 = Slice(),
329 int16_t posix_code = -1) {
330 return Status(kConfigurationError, msg, msg2, posix_code);
331 }
332 static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice(),
333 int64_t posix_code = -1) {
334 return Status(kIncomplete, msg, msg2, posix_code);
335 }
336 static Status EndOfFile(const Slice& msg, const Slice& msg2 = Slice(),
337 int64_t posix_code = -1) {
338 return Status(kEndOfFile, msg, msg2, posix_code);
339 }
340 static Status Immutable(const Slice& msg, const Slice& msg2 = Slice(),
341 int64_t posix_code = -1) {
342 return Status(kImmutable, msg, msg2, posix_code);
343 }
344
345
347 bool ok() const { return (state_ == NULL); }
348
350 bool IsNotFound() const { return code() == kNotFound; }
351
353 bool IsCorruption() const { return code() == kCorruption; }
354
356 bool IsNotSupported() const { return code() == kNotSupported; }
357
359 bool IsIOError() const { return code() == kIOError; }
360
362 bool IsInvalidArgument() const { return code() == kInvalidArgument; }
363
365 bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
366
368 bool IsRuntimeError() const { return code() == kRuntimeError; }
369
371 bool IsNetworkError() const { return code() == kNetworkError; }
372
374 bool IsIllegalState() const { return code() == kIllegalState; }
375
377 bool IsNotAuthorized() const { return code() == kNotAuthorized; }
378
380 bool IsAborted() const { return code() == kAborted; }
381
383 bool IsRemoteError() const { return code() == kRemoteError; }
384
386 bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
387
389 bool IsTimedOut() const { return code() == kTimedOut; }
390
392 bool IsUninitialized() const { return code() == kUninitialized; }
393
395 bool IsConfigurationError() const { return code() == kConfigurationError; }
396
398 bool IsIncomplete() const { return code() == kIncomplete; }
399
401 bool IsEndOfFile() const { return code() == kEndOfFile; }
402
404 bool IsImmutable() const { return code() == kImmutable; }
405
407 bool IsDiskFailure() const {
408 switch (posix_code()) {
409 case EIO:
410 case ENODEV:
411 case ENXIO:
412 case EROFS:
413 return true;
414 }
415 return false;
416 }
417
420 std::string ToString() const;
421
424 std::string CodeAsString() const;
425
434 Slice message() const;
435
438 int16_t posix_code() const;
439
448 Status CloneAndPrepend(const Slice& msg) const;
449
458 Status CloneAndAppend(const Slice& msg) const;
459
463
467
468 private:
469 // OK status has a NULL state_. Otherwise, state_ is a new[] array
470 // of the following form:
471 // state_[0..3] == length of message
472 // state_[4] == code
473 // state_[5..6] == posix_code
474 // state_[7..] == message
475 const char* state_;
476
477 enum Code {
478 kOk = 0,
479 kNotFound = 1,
480 kCorruption = 2,
481 kNotSupported = 3,
482 kInvalidArgument = 4,
483 kIOError = 5,
484 kAlreadyPresent = 6,
485 kRuntimeError = 7,
486 kNetworkError = 8,
487 kIllegalState = 9,
488 kNotAuthorized = 10,
489 kAborted = 11,
490 kRemoteError = 12,
491 kServiceUnavailable = 13,
492 kTimedOut = 14,
493 kUninitialized = 15,
494 kConfigurationError = 16,
495 kIncomplete = 17,
496 kEndOfFile = 18,
497 // kCancelled stems from AppStatusPB, although it seems nobody use it now, we still reserve it.
498 // kCancelled = 19,
499 kImmutable = 20,
500 // NOTE: Remember to duplicate these constants into wire_protocol.proto and
501 // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
502 // Also remember to make the same changes to the java client in Status.java.
503 //
504 // TODO: Move error codes into an error_code.proto or something similar.
505 };
506 COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
507
508 Code code() const {
509 return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
510 }
511
512 Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
513 static const char* CopyState(const char* s);
514};
515
516inline Status::Status(const Status& s) {
517 state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
518}
519
520inline Status& Status::operator=(const Status& s) {
521 // The following condition catches both aliasing (when this == &s),
522 // and the common case where both s and *this are OK.
523 if (state_ != s.state_) {
524 delete[] state_;
525 state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
526 }
527 return *this;
528}
529
530#if __cplusplus >= 201103L
531inline Status::Status(Status&& s) noexcept : state_(s.state_) {
532 s.state_ = nullptr;
533}
534
535inline Status& Status::operator=(Status&& s) noexcept {
536 if (state_ != s.state_) {
537 delete[] state_;
538 state_ = s.state_;
539 s.state_ = nullptr;
540 }
541 return *this;
542}
543#endif
544
545} // namespace kudu
546
547#endif // KUDU_UTIL_STATUS_H_
A representation of an operation's outcome.
Definition status.h:191
A wrapper around externally allocated data.
Definition slice.h:51
A representation of an operation's outcome.
Definition status.h:191
bool IsInvalidArgument() const
Definition status.h:362
static Status TimedOut(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:320
bool IsRemoteError() const
Definition status.h:383
size_t memory_footprint_including_this() const
bool IsEndOfFile() const
Definition status.h:401
static Status Immutable(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition status.h:340
bool IsTimedOut() const
Definition status.h:389
bool IsUninitialized() const
Definition status.h:392
static Status RuntimeError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:292
static Status IOError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:284
int16_t posix_code() const
bool IsAlreadyPresent() const
Definition status.h:365
bool IsCorruption() const
Definition status.h:353
size_t memory_footprint_excluding_this() const
static Status ServiceUnavailable(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:316
static Status Corruption(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:272
bool IsIOError() const
Definition status.h:359
static Status IllegalState(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:300
bool IsAborted() const
Definition status.h:380
static Status Aborted(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:308
std::string CodeAsString() const
static Status NotSupported(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:276
Status CloneAndAppend(const Slice &msg) const
bool IsNotFound() const
Definition status.h:350
bool IsServiceUnavailable() const
Definition status.h:386
bool IsConfigurationError() const
Definition status.h:395
static Status AlreadyPresent(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:288
Status & operator=(const Status &s)
Definition status.h:520
bool IsDiskFailure() const
Definition status.h:407
static Status NotFound(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:268
bool IsNotSupported() const
Definition status.h:356
static Status InvalidArgument(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:280
static Status Incomplete(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition status.h:332
Status CloneAndPrepend(const Slice &msg) const
static Status NetworkError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:296
static Status Uninitialized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:324
bool IsIncomplete() const
Definition status.h:398
bool IsNotAuthorized() const
Definition status.h:377
static Status NotAuthorized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:304
Status()
Create an object representing success status.
Definition status.h:194
bool IsIllegalState() const
Definition status.h:374
bool IsNetworkError() const
Definition status.h:371
bool IsImmutable() const
Definition status.h:404
static Status OK()
Definition status.h:256
bool ok() const
Definition status.h:347
bool IsRuntimeError() const
Definition status.h:368
std::string ToString() const
static Status EndOfFile(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition status.h:336
static Status ConfigurationError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:328
static Status RemoteError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition status.h:312
Slice message() const