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 
232 
244  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice(),
245  int16_t posix_code = -1) {
246  return Status(kNotFound, msg, msg2, posix_code);
247  }
248  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice(),
249  int16_t posix_code = -1) {
250  return Status(kCorruption, msg, msg2, posix_code);
251  }
252  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice(),
253  int16_t posix_code = -1) {
254  return Status(kNotSupported, msg, msg2, posix_code);
255  }
256  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice(),
257  int16_t posix_code = -1) {
258  return Status(kInvalidArgument, msg, msg2, posix_code);
259  }
260  static Status IOError(const Slice& msg, const Slice& msg2 = Slice(),
261  int16_t posix_code = -1) {
262  return Status(kIOError, msg, msg2, posix_code);
263  }
264  static Status AlreadyPresent(const Slice& msg, const Slice& msg2 = Slice(),
265  int16_t posix_code = -1) {
266  return Status(kAlreadyPresent, msg, msg2, posix_code);
267  }
268  static Status RuntimeError(const Slice& msg, const Slice& msg2 = Slice(),
269  int16_t posix_code = -1) {
270  return Status(kRuntimeError, msg, msg2, posix_code);
271  }
272  static Status NetworkError(const Slice& msg, const Slice& msg2 = Slice(),
273  int16_t posix_code = -1) {
274  return Status(kNetworkError, msg, msg2, posix_code);
275  }
276  static Status IllegalState(const Slice& msg, const Slice& msg2 = Slice(),
277  int16_t posix_code = -1) {
278  return Status(kIllegalState, msg, msg2, posix_code);
279  }
280  static Status NotAuthorized(const Slice& msg, const Slice& msg2 = Slice(),
281  int16_t posix_code = -1) {
282  return Status(kNotAuthorized, msg, msg2, posix_code);
283  }
284  static Status Aborted(const Slice& msg, const Slice& msg2 = Slice(),
285  int16_t posix_code = -1) {
286  return Status(kAborted, msg, msg2, posix_code);
287  }
288  static Status RemoteError(const Slice& msg, const Slice& msg2 = Slice(),
289  int16_t posix_code = -1) {
290  return Status(kRemoteError, msg, msg2, posix_code);
291  }
292  static Status ServiceUnavailable(const Slice& msg, const Slice& msg2 = Slice(),
293  int16_t posix_code = -1) {
294  return Status(kServiceUnavailable, msg, msg2, posix_code);
295  }
296  static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice(),
297  int16_t posix_code = -1) {
298  return Status(kTimedOut, msg, msg2, posix_code);
299  }
300  static Status Uninitialized(const Slice& msg, const Slice& msg2 = Slice(),
301  int16_t posix_code = -1) {
302  return Status(kUninitialized, msg, msg2, posix_code);
303  }
304  static Status ConfigurationError(const Slice& msg, const Slice& msg2 = Slice(),
305  int16_t posix_code = -1) {
306  return Status(kConfigurationError, msg, msg2, posix_code);
307  }
308  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice(),
309  int64_t posix_code = -1) {
310  return Status(kIncomplete, msg, msg2, posix_code);
311  }
312  static Status EndOfFile(const Slice& msg, const Slice& msg2 = Slice(),
313  int64_t posix_code = -1) {
314  return Status(kEndOfFile, msg, msg2, posix_code);
315  }
317 
319  bool ok() const { return (state_ == NULL); }
320 
322  bool IsNotFound() const { return code() == kNotFound; }
323 
325  bool IsCorruption() const { return code() == kCorruption; }
326 
328  bool IsNotSupported() const { return code() == kNotSupported; }
329 
331  bool IsIOError() const { return code() == kIOError; }
332 
334  bool IsInvalidArgument() const { return code() == kInvalidArgument; }
335 
337  bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
338 
340  bool IsRuntimeError() const { return code() == kRuntimeError; }
341 
343  bool IsNetworkError() const { return code() == kNetworkError; }
344 
346  bool IsIllegalState() const { return code() == kIllegalState; }
347 
349  bool IsNotAuthorized() const { return code() == kNotAuthorized; }
350 
352  bool IsAborted() const { return code() == kAborted; }
353 
355  bool IsRemoteError() const { return code() == kRemoteError; }
356 
358  bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
359 
361  bool IsTimedOut() const { return code() == kTimedOut; }
362 
364  bool IsUninitialized() const { return code() == kUninitialized; }
365 
367  bool IsConfigurationError() const { return code() == kConfigurationError; }
368 
370  bool IsIncomplete() const { return code() == kIncomplete; }
371 
373  bool IsEndOfFile() const { return code() == kEndOfFile; }
374 
376  bool IsDiskFailure() const {
377  switch (posix_code()) {
378  case EIO:
379  case ENODEV:
380  case ENXIO:
381  case EROFS:
382  return true;
383  }
384  return false;
385  }
386 
389  std::string ToString() const;
390 
393  std::string CodeAsString() const;
394 
403  Slice message() const;
404 
407  int16_t posix_code() const;
408 
417  Status CloneAndPrepend(const Slice& msg) const;
418 
427  Status CloneAndAppend(const Slice& msg) const;
428 
431  size_t memory_footprint_excluding_this() const;
432 
435  size_t memory_footprint_including_this() const;
436 
437  private:
438  // OK status has a NULL state_. Otherwise, state_ is a new[] array
439  // of the following form:
440  // state_[0..3] == length of message
441  // state_[4] == code
442  // state_[5..6] == posix_code
443  // state_[7..] == message
444  const char* state_;
445 
446  enum Code {
447  kOk = 0,
448  kNotFound = 1,
449  kCorruption = 2,
450  kNotSupported = 3,
451  kInvalidArgument = 4,
452  kIOError = 5,
453  kAlreadyPresent = 6,
454  kRuntimeError = 7,
455  kNetworkError = 8,
456  kIllegalState = 9,
457  kNotAuthorized = 10,
458  kAborted = 11,
459  kRemoteError = 12,
460  kServiceUnavailable = 13,
461  kTimedOut = 14,
462  kUninitialized = 15,
463  kConfigurationError = 16,
464  kIncomplete = 17,
465  kEndOfFile = 18,
466  // NOTE: Remember to duplicate these constants into wire_protocol.proto and
467  // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
468  // Also remember to make the same changes to the java client in Status.java.
469  //
470  // TODO: Move error codes into an error_code.proto or something similar.
471  };
472  COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
473 
474  Code code() const {
475  return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
476  }
477 
478  Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
479  static const char* CopyState(const char* s);
480 };
481 
482 inline Status::Status(const Status& s) {
483  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
484 }
485 
486 inline Status& Status::operator=(const Status& s) {
487  // The following condition catches both aliasing (when this == &s),
488  // and the common case where both s and *this are OK.
489  if (state_ != s.state_) {
490  delete[] state_;
491  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
492  }
493  return *this;
494 }
495 
496 #if __cplusplus >= 201103L
497 inline Status::Status(Status&& s) noexcept : state_(s.state_) {
498  s.state_ = nullptr;
499 }
500 
501 inline Status& Status::operator=(Status&& s) noexcept {
502  if (state_ != s.state_) {
503  delete[] state_;
504  state_ = s.state_;
505  s.state_ = nullptr;
506  }
507  return *this;
508 }
509 #endif
510 
511 } // namespace kudu
512 
513 #endif // KUDU_UTIL_STATUS_H_
Status()
Create an object representing success status.
Definition: status.h:168
bool IsNotAuthorized() const
Definition: status.h:349
A representation of an operation&#39;s outcome.
Definition: status.h:165
bool IsIllegalState() const
Definition: status.h:346
Definition: callbacks.h:28
bool ok() const
Definition: status.h:319
bool IsTimedOut() const
Definition: status.h:361
bool IsRemoteError() const
Definition: status.h:355
bool IsDiskFailure() const
Definition: status.h:376
bool IsServiceUnavailable() const
Definition: status.h:358
bool IsAborted() const
Definition: status.h:352
bool IsUninitialized() const
Definition: status.h:364
bool IsRuntimeError() const
Definition: status.h:340
bool IsAlreadyPresent() const
Definition: status.h:337
bool IsIOError() const
Definition: status.h:331
static Status OK()
Definition: status.h:230
A wrapper around externally allocated data.
Definition: slice.h:51
Status & operator=(const Status &s)
Definition: status.h:486
bool IsConfigurationError() const
Definition: status.h:367
bool IsInvalidArgument() const
Definition: status.h:334
bool IsCorruption() const
Definition: status.h:325
bool IsEndOfFile() const
Definition: status.h:373
bool IsNotSupported() const
Definition: status.h:328
bool IsNetworkError() const
Definition: status.h:343
bool IsIncomplete() const
Definition: status.h:370
bool IsNotFound() const
Definition: status.h:322