Kudu C++ client API
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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_WARN_NOT_OK(to_call, warning_prefix) do { \
57  const ::kudu::Status& _s = (to_call); \
58  if (PREDICT_FALSE(!_s.ok())) { \
59  KUDU_LOG(WARNING) << (warning_prefix) << ": " << _s.ToString(); \
60  } \
61  } while (0);
62 
64 #define KUDU_LOG_AND_RETURN(level, status) do { \
65  const ::kudu::Status& _s = (status); \
66  KUDU_LOG(level) << _s.ToString(); \
67  return _s; \
68  } while (0);
69 
71 #define KUDU_RETURN_NOT_OK_LOG(s, level, msg) do { \
72  const ::kudu::Status& _s = (s); \
73  if (PREDICT_FALSE(!_s.ok())) { \
74  KUDU_LOG(level) << "Status: " << _s.ToString() << " " << (msg); \
75  return _s; \
76  } \
77  } while (0);
78 
81 #define KUDU_CHECK_OK_PREPEND(to_call, msg) do { \
82  const ::kudu::Status& _s = (to_call); \
83  KUDU_CHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
84  } while (0);
85 
88 #define KUDU_CHECK_OK(s) KUDU_CHECK_OK_PREPEND(s, "Bad status")
89 
92 #define KUDU_DCHECK_OK_PREPEND(to_call, msg) do { \
93  const ::kudu::Status& _s = (to_call); \
94  KUDU_DCHECK(_s.ok()) << (msg) << ": " << _s.ToString(); \
95  } while (0);
96 
99 #define KUDU_DCHECK_OK(s) KUDU_DCHECK_OK_PREPEND(s, "Bad status")
100 
114 #ifdef KUDU_HEADERS_USE_SHORT_STATUS_MACROS
115 #define RETURN_NOT_OK KUDU_RETURN_NOT_OK
116 #define RETURN_NOT_OK_PREPEND KUDU_RETURN_NOT_OK_PREPEND
117 #define RETURN_NOT_OK_RET KUDU_RETURN_NOT_OK_RET
118 #define WARN_NOT_OK KUDU_WARN_NOT_OK
119 #define LOG_AND_RETURN KUDU_LOG_AND_RETURN
120 #define RETURN_NOT_OK_LOG KUDU_RETURN_NOT_OK_LOG
121 #define CHECK_OK_PREPEND KUDU_CHECK_OK_PREPEND
122 #define CHECK_OK KUDU_CHECK_OK
123 #define DCHECK_OK_PREPEND KUDU_DCHECK_OK_PREPEND
124 #define DCHECK_OK KUDU_DCHECK_OK
125 
126 // These are standard glog macros.
127 #define KUDU_LOG LOG
128 #define KUDU_CHECK CHECK
129 #define KUDU_DCHECK DCHECK
130 #endif
131 
132 namespace kudu {
133 
135 class KUDU_EXPORT Status {
136  public:
138  Status() : state_(NULL) { }
139 
140  ~Status() { delete[] state_; }
141 
146  Status(const Status& s);
147 
153  Status& operator=(const Status& s);
154 
155 #if __cplusplus >= 201103L
156  Status(Status&& s);
161 
167  Status& operator=(Status&& s);
168 
190  template<typename F>
191  Status AndThen(F op) {
192  if (ok()) {
193  return op();
194  }
195  return *this;
196  }
197 #endif
198 
200  static Status OK() { return Status(); }
201 
202 
214  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice(),
215  int16_t posix_code = -1) {
216  return Status(kNotFound, msg, msg2, posix_code);
217  }
218  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice(),
219  int16_t posix_code = -1) {
220  return Status(kCorruption, msg, msg2, posix_code);
221  }
222  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice(),
223  int16_t posix_code = -1) {
224  return Status(kNotSupported, msg, msg2, posix_code);
225  }
226  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice(),
227  int16_t posix_code = -1) {
228  return Status(kInvalidArgument, msg, msg2, posix_code);
229  }
230  static Status IOError(const Slice& msg, const Slice& msg2 = Slice(),
231  int16_t posix_code = -1) {
232  return Status(kIOError, msg, msg2, posix_code);
233  }
234  static Status AlreadyPresent(const Slice& msg, const Slice& msg2 = Slice(),
235  int16_t posix_code = -1) {
236  return Status(kAlreadyPresent, msg, msg2, posix_code);
237  }
238  static Status RuntimeError(const Slice& msg, const Slice& msg2 = Slice(),
239  int16_t posix_code = -1) {
240  return Status(kRuntimeError, msg, msg2, posix_code);
241  }
242  static Status NetworkError(const Slice& msg, const Slice& msg2 = Slice(),
243  int16_t posix_code = -1) {
244  return Status(kNetworkError, msg, msg2, posix_code);
245  }
246  static Status IllegalState(const Slice& msg, const Slice& msg2 = Slice(),
247  int16_t posix_code = -1) {
248  return Status(kIllegalState, msg, msg2, posix_code);
249  }
250  static Status NotAuthorized(const Slice& msg, const Slice& msg2 = Slice(),
251  int16_t posix_code = -1) {
252  return Status(kNotAuthorized, msg, msg2, posix_code);
253  }
254  static Status Aborted(const Slice& msg, const Slice& msg2 = Slice(),
255  int16_t posix_code = -1) {
256  return Status(kAborted, msg, msg2, posix_code);
257  }
258  static Status RemoteError(const Slice& msg, const Slice& msg2 = Slice(),
259  int16_t posix_code = -1) {
260  return Status(kRemoteError, msg, msg2, posix_code);
261  }
262  static Status ServiceUnavailable(const Slice& msg, const Slice& msg2 = Slice(),
263  int16_t posix_code = -1) {
264  return Status(kServiceUnavailable, msg, msg2, posix_code);
265  }
266  static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice(),
267  int16_t posix_code = -1) {
268  return Status(kTimedOut, msg, msg2, posix_code);
269  }
270  static Status Uninitialized(const Slice& msg, const Slice& msg2 = Slice(),
271  int16_t posix_code = -1) {
272  return Status(kUninitialized, msg, msg2, posix_code);
273  }
274  static Status ConfigurationError(const Slice& msg, const Slice& msg2 = Slice(),
275  int16_t posix_code = -1) {
276  return Status(kConfigurationError, msg, msg2, posix_code);
277  }
278  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice(),
279  int64_t posix_code = -1) {
280  return Status(kIncomplete, msg, msg2, posix_code);
281  }
282  static Status EndOfFile(const Slice& msg, const Slice& msg2 = Slice(),
283  int64_t posix_code = -1) {
284  return Status(kEndOfFile, msg, msg2, posix_code);
285  }
287 
289  bool ok() const { return (state_ == NULL); }
290 
292  bool IsNotFound() const { return code() == kNotFound; }
293 
295  bool IsCorruption() const { return code() == kCorruption; }
296 
298  bool IsNotSupported() const { return code() == kNotSupported; }
299 
301  bool IsIOError() const { return code() == kIOError; }
302 
304  bool IsInvalidArgument() const { return code() == kInvalidArgument; }
305 
307  bool IsAlreadyPresent() const { return code() == kAlreadyPresent; }
308 
310  bool IsRuntimeError() const { return code() == kRuntimeError; }
311 
313  bool IsNetworkError() const { return code() == kNetworkError; }
314 
316  bool IsIllegalState() const { return code() == kIllegalState; }
317 
319  bool IsNotAuthorized() const { return code() == kNotAuthorized; }
320 
322  bool IsAborted() const { return code() == kAborted; }
323 
325  bool IsRemoteError() const { return code() == kRemoteError; }
326 
328  bool IsServiceUnavailable() const { return code() == kServiceUnavailable; }
329 
331  bool IsTimedOut() const { return code() == kTimedOut; }
332 
334  bool IsUninitialized() const { return code() == kUninitialized; }
335 
337  bool IsConfigurationError() const { return code() == kConfigurationError; }
338 
340  bool IsIncomplete() const { return code() == kIncomplete; }
341 
343  bool IsEndOfFile() const { return code() == kEndOfFile; }
344 
346  bool IsDiskFailure() const {
347  switch (posix_code()) {
348  case EIO:
349  case ENODEV:
350  case ENXIO:
351  case EROFS:
352  return true;
353  }
354  return false;
355  }
356 
359  std::string ToString() const;
360 
363  std::string CodeAsString() const;
364 
373  Slice message() const;
374 
377  int16_t posix_code() const;
378 
387  Status CloneAndPrepend(const Slice& msg) const;
388 
397  Status CloneAndAppend(const Slice& msg) const;
398 
401  size_t memory_footprint_excluding_this() const;
402 
405  size_t memory_footprint_including_this() const;
406 
407  private:
408  // OK status has a NULL state_. Otherwise, state_ is a new[] array
409  // of the following form:
410  // state_[0..3] == length of message
411  // state_[4] == code
412  // state_[5..6] == posix_code
413  // state_[7..] == message
414  const char* state_;
415 
416  enum Code {
417  kOk = 0,
418  kNotFound = 1,
419  kCorruption = 2,
420  kNotSupported = 3,
421  kInvalidArgument = 4,
422  kIOError = 5,
423  kAlreadyPresent = 6,
424  kRuntimeError = 7,
425  kNetworkError = 8,
426  kIllegalState = 9,
427  kNotAuthorized = 10,
428  kAborted = 11,
429  kRemoteError = 12,
430  kServiceUnavailable = 13,
431  kTimedOut = 14,
432  kUninitialized = 15,
433  kConfigurationError = 16,
434  kIncomplete = 17,
435  kEndOfFile = 18,
436  // NOTE: Remember to duplicate these constants into wire_protocol.proto and
437  // and to add StatusTo/FromPB ser/deser cases in wire_protocol.cc !
438  // Also remember to make the same changes to the java client in Status.java.
439  //
440  // TODO: Move error codes into an error_code.proto or something similar.
441  };
442  COMPILE_ASSERT(sizeof(Code) == 4, code_enum_size_is_part_of_abi);
443 
444  Code code() const {
445  return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
446  }
447 
448  Status(Code code, const Slice& msg, const Slice& msg2, int16_t posix_code);
449  static const char* CopyState(const char* s);
450 };
451 
452 inline Status::Status(const Status& s) {
453  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
454 }
455 
456 inline Status& Status::operator=(const Status& s) {
457  // The following condition catches both aliasing (when this == &s),
458  // and the common case where both s and *this are OK.
459  if (state_ != s.state_) {
460  delete[] state_;
461  state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
462  }
463  return *this;
464 }
465 
466 #if __cplusplus >= 201103L
467 inline Status::Status(Status&& s) : state_(s.state_) {
468  s.state_ = nullptr;
469 }
470 
471 inline Status& Status::operator=(Status&& s) {
472  if (state_ != s.state_) {
473  delete[] state_;
474  state_ = s.state_;
475  s.state_ = nullptr;
476  }
477  return *this;
478 }
479 #endif
480 
481 } // namespace kudu
482 
483 #endif // KUDU_UTIL_STATUS_H_
Status()
Create an object representing success status.
Definition: status.h:138
bool IsNotAuthorized() const
Definition: status.h:319
A representation of an operation&#39;s outcome.
Definition: status.h:135
bool IsIllegalState() const
Definition: status.h:316
bool ok() const
Definition: status.h:289
bool IsTimedOut() const
Definition: status.h:331
bool IsRemoteError() const
Definition: status.h:325
bool IsDiskFailure() const
Definition: status.h:346
bool IsServiceUnavailable() const
Definition: status.h:328
bool IsAborted() const
Definition: status.h:322
bool IsUninitialized() const
Definition: status.h:334
bool IsRuntimeError() const
Definition: status.h:310
bool IsAlreadyPresent() const
Definition: status.h:307
bool IsIOError() const
Definition: status.h:301
static Status OK()
Definition: status.h:200
A wrapper around externally allocated data.
Definition: slice.h:47
Status & operator=(const Status &s)
Definition: status.h:456
bool IsConfigurationError() const
Definition: status.h:337
bool IsInvalidArgument() const
Definition: status.h:304
bool IsCorruption() const
Definition: status.h:295
bool IsEndOfFile() const
Definition: status.h:343
bool IsNotSupported() const
Definition: status.h:298
bool IsNetworkError() const
Definition: status.h:313
bool IsIncomplete() const
Definition: status.h:340
bool IsNotFound() const
Definition: status.h:292