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
186  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  }
315 
317  bool ok() const { return (state_ == NULL); }
318 
320  bool IsNotFound() const { return code() == kNotFound; }
321 
323  bool IsCorruption() const { return code() == kCorruption; }
324 
326  bool IsNotSupported() const { return code() == kNotSupported; }
327 
329  bool IsIOError() const { return code() == kIOError; }
330 
332  bool IsInvalidArgument() const { return code() == kInvalidArgument; }
333 
335  bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
336 
338  bool IsRuntimeError() const { return code() == kRuntimeError; }
339 
341  bool IsNetworkError() const { return code() == kNetworkError; }
342 
344  bool IsIllegalState() const { return code() == kIllegalState; }
345 
347  bool IsNotAuthorized() const { return code() == kNotAuthorized; }
348 
350  bool IsAborted() const { return code() == kAborted; }
351 
353  bool IsRemoteError() const { return code() == kRemoteError; }
354 
356  bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
357 
359  bool IsTimedOut() const { return code() == kTimedOut; }
360 
362  bool IsUninitialized() const { return code() == kUninitialized; }
363 
365  bool IsConfigurationError() const { return code() == kConfigurationError; }
366 
368  bool IsIncomplete() const { return code() == kIncomplete; }
369 
371  bool IsEndOfFile() const { return code() == kEndOfFile; }
372 
374  bool IsDiskFailure() const {
375  switch (posix_code()) {
376  case EIO:
377  case ENODEV:
378  case ENXIO:
379  case EROFS:
380  return true;
381  }
382  return false;
383  }
384 
387  std::string ToString() const;
388 
391  std::string CodeAsString() const;
392 
401  Slice message() const;
402 
405  int16_t posix_code() const;
406 
415  Status CloneAndPrepend(const Slice& msg) const;
416 
425  Status CloneAndAppend(const Slice& msg) const;
426 
430 
434 
435  private:
436  // OK status has a NULL state_. Otherwise, state_ is a new[] array
437  // of the following form:
438  // state_[0..3] == length of message
439  // state_[4] == code
440  // state_[5..6] == posix_code
441  // state_[7..] == message
442  const char* state_;
443 
444  enum Code {
445  kOk = 0,
446  kNotFound = 1,
447  kCorruption = 2,
448  kNotSupported = 3,
449  kInvalidArgument = 4,
450  kIOError = 5,
451  kAlreadyPresent = 6,
452  kRuntimeError = 7,
453  kNetworkError = 8,
454  kIllegalState = 9,
455  kNotAuthorized = 10,
456  kAborted = 11,
457  kRemoteError = 12,
458  kServiceUnavailable = 13,
459  kTimedOut = 14,
460  kUninitialized = 15,
461  kConfigurationError = 16,
462  kIncomplete = 17,
463  kEndOfFile = 18,
464  // NOTE: Remember to duplicate these constants into wire_protocol.proto and
465  // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
466  // Also remember to make the same changes to the java client in Status.java.
467  //
468  // TODO: Move error codes into an error_code.proto or something similar.
469  };
470  COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
471 
472  Code code() const {
473  return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
474  }
475 
476  Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
477  static const char* CopyState(const char* s);
478 };
479 
480 inline Status::Status(const Status& s) {
481  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
482 }
483 
484 inline Status& Status::operator=(const Status& s) {
485  // The following condition catches both aliasing (when this == &s),
486  // and the common case where both s and *this are OK.
487  if (state_ != s.state_) {
488  delete[] state_;
489  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
490  }
491  return *this;
492 }
493 
494 #if __cplusplus >= 201103L
495 inline Status::Status(Status&& s) noexcept : state_(s.state_) {
496  s.state_ = nullptr;
497 }
498 
499 inline Status& Status::operator=(Status&& s) noexcept {
500  if (state_ != s.state_) {
501  delete[] state_;
502  state_ = s.state_;
503  s.state_ = nullptr;
504  }
505  return *this;
506 }
507 #endif
508 
509 } // namespace kudu
510 
511 #endif // KUDU_UTIL_STATUS_H_
kudu::Status::IsNotSupported
bool IsNotSupported() const
Definition: status.h:326
kudu::Status::IsNotAuthorized
bool IsNotAuthorized() const
Definition: status.h:347
kudu::Status::IsInvalidArgument
bool IsInvalidArgument() const
Definition: status.h:332
kudu::Status::TimedOut
static Status TimedOut(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:294
kudu::Status::operator=
Status & operator=(const Status &s)
Definition: status.h:484
kudu::Status::Status
Status()
Create an object representing success status.
Definition: status.h:168
kudu::Status::IsUninitialized
bool IsUninitialized() const
Definition: status.h:362
kudu::Status::IllegalState
static Status IllegalState(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:274
kudu::Status::EndOfFile
static Status EndOfFile(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition: status.h:310
kudu::Status::IsRuntimeError
bool IsRuntimeError() const
Definition: status.h:338
kudu::Status::RuntimeError
static Status RuntimeError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:266
kudu::Status::Incomplete
static Status Incomplete(const Slice &msg, const Slice &msg2=Slice(), int64_t posix_code=-1)
Definition: status.h:306
kudu::Status::CloneAndPrepend
Status CloneAndPrepend(const Slice &msg) const
kudu::Status::IsTimedOut
bool IsTimedOut() const
Definition: status.h:359
kudu::Status::IOError
static Status IOError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:258
kudu::Status::InvalidArgument
static Status InvalidArgument(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:254
kudu::Status::IsServiceUnavailable
bool IsServiceUnavailable() const
Definition: status.h:356
kudu::Status::ConfigurationError
static Status ConfigurationError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:302
kudu::Status::Aborted
static Status Aborted(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:282
kudu::Status::OK
static Status OK()
Definition: status.h:230
kudu::Status::ok
bool ok() const
Definition: status.h:317
kudu::Status::IsEndOfFile
bool IsEndOfFile() const
Definition: status.h:371
kudu::Status::NetworkError
static Status NetworkError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:270
kudu::Status::Uninitialized
static Status Uninitialized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:298
kudu::Status::ToString
std::string ToString() const
kudu::Status::AlreadyPresent
static Status AlreadyPresent(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:262
kudu::Status::IsAlreadyPresent
bool IsAlreadyPresent() const
Definition: status.h:335
kudu::Status::posix_code
int16_t posix_code() const
kudu::Status::IsNetworkError
bool IsNetworkError() const
Definition: status.h:341
kudu::Status::IsNotFound
bool IsNotFound() const
Definition: status.h:320
kudu::Status::IsIllegalState
bool IsIllegalState() const
Definition: status.h:344
kudu::Status::IsConfigurationError
bool IsConfigurationError() const
Definition: status.h:365
kudu::Status
A representation of an operation's outcome.
Definition: status.h:165
kudu::Status::IsAborted
bool IsAborted() const
Definition: status.h:350
kudu::Status::CodeAsString
std::string CodeAsString() const
kudu::Status::CloneAndAppend
Status CloneAndAppend(const Slice &msg) const
kudu::Status::IsCorruption
bool IsCorruption() const
Definition: status.h:323
kudu::Status::IsIncomplete
bool IsIncomplete() const
Definition: status.h:368
kudu::Status::memory_footprint_excluding_this
size_t memory_footprint_excluding_this() const
kudu::Status::IsRemoteError
bool IsRemoteError() const
Definition: status.h:353
kudu::Slice
A wrapper around externally allocated data.
Definition: slice.h:51
kudu::Status::NotAuthorized
static Status NotAuthorized(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:278
kudu::Status::NotFound
static Status NotFound(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:242
kudu::Status::message
Slice message() const
kudu::Status::Corruption
static Status Corruption(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:246
kudu::Status::IsIOError
bool IsIOError() const
Definition: status.h:329
kudu::Status::ServiceUnavailable
static Status ServiceUnavailable(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:290
kudu::Status::RemoteError
static Status RemoteError(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:286
kudu::Status::IsDiskFailure
bool IsDiskFailure() const
Definition: status.h:374
kudu::Status::memory_footprint_including_this
size_t memory_footprint_including_this() const
kudu::Status::NotSupported
static Status NotSupported(const Slice &msg, const Slice &msg2=Slice(), int16_t posix_code=-1)
Definition: status.h:250