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 errno 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 #ifdef KUDU_HEADERS_NO_STUBS
25 #include "kudu/gutil/macros.h"
26 #include "kudu/gutil/port.h"
27 #else
28 #include "kudu/client/stubs.h"
29 #endif
30 
31 #include "kudu/util/kudu_export.h"
32 #include "kudu/util/slice.h"
33 
35 #define KUDU_RETURN_NOT_OK(s) do { \
36  const ::kudu::Status& _s = (s); \
37  if (PREDICT_FALSE(!_s.ok())) return _s; \
38  } while (0);
39 
42 #define KUDU_RETURN_NOT_OK_PREPEND(s, msg) do { \
43  const ::kudu::Status& _s = (s); \
44  if (PREDICT_FALSE(!_s.ok())) return _s.CloneAndPrepend(msg); \
45  } while (0);
46 
50 #define KUDU_RETURN_NOT_OK_RET(to_call, to_return) do { \
51  const ::kudu::Status& s = (to_call); \
52  if (PREDICT_FALSE(!s.ok())) return (to_return); \
53  } while (0);
54 
56 #define KUDU_RETURN_NOT_OK_EVAL(s, on_error) do { \
57  const ::kudu::Status& _s = (s); \
58  if (PREDICT_FALSE(!_s.ok())) { \
59  (on_error); \
60  return _s; \
61  } \
62  } while (0);
63 
65 #define KUDU_WARN_NOT_OK(to_call, warning_prefix) do { \
66  const ::kudu::Status& _s = (to_call); \
67  if (PREDICT_FALSE(!_s.ok())) { \
68  KUDU_LOG(WARNING) << (warning_prefix) << ": " << _s.ToString(); \
69  } \
70  } while (0);
71 
73 #define KUDU_LOG_AND_RETURN(level, status) do { \
74  const ::kudu::Status& _s = (status); \
75  KUDU_LOG(level) << _s.ToString(); \
76  return _s; \
77  } while (0);
78 
80 #define KUDU_RETURN_NOT_OK_LOG(s, level, msg) do { \
81  const ::kudu::Status& _s = (s); \
82  if (PREDICT_FALSE(!_s.ok())) { \
83  KUDU_LOG(level) << "Status: " << _s.ToString() << " " << (msg); \
84  return _s; \
85  } \
86  } while (0);
87 
90 #define KUDU_CHECK_OK_PREPEND(to_call, msg) do { \
91  const ::kudu::Status& _s = (to_call); \
92  KUDU_CHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
93  } while (0);
94 
97 #define KUDU_CHECK_OK(s) KUDU_CHECK_OK_PREPEND(s, "Bad status")
98 
101 #define KUDU_DCHECK_OK_PREPEND(to_call, msg) do { \
102  const ::kudu::Status& _s = (to_call); \
103  KUDU_DCHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
104  } while (0);
105 
108 #define KUDU_DCHECK_OK(s) KUDU_DCHECK_OK_PREPEND(s, "Bad status")
109 
123 #ifdef KUDU_HEADERS_USE_SHORT_STATUS_MACROS
124 #define RETURN_NOT_OK KUDU_RETURN_NOT_OK
125 #define RETURN_NOT_OK_PREPEND KUDU_RETURN_NOT_OK_PREPEND
126 #define RETURN_NOT_OK_RET KUDU_RETURN_NOT_OK_RET
127 #define RETURN_NOT_OK_EVAL KUDU_RETURN_NOT_OK_EVAL
128 #define WARN_NOT_OK KUDU_WARN_NOT_OK
129 #define LOG_AND_RETURN KUDU_LOG_AND_RETURN
130 #define RETURN_NOT_OK_LOG KUDU_RETURN_NOT_OK_LOG
131 #define CHECK_OK_PREPEND KUDU_CHECK_OK_PREPEND
132 #define CHECK_OK KUDU_CHECK_OK
133 #define DCHECK_OK_PREPEND KUDU_DCHECK_OK_PREPEND
134 #define DCHECK_OK KUDU_DCHECK_OK
135 
136 // These are standard glog macros.
137 #define KUDU_LOG LOG
138 #define KUDU_CHECK CHECK
139 #define KUDU_DCHECK DCHECK
140 #endif
141 
142 namespace kudu {
143 
145 class KUDU_EXPORT Status {
146  public:
148  Status() : state_(NULL) { }
149 
150  ~Status() { delete[] state_; }
151 
156  Status(const Status& s);
157 
163  Status& operator=(const Status& s);
164 
165 #if __cplusplus >= 201103L
166  Status(Status&& s) noexcept;
171 
177  Status& operator=(Status&& s) noexcept;
178 
200  template<typename F>
201  Status AndThen(F op) {
202  if (ok()) {
203  return op();
204  }
205  return *this;
206  }
207 #endif
208 
210  static Status OK() { return Status(); }
211 
212 
224  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice(),
225  int16_t posix_code = -1) {
226  return Status(kNotFound, msg, msg2, posix_code);
227  }
228  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice(),
229  int16_t posix_code = -1) {
230  return Status(kCorruption, msg, msg2, posix_code);
231  }
232  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice(),
233  int16_t posix_code = -1) {
234  return Status(kNotSupported, msg, msg2, posix_code);
235  }
236  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice(),
237  int16_t posix_code = -1) {
238  return Status(kInvalidArgument, msg, msg2, posix_code);
239  }
240  static Status IOError(const Slice& msg, const Slice& msg2 = Slice(),
241  int16_t posix_code = -1) {
242  return Status(kIOError, msg, msg2, posix_code);
243  }
244  static Status AlreadyPresent(const Slice& msg, const Slice& msg2 = Slice(),
245  int16_t posix_code = -1) {
246  return Status(kAlreadyPresent, msg, msg2, posix_code);
247  }
248  static Status RuntimeError(const Slice& msg, const Slice& msg2 = Slice(),
249  int16_t posix_code = -1) {
250  return Status(kRuntimeError, msg, msg2, posix_code);
251  }
252  static Status NetworkError(const Slice& msg, const Slice& msg2 = Slice(),
253  int16_t posix_code = -1) {
254  return Status(kNetworkError, msg, msg2, posix_code);
255  }
256  static Status IllegalState(const Slice& msg, const Slice& msg2 = Slice(),
257  int16_t posix_code = -1) {
258  return Status(kIllegalState, msg, msg2, posix_code);
259  }
260  static Status NotAuthorized(const Slice& msg, const Slice& msg2 = Slice(),
261  int16_t posix_code = -1) {
262  return Status(kNotAuthorized, msg, msg2, posix_code);
263  }
264  static Status Aborted(const Slice& msg, const Slice& msg2 = Slice(),
265  int16_t posix_code = -1) {
266  return Status(kAborted, msg, msg2, posix_code);
267  }
268  static Status RemoteError(const Slice& msg, const Slice& msg2 = Slice(),
269  int16_t posix_code = -1) {
270  return Status(kRemoteError, msg, msg2, posix_code);
271  }
272  static Status ServiceUnavailable(const Slice& msg, const Slice& msg2 = Slice(),
273  int16_t posix_code = -1) {
274  return Status(kServiceUnavailable, msg, msg2, posix_code);
275  }
276  static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice(),
277  int16_t posix_code = -1) {
278  return Status(kTimedOut, msg, msg2, posix_code);
279  }
280  static Status Uninitialized(const Slice& msg, const Slice& msg2 = Slice(),
281  int16_t posix_code = -1) {
282  return Status(kUninitialized, msg, msg2, posix_code);
283  }
284  static Status ConfigurationError(const Slice& msg, const Slice& msg2 = Slice(),
285  int16_t posix_code = -1) {
286  return Status(kConfigurationError, msg, msg2, posix_code);
287  }
288  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice(),
289  int64_t posix_code = -1) {
290  return Status(kIncomplete, msg, msg2, posix_code);
291  }
292  static Status EndOfFile(const Slice& msg, const Slice& msg2 = Slice(),
293  int64_t posix_code = -1) {
294  return Status(kEndOfFile, msg, msg2, posix_code);
295  }
297 
299  bool ok() const { return (state_ == NULL); }
300 
302  bool IsNotFound() const { return code() == kNotFound; }
303 
305  bool IsCorruption() const { return code() == kCorruption; }
306 
308  bool IsNotSupported() const { return code() == kNotSupported; }
309 
311  bool IsIOError() const { return code() == kIOError; }
312 
314  bool IsInvalidArgument() const { return code() == kInvalidArgument; }
315 
317  bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
318 
320  bool IsRuntimeError() const { return code() == kRuntimeError; }
321 
323  bool IsNetworkError() const { return code() == kNetworkError; }
324 
326  bool IsIllegalState() const { return code() == kIllegalState; }
327 
329  bool IsNotAuthorized() const { return code() == kNotAuthorized; }
330 
332  bool IsAborted() const { return code() == kAborted; }
333 
335  bool IsRemoteError() const { return code() == kRemoteError; }
336 
338  bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
339 
341  bool IsTimedOut() const { return code() == kTimedOut; }
342 
344  bool IsUninitialized() const { return code() == kUninitialized; }
345 
347  bool IsConfigurationError() const { return code() == kConfigurationError; }
348 
350  bool IsIncomplete() const { return code() == kIncomplete; }
351 
353  bool IsEndOfFile() const { return code() == kEndOfFile; }
354 
356  bool IsDiskFailure() const {
357  switch (posix_code()) {
358  case EIO:
359  case ENODEV:
360  case ENXIO:
361  case EROFS:
362  return true;
363  }
364  return false;
365  }
366 
369  std::string ToString() const;
370 
373  std::string CodeAsString() const;
374 
383  Slice message() const;
384 
387  int16_t posix_code() const;
388 
397  Status CloneAndPrepend(const Slice& msg) const;
398 
407  Status CloneAndAppend(const Slice& msg) const;
408 
411  size_t memory_footprint_excluding_this() const;
412 
415  size_t memory_footprint_including_this() const;
416 
417  private:
418  // OK status has a NULL state_. Otherwise, state_ is a new[] array
419  // of the following form:
420  // state_[0..3] == length of message
421  // state_[4] == code
422  // state_[5..6] == posix_code
423  // state_[7..] == message
424  const char* state_;
425 
426  enum Code {
427  kOk = 0,
428  kNotFound = 1,
429  kCorruption = 2,
430  kNotSupported = 3,
431  kInvalidArgument = 4,
432  kIOError = 5,
433  kAlreadyPresent = 6,
434  kRuntimeError = 7,
435  kNetworkError = 8,
436  kIllegalState = 9,
437  kNotAuthorized = 10,
438  kAborted = 11,
439  kRemoteError = 12,
440  kServiceUnavailable = 13,
441  kTimedOut = 14,
442  kUninitialized = 15,
443  kConfigurationError = 16,
444  kIncomplete = 17,
445  kEndOfFile = 18,
446  // NOTE: Remember to duplicate these constants into wire_protocol.proto and
447  // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
448  // Also remember to make the same changes to the java client in Status.java.
449  //
450  // TODO: Move error codes into an error_code.proto or something similar.
451  };
452  COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
453 
454  Code code() const {
455  return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
456  }
457 
458  Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
459  static const char* CopyState(const char* s);
460 };
461 
462 inline Status::Status(const Status& s) {
463  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
464 }
465 
466 inline Status& Status::operator=(const Status& s) {
467  // The following condition catches both aliasing (when this == &s),
468  // and the common case where both s and *this are OK.
469  if (state_ != s.state_) {
470  delete[] state_;
471  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
472  }
473  return *this;
474 }
475 
476 #if __cplusplus >= 201103L
477 inline Status::Status(Status&& s) noexcept : state_(s.state_) {
478  s.state_ = nullptr;
479 }
480 
481 inline Status& Status::operator=(Status&& s) noexcept {
482  if (state_ != s.state_) {
483  delete[] state_;
484  state_ = s.state_;
485  s.state_ = nullptr;
486  }
487  return *this;
488 }
489 #endif
490 
491 } // namespace kudu
492 
493 #endif // KUDU_UTIL_STATUS_H_
bool IsNotSupported() const
Definition: status.h:308
bool IsNotAuthorized() const
Definition: status.h:329
bool IsDiskFailure() const
Definition: status.h:356
Definition: callbacks.h:28
bool IsNotFound() const
Definition: status.h:302
bool IsUninitialized() const
Definition: status.h:344
Status & operator=(const Status &s)
Definition: status.h:466
bool IsIllegalState() const
Definition: status.h:326
bool IsAborted() const
Definition: status.h:332
Status()
Create an object representing success status.
Definition: status.h:148
bool IsEndOfFile() const
Definition: status.h:353
bool IsIncomplete() const
Definition: status.h:350
bool IsCorruption() const
Definition: status.h:305
bool IsServiceUnavailable() const
Definition: status.h:338
bool IsIOError() const
Definition: status.h:311
bool IsRemoteError() const
Definition: status.h:335
static Status OK()
Definition: status.h:210
A wrapper around externally allocated data.
Definition: slice.h:50
bool IsNetworkError() const
Definition: status.h:323
A representation of an operation&#39;s outcome.
Definition: status.h:145
bool ok() const
Definition: status.h:299
bool IsInvalidArgument() const
Definition: status.h:314
bool IsTimedOut() const
Definition: status.h:341
bool IsRuntimeError() const
Definition: status.h:320
bool IsAlreadyPresent() const
Definition: status.h:317
bool IsConfigurationError() const
Definition: status.h:347