Kudu C++ client API
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 
142 #ifdef KUDU_HEADERS_USE_SHORT_STATUS_MACROS
143 #define RETURN_NOT_OK KUDU_RETURN_NOT_OK
144 #define RETURN_NOT_OK_PREPEND KUDU_RETURN_NOT_OK_PREPEND
145 #define RETURN_NOT_OK_RET KUDU_RETURN_NOT_OK_RET
146 #define RETURN_NOT_OK_EVAL KUDU_RETURN_NOT_OK_EVAL
147 #define WARN_NOT_OK KUDU_WARN_NOT_OK
148 #define LOG_AND_RETURN KUDU_LOG_AND_RETURN
149 #define RETURN_NOT_OK_LOG KUDU_RETURN_NOT_OK_LOG
150 #define CHECK_OK_PREPEND KUDU_CHECK_OK_PREPEND
151 #define CHECK_OK KUDU_CHECK_OK
152 #define DCHECK_OK_PREPEND KUDU_DCHECK_OK_PREPEND
153 #define DCHECK_OK KUDU_DCHECK_OK
154 #define RETURN_MAIN_NOT_OK KUDU_RETURN_MAIN_NOT_OK
155 
156 // These are standard glog macros.
157 #define KUDU_LOG LOG
158 #define KUDU_CHECK CHECK
159 #define KUDU_DCHECK DCHECK
160 #endif
161 
162 namespace kudu {
163 
165 class KUDU_EXPORT Status {
166  public:
168  Status() : state_(NULL) { }
169 
170  ~Status() { delete[] state_; }
171 
176  Status(const Status& s);
177 
183  Status& operator=(const Status& s);
184 
185 #if __cplusplus >= 201103L
190  Status(Status&& s) noexcept;
191 
197  Status& operator=(Status&& s) noexcept;
198 
220  template<typename F>
221  Status AndThen(F op) {
222  if (ok()) {
223  return op();
224  }
225  return *this;
226  }
227 #endif
228 
230  static Status OK() { return Status(); }
231 
234 
242  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice(),
243  int16_t posix_code = -1) {
244  return Status(kNotFound, msg, msg2, posix_code);
245  }
246  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice(),
247  int16_t posix_code = -1) {
248  return Status(kCorruption, msg, msg2, posix_code);
249  }
250  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice(),
251  int16_t posix_code = -1) {
252  return Status(kNotSupported, msg, msg2, posix_code);
253  }
254  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice(),
255  int16_t posix_code = -1) {
256  return Status(kInvalidArgument, msg, msg2, posix_code);
257  }
258  static Status IOError(const Slice& msg, const Slice& msg2 = Slice(),
259  int16_t posix_code = -1) {
260  return Status(kIOError, msg, msg2, posix_code);
261  }
262  static Status AlreadyPresent(const Slice& msg, const Slice& msg2 = Slice(),
263  int16_t posix_code = -1) {
264  return Status(kAlreadyPresent, msg, msg2, posix_code);
265  }
266  static Status RuntimeError(const Slice& msg, const Slice& msg2 = Slice(),
267  int16_t posix_code = -1) {
268  return Status(kRuntimeError, msg, msg2, posix_code);
269  }
270  static Status NetworkError(const Slice& msg, const Slice& msg2 = Slice(),
271  int16_t posix_code = -1) {
272  return Status(kNetworkError, msg, msg2, posix_code);
273  }
274  static Status IllegalState(const Slice& msg, const Slice& msg2 = Slice(),
275  int16_t posix_code = -1) {
276  return Status(kIllegalState, msg, msg2, posix_code);
277  }
278  static Status NotAuthorized(const Slice& msg, const Slice& msg2 = Slice(),
279  int16_t posix_code = -1) {
280  return Status(kNotAuthorized, msg, msg2, posix_code);
281  }
282  static Status Aborted(const Slice& msg, const Slice& msg2 = Slice(),
283  int16_t posix_code = -1) {
284  return Status(kAborted, msg, msg2, posix_code);
285  }
286  static Status RemoteError(const Slice& msg, const Slice& msg2 = Slice(),
287  int16_t posix_code = -1) {
288  return Status(kRemoteError, msg, msg2, posix_code);
289  }
290  static Status ServiceUnavailable(const Slice& msg, const Slice& msg2 = Slice(),
291  int16_t posix_code = -1) {
292  return Status(kServiceUnavailable, msg, msg2, posix_code);
293  }
294  static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice(),
295  int16_t posix_code = -1) {
296  return Status(kTimedOut, msg, msg2, posix_code);
297  }
298  static Status Uninitialized(const Slice& msg, const Slice& msg2 = Slice(),
299  int16_t posix_code = -1) {
300  return Status(kUninitialized, msg, msg2, posix_code);
301  }
302  static Status ConfigurationError(const Slice& msg, const Slice& msg2 = Slice(),
303  int16_t posix_code = -1) {
304  return Status(kConfigurationError, msg, msg2, posix_code);
305  }
306  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice(),
307  int64_t posix_code = -1) {
308  return Status(kIncomplete, msg, msg2, posix_code);
309  }
310  static Status EndOfFile(const Slice& msg, const Slice& msg2 = Slice(),
311  int64_t posix_code = -1) {
312  return Status(kEndOfFile, msg, msg2, posix_code);
313  }
314  static Status Immutable(const Slice& msg, const Slice& msg2 = Slice(),
315  int64_t posix_code = -1) {
316  return Status(kImmutable, msg, msg2, posix_code);
317  }
319 
321  bool ok() const { return (state_ == NULL); }
322 
324  bool IsNotFound() const { return code() == kNotFound; }
325 
327  bool IsCorruption() const { return code() == kCorruption; }
328 
330  bool IsNotSupported() const { return code() == kNotSupported; }
331 
333  bool IsIOError() const { return code() == kIOError; }
334 
336  bool IsInvalidArgument() const { return code() == kInvalidArgument; }
337 
339  bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
340 
342  bool IsRuntimeError() const { return code() == kRuntimeError; }
343 
345  bool IsNetworkError() const { return code() == kNetworkError; }
346 
348  bool IsIllegalState() const { return code() == kIllegalState; }
349 
351  bool IsNotAuthorized() const { return code() == kNotAuthorized; }
352 
354  bool IsAborted() const { return code() == kAborted; }
355 
357  bool IsRemoteError() const { return code() == kRemoteError; }
358 
360  bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
361 
363  bool IsTimedOut() const { return code() == kTimedOut; }
364 
366  bool IsUninitialized() const { return code() == kUninitialized; }
367 
369  bool IsConfigurationError() const { return code() == kConfigurationError; }
370 
372  bool IsIncomplete() const { return code() == kIncomplete; }
373 
375  bool IsEndOfFile() const { return code() == kEndOfFile; }
376 
378  bool IsImmutable() const { return code() == kImmutable; }
379 
381  bool IsDiskFailure() const {
382  switch (posix_code()) {
383  case EIO:
384  case ENODEV:
385  case ENXIO:
386  case EROFS:
387  return true;
388  }
389  return false;
390  }
391 
394  std::string ToString() const;
395 
398  std::string CodeAsString() const;
399 
408  Slice message() const;
409 
412  int16_t posix_code() const;
413 
422  Status CloneAndPrepend(const Slice& msg) const;
423 
432  Status CloneAndAppend(const Slice& msg) const;
433 
437 
441 
442  private:
443  // OK status has a NULL state_. Otherwise, state_ is a new[] array
444  // of the following form:
445  // state_[0..3] == length of message
446  // state_[4] == code
447  // state_[5..6] == posix_code
448  // state_[7..] == message
449  const char* state_;
450 
451  enum Code {
452  kOk = 0,
453  kNotFound = 1,
454  kCorruption = 2,
455  kNotSupported = 3,
456  kInvalidArgument = 4,
457  kIOError = 5,
458  kAlreadyPresent = 6,
459  kRuntimeError = 7,
460  kNetworkError = 8,
461  kIllegalState = 9,
462  kNotAuthorized = 10,
463  kAborted = 11,
464  kRemoteError = 12,
465  kServiceUnavailable = 13,
466  kTimedOut = 14,
467  kUninitialized = 15,
468  kConfigurationError = 16,
469  kIncomplete = 17,
470  kEndOfFile = 18,
471  // kCancelled stems from AppStatusPB, although it seems nobody use it now, we still reserve it.
472  // kCancelled = 19,
473  kImmutable = 20,
474  // NOTE: Remember to duplicate these constants into wire_protocol.proto and
475  // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
476  // Also remember to make the same changes to the java client in Status.java.
477  //
478  // TODO: Move error codes into an error_code.proto or something similar.
479  };
480  COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
481 
482  Code code() const {
483  return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
484  }
485 
486  Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
487  static const char* CopyState(const char* s);
488 };
489 
490 inline Status::Status(const Status& s) {
491  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
492 }
493 
494 inline Status& Status::operator=(const Status& s) {
495  // The following condition catches both aliasing (when this == &s),
496  // and the common case where both s and *this are OK.
497  if (state_ != s.state_) {
498  delete[] state_;
499  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
500  }
501  return *this;
502 }
503 
504 #if __cplusplus >= 201103L
505 inline Status::Status(Status&& s) noexcept : state_(s.state_) {
506  s.state_ = nullptr;
507 }
508 
509 inline Status& Status::operator=(Status&& s) noexcept {
510  if (state_ != s.state_) {
511  delete[] state_;
512  state_ = s.state_;
513  s.state_ = nullptr;
514  }
515  return *this;
516 }
517 #endif
518 
519 } // namespace kudu
520 
521 #endif // KUDU_UTIL_STATUS_H_
A wrapper around externally allocated data.
Definition: slice.h:51
A representation of an operation's outcome.
Definition: status.h:165
bool IsInvalidArgument() const
Definition: status.h:336
static Status TimedOut(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:294
bool IsRemoteError() const
Definition: status.h:357
size_t memory_footprint_including_this() const
bool IsEndOfFile() const
Definition: status.h:375
static Status Immutable(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition: status.h:314
bool IsTimedOut() const
Definition: status.h:363
bool IsUninitialized() const
Definition: status.h:366
static Status RuntimeError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:266
static Status IOError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:258
int16_t posix_code() const
bool IsAlreadyPresent() const
Definition: status.h:339
bool IsCorruption() const
Definition: status.h:327
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:290
static Status Corruption(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:246
bool IsIOError() const
Definition: status.h:333
static Status IllegalState(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:274
bool IsAborted() const
Definition: status.h:354
static Status Aborted(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:282
std::string CodeAsString() const
static Status NotSupported(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:250
Status CloneAndAppend(const Slice &msg) const
bool IsNotFound() const
Definition: status.h:324
bool IsServiceUnavailable() const
Definition: status.h:360
bool IsConfigurationError() const
Definition: status.h:369
static Status AlreadyPresent(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:262
Status & operator=(const Status &s)
Definition: status.h:494
bool IsDiskFailure() const
Definition: status.h:381
static Status NotFound(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:242
bool IsNotSupported() const
Definition: status.h:330
static Status InvalidArgument(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:254
static Status Incomplete(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition: status.h:306
Status CloneAndPrepend(const Slice &msg) const
static Status NetworkError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:270
static Status Uninitialized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:298
bool IsIncomplete() const
Definition: status.h:372
bool IsNotAuthorized() const
Definition: status.h:351
static Status NotAuthorized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:278
Status()
Create an object representing success status.
Definition: status.h:168
bool IsIllegalState() const
Definition: status.h:348
bool IsNetworkError() const
Definition: status.h:345
bool IsImmutable() const
Definition: status.h:378
static Status OK()
Definition: status.h:230
bool ok() const
Definition: status.h:321
bool IsRuntimeError() const
Definition: status.h:342
std::string ToString() const
static Status EndOfFile(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition: status.h:310
static Status ConfigurationError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:302
static Status RemoteError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:286
Slice message() const