Apache Arrow (C++)
A columnar in-memory analytics layer designed to accelerate big data.
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 // Adapted from Apache Kudu, TensorFlow
14 
15 #ifndef ARROW_STATUS_H_
16 #define ARROW_STATUS_H_
17 
18 #include <cstring>
19 #include <iosfwd>
20 #include <string>
21 #include <utility>
22 
23 #ifdef ARROW_EXTRA_ERROR_CONTEXT
24 #include <sstream>
25 #endif
26 
27 #include "arrow/util/macros.h"
28 #include "arrow/util/visibility.h"
29 
30 #ifdef ARROW_EXTRA_ERROR_CONTEXT
31 
32 #define RETURN_NOT_OK(s) \
33  do { \
34  ::arrow::Status _s = (s); \
35  if (ARROW_PREDICT_FALSE(!_s.ok())) { \
36  std::stringstream ss; \
37  ss << __FILE__ << ":" << __LINE__ << " code: " << #s << "\n" << _s.message(); \
38  return Status(_s.code(), ss.str()); \
39  } \
40  } while (0)
41 
42 #else
43 
44 #define RETURN_NOT_OK(s) \
45  do { \
46  ::arrow::Status _s = (s); \
47  if (ARROW_PREDICT_FALSE(!_s.ok())) { \
48  return _s; \
49  } \
50  } while (false)
51 
52 #endif // ARROW_EXTRA_ERROR_CONTEXT
53 
54 #define RETURN_NOT_OK_ELSE(s, else_) \
55  do { \
56  ::arrow::Status _s = (s); \
57  if (!_s.ok()) { \
58  else_; \
59  return _s; \
60  } \
61  } while (false)
62 
63 // This is used by other codebases. The macros above
64 // should probably have that prefix, but there is a
65 // lot of code that already uses that macro and changing
66 // it would be of no benefit.
67 #define ARROW_RETURN_NOT_OK(s) RETURN_NOT_OK(s)
68 
69 namespace arrow {
70 
71 enum class StatusCode : char {
72  OK = 0,
73  OutOfMemory = 1,
74  KeyError = 2,
75  TypeError = 3,
76  Invalid = 4,
77  IOError = 5,
78  CapacityError = 6,
79  UnknownError = 9,
80  NotImplemented = 10,
81  SerializationError = 11,
82  PythonError = 12,
83  PlasmaObjectExists = 20,
85  PlasmaStoreFull = 22,
87 };
88 
89 #if defined(__clang__)
90 // Only clang supports warn_unused_result as a type annotation.
91 class ARROW_MUST_USE_RESULT ARROW_EXPORT Status;
92 #endif
93 
94 class ARROW_EXPORT Status {
95  public:
96  // Create a success status.
97  Status() noexcept : state_(NULL) {}
98  ~Status() noexcept {
99  // ARROW-2400: On certain compilers, splitting off the slow path improves
100  // performance significantly.
101  if (ARROW_PREDICT_FALSE(state_ != NULL)) {
102  DeleteState();
103  }
104  }
105 
106  Status(StatusCode code, const std::string& msg);
107 
108  // Copy the specified status.
109  Status(const Status& s);
110  Status& operator=(const Status& s);
111 
112  // Move the specified status.
113  Status(Status&& s) noexcept;
114  Status& operator=(Status&& s) noexcept;
115 
116  // AND the statuses.
117  Status operator&(const Status& s) const noexcept;
118  Status operator&(Status&& s) const noexcept;
119  Status& operator&=(const Status& s) noexcept;
120  Status& operator&=(Status&& s) noexcept;
121 
122  // Return a success status.
123  static Status OK() { return Status(); }
124 
125  // Return error status of an appropriate type.
126  static Status OutOfMemory(const std::string& msg) {
127  return Status(StatusCode::OutOfMemory, msg);
128  }
129 
130  static Status KeyError(const std::string& msg) {
131  return Status(StatusCode::KeyError, msg);
132  }
133 
134  static Status TypeError(const std::string& msg) {
135  return Status(StatusCode::TypeError, msg);
136  }
137 
138  static Status UnknownError(const std::string& msg) {
139  return Status(StatusCode::UnknownError, msg);
140  }
141 
142  static Status NotImplemented(const std::string& msg) {
143  return Status(StatusCode::NotImplemented, msg);
144  }
145 
146  static Status Invalid(const std::string& msg) {
147  return Status(StatusCode::Invalid, msg);
148  }
149 
150  static Status CapacityError(const std::string& msg) {
151  return Status(StatusCode::CapacityError, msg);
152  }
153 
154  static Status IOError(const std::string& msg) {
155  return Status(StatusCode::IOError, msg);
156  }
157 
158  static Status SerializationError(const std::string& msg) {
160  }
161 
162  static Status PlasmaObjectExists(const std::string& msg) {
164  }
165 
166  static Status PlasmaObjectNonexistent(const std::string& msg) {
168  }
169 
170  static Status PlasmaObjectAlreadySealed(const std::string& msg) {
172  }
173 
174  static Status PlasmaStoreFull(const std::string& msg) {
175  return Status(StatusCode::PlasmaStoreFull, msg);
176  }
177 
178  // Returns true iff the status indicates success.
179  bool ok() const { return (state_ == NULL); }
180 
181  bool IsOutOfMemory() const { return code() == StatusCode::OutOfMemory; }
182  bool IsKeyError() const { return code() == StatusCode::KeyError; }
183  bool IsInvalid() const { return code() == StatusCode::Invalid; }
184  bool IsIOError() const { return code() == StatusCode::IOError; }
185  bool IsCapacityError() const { return code() == StatusCode::CapacityError; }
186  bool IsTypeError() const { return code() == StatusCode::TypeError; }
187  bool IsUnknownError() const { return code() == StatusCode::UnknownError; }
188  bool IsNotImplemented() const { return code() == StatusCode::NotImplemented; }
189  // An object could not be serialized or deserialized.
190  bool IsSerializationError() const { return code() == StatusCode::SerializationError; }
191  // An error is propagated from a nested Python function.
192  bool IsPythonError() const { return code() == StatusCode::PythonError; }
193  // An object with this object ID already exists in the plasma store.
194  bool IsPlasmaObjectExists() const { return code() == StatusCode::PlasmaObjectExists; }
195  // An object was requested that doesn't exist in the plasma store.
197  return code() == StatusCode::PlasmaObjectNonexistent;
198  }
199  // An already sealed object is tried to be sealed again.
201  return code() == StatusCode::PlasmaObjectAlreadySealed;
202  }
203  // An object is too large to fit into the plasma store.
204  bool IsPlasmaStoreFull() const { return code() == StatusCode::PlasmaStoreFull; }
205 
206  // Return a string representation of this status suitable for printing.
207  // Returns the string "OK" for success.
208  std::string ToString() const;
209 
210  // Return a string representation of the status code, without the message
211  // text or posix code information.
212  std::string CodeAsString() const;
213 
214  StatusCode code() const { return ok() ? StatusCode::OK : state_->code; }
215 
216  std::string message() const { return ok() ? "" : state_->msg; }
217 
218  private:
219  struct State {
220  StatusCode code;
221  std::string msg;
222  };
223  // OK status has a `NULL` state_. Otherwise, `state_` points to
224  // a `State` structure containing the error code and message(s)
225  State* state_;
226 
227  void DeleteState() {
228  delete state_;
229  state_ = NULL;
230  }
231  void CopyFrom(const Status& s);
232  void MoveFrom(Status& s);
233 };
234 
235 static inline std::ostream& operator<<(std::ostream& os, const Status& x) {
236  os << x.ToString();
237  return os;
238 }
239 
240 inline void Status::MoveFrom(Status& s) {
241  delete state_;
242  state_ = s.state_;
243  s.state_ = NULL;
244 }
245 
246 inline Status::Status(const Status& s)
247  : state_((s.state_ == NULL) ? NULL : new State(*s.state_)) {}
248 
249 inline Status& Status::operator=(const Status& s) {
250  // The following condition catches both aliasing (when this == &s),
251  // and the common case where both s and *this are ok.
252  if (state_ != s.state_) {
253  CopyFrom(s);
254  }
255  return *this;
256 }
257 
258 inline Status::Status(Status&& s) noexcept : state_(s.state_) { s.state_ = NULL; }
259 
260 inline Status& Status::operator=(Status&& s) noexcept {
261  MoveFrom(s);
262  return *this;
263 }
264 
265 inline Status Status::operator&(const Status& s) const noexcept {
266  if (ok()) {
267  return s;
268  } else {
269  return *this;
270  }
271 }
272 
273 inline Status Status::operator&(Status&& s) const noexcept {
274  if (ok()) {
275  return std::move(s);
276  } else {
277  return *this;
278  }
279 }
280 
281 inline Status& Status::operator&=(const Status& s) noexcept {
282  if (ok() && !s.ok()) {
283  CopyFrom(s);
284  }
285  return *this;
286 }
287 
288 inline Status& Status::operator&=(Status&& s) noexcept {
289  if (ok() && !s.ok()) {
290  MoveFrom(s);
291  }
292  return *this;
293 }
294 
295 } // namespace arrow
296 
297 #endif // ARROW_STATUS_H_
bool IsPlasmaObjectNonexistent() const
Definition: status.h:196
StatusCode code() const
Definition: status.h:214
bool IsUnknownError() const
Definition: status.h:187
StatusCode
Definition: status.h:71
Status & operator=(const Status &s)
Definition: status.h:249
bool IsPlasmaObjectExists() const
Definition: status.h:194
static Status PlasmaObjectExists(const std::string &msg)
Definition: status.h:162
#define ARROW_PREDICT_FALSE(x)
Definition: macros.h:48
Definition: status.h:94
bool ok() const
Definition: status.h:179
Status() noexcept
Definition: status.h:97
#define ARROW_MUST_USE_RESULT
Definition: macros.h:58
bool IsOutOfMemory() const
Definition: status.h:181
bool IsCapacityError() const
Definition: status.h:185
static Status OK()
Definition: status.h:123
static Status KeyError(const std::string &msg)
Definition: status.h:130
~Status() noexcept
Definition: status.h:98
static Status PlasmaObjectNonexistent(const std::string &msg)
Definition: status.h:166
static Status Invalid(const std::string &msg)
Definition: status.h:146
bool IsIOError() const
Definition: status.h:184
static Status IOError(const std::string &msg)
Definition: status.h:154
Status & operator &=(const Status &s) noexcept
bool IsKeyError() const
Definition: status.h:182
static Status UnknownError(const std::string &msg)
Definition: status.h:138
static Status TypeError(const std::string &msg)
Definition: status.h:134
bool IsSerializationError() const
Definition: status.h:190
bool IsTypeError() const
Definition: status.h:186
Top-level namespace for Apache Arrow C++ API.
Definition: adapter.h:32
bool IsPythonError() const
Definition: status.h:192
static Status OutOfMemory(const std::string &msg)
Definition: status.h:126
bool IsNotImplemented() const
Definition: status.h:188
static Status NotImplemented(const std::string &msg)
Definition: status.h:142
bool IsPlasmaStoreFull() const
Definition: status.h:204
std::string message() const
Definition: status.h:216
static Status PlasmaObjectAlreadySealed(const std::string &msg)
Definition: status.h:170
Status operator &(const Status &s) const noexcept
bool IsPlasmaObjectAlreadySealed() const
Definition: status.h:200
static Status SerializationError(const std::string &msg)
Definition: status.h:158
bool IsInvalid() const
Definition: status.h:183
static Status CapacityError(const std::string &msg)
Definition: status.h:150
static Status PlasmaStoreFull(const std::string &msg)
Definition: status.h:174