1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 // A Status encapsulates the result of an operation. It may indicate success,
10 // or it may indicate an error with an associated error message.
12 // Multiple threads can invoke const methods on a Status without
13 // external synchronization, but if any of the threads may call a
14 // non-const method, all threads accessing the same Status must use
15 // external synchronization.
20 #include "rocksdb/slice.h"
22 namespace ROCKSDB_NAMESPACE
{
26 // Create a success status.
27 Status() : code_(kOk
), subcode_(kNone
), sev_(kNoError
), state_(nullptr) {}
28 ~Status() { delete[] state_
; }
30 // Copy the specified status.
31 Status(const Status
& s
);
32 Status
& operator=(const Status
& s
);
34 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
38 Status
& operator=(Status
&& s
)
39 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
43 bool operator==(const Status
& rhs
) const;
44 bool operator!=(const Status
& rhs
) const;
46 enum Code
: unsigned char {
55 kShutdownInProgress
= 8,
61 kCompactionTooLarge
= 14,
62 kColumnFamilyDropped
= 15,
66 Code
code() const { return code_
; }
68 enum SubCode
: unsigned char {
79 KMergeOperandsInsufficientCapacity
= 10,
80 kManualCompactionPaused
= 11,
84 SubCode
subcode() const { return subcode_
; }
86 enum Severity
: unsigned char {
91 kUnrecoverableError
= 4,
95 Status(const Status
& s
, Severity sev
);
96 Severity
severity() const { return sev_
; }
98 // Returns a C style string indicating the message of the Status
99 const char* getState() const { return state_
; }
101 // Return a success status.
102 static Status
OK() { return Status(); }
104 // Return error status of an appropriate type.
105 static Status
NotFound(const Slice
& msg
, const Slice
& msg2
= Slice()) {
106 return Status(kNotFound
, msg
, msg2
);
108 // Fast path for not found without malloc;
109 static Status
NotFound(SubCode msg
= kNone
) { return Status(kNotFound
, msg
); }
111 static Status
Corruption(const Slice
& msg
, const Slice
& msg2
= Slice()) {
112 return Status(kCorruption
, msg
, msg2
);
114 static Status
Corruption(SubCode msg
= kNone
) {
115 return Status(kCorruption
, msg
);
118 static Status
NotSupported(const Slice
& msg
, const Slice
& msg2
= Slice()) {
119 return Status(kNotSupported
, msg
, msg2
);
121 static Status
NotSupported(SubCode msg
= kNone
) {
122 return Status(kNotSupported
, msg
);
125 static Status
InvalidArgument(const Slice
& msg
, const Slice
& msg2
= Slice()) {
126 return Status(kInvalidArgument
, msg
, msg2
);
128 static Status
InvalidArgument(SubCode msg
= kNone
) {
129 return Status(kInvalidArgument
, msg
);
132 static Status
IOError(const Slice
& msg
, const Slice
& msg2
= Slice()) {
133 return Status(kIOError
, msg
, msg2
);
135 static Status
IOError(SubCode msg
= kNone
) { return Status(kIOError
, msg
); }
137 static Status
MergeInProgress(const Slice
& msg
, const Slice
& msg2
= Slice()) {
138 return Status(kMergeInProgress
, msg
, msg2
);
140 static Status
MergeInProgress(SubCode msg
= kNone
) {
141 return Status(kMergeInProgress
, msg
);
144 static Status
Incomplete(const Slice
& msg
, const Slice
& msg2
= Slice()) {
145 return Status(kIncomplete
, msg
, msg2
);
147 static Status
Incomplete(SubCode msg
= kNone
) {
148 return Status(kIncomplete
, msg
);
151 static Status
ShutdownInProgress(SubCode msg
= kNone
) {
152 return Status(kShutdownInProgress
, msg
);
154 static Status
ShutdownInProgress(const Slice
& msg
,
155 const Slice
& msg2
= Slice()) {
156 return Status(kShutdownInProgress
, msg
, msg2
);
158 static Status
Aborted(SubCode msg
= kNone
) { return Status(kAborted
, msg
); }
159 static Status
Aborted(const Slice
& msg
, const Slice
& msg2
= Slice()) {
160 return Status(kAborted
, msg
, msg2
);
163 static Status
Busy(SubCode msg
= kNone
) { return Status(kBusy
, msg
); }
164 static Status
Busy(const Slice
& msg
, const Slice
& msg2
= Slice()) {
165 return Status(kBusy
, msg
, msg2
);
168 static Status
TimedOut(SubCode msg
= kNone
) { return Status(kTimedOut
, msg
); }
169 static Status
TimedOut(const Slice
& msg
, const Slice
& msg2
= Slice()) {
170 return Status(kTimedOut
, msg
, msg2
);
173 static Status
Expired(SubCode msg
= kNone
) { return Status(kExpired
, msg
); }
174 static Status
Expired(const Slice
& msg
, const Slice
& msg2
= Slice()) {
175 return Status(kExpired
, msg
, msg2
);
178 static Status
TryAgain(SubCode msg
= kNone
) { return Status(kTryAgain
, msg
); }
179 static Status
TryAgain(const Slice
& msg
, const Slice
& msg2
= Slice()) {
180 return Status(kTryAgain
, msg
, msg2
);
183 static Status
CompactionTooLarge(SubCode msg
= kNone
) {
184 return Status(kCompactionTooLarge
, msg
);
186 static Status
CompactionTooLarge(const Slice
& msg
,
187 const Slice
& msg2
= Slice()) {
188 return Status(kCompactionTooLarge
, msg
, msg2
);
191 static Status
ColumnFamilyDropped(SubCode msg
= kNone
) {
192 return Status(kColumnFamilyDropped
, msg
);
195 static Status
ColumnFamilyDropped(const Slice
& msg
,
196 const Slice
& msg2
= Slice()) {
197 return Status(kColumnFamilyDropped
, msg
, msg2
);
200 static Status
NoSpace() { return Status(kIOError
, kNoSpace
); }
201 static Status
NoSpace(const Slice
& msg
, const Slice
& msg2
= Slice()) {
202 return Status(kIOError
, kNoSpace
, msg
, msg2
);
205 static Status
MemoryLimit() { return Status(kAborted
, kMemoryLimit
); }
206 static Status
MemoryLimit(const Slice
& msg
, const Slice
& msg2
= Slice()) {
207 return Status(kAborted
, kMemoryLimit
, msg
, msg2
);
210 static Status
SpaceLimit() { return Status(kIOError
, kSpaceLimit
); }
211 static Status
SpaceLimit(const Slice
& msg
, const Slice
& msg2
= Slice()) {
212 return Status(kIOError
, kSpaceLimit
, msg
, msg2
);
215 static Status
PathNotFound() { return Status(kIOError
, kPathNotFound
); }
216 static Status
PathNotFound(const Slice
& msg
, const Slice
& msg2
= Slice()) {
217 return Status(kIOError
, kPathNotFound
, msg
, msg2
);
220 // Returns true iff the status indicates success.
221 bool ok() const { return code() == kOk
; }
223 // Returns true iff the status indicates a NotFound error.
224 bool IsNotFound() const { return code() == kNotFound
; }
226 // Returns true iff the status indicates a Corruption error.
227 bool IsCorruption() const { return code() == kCorruption
; }
229 // Returns true iff the status indicates a NotSupported error.
230 bool IsNotSupported() const { return code() == kNotSupported
; }
232 // Returns true iff the status indicates an InvalidArgument error.
233 bool IsInvalidArgument() const { return code() == kInvalidArgument
; }
235 // Returns true iff the status indicates an IOError.
236 bool IsIOError() const { return code() == kIOError
; }
238 // Returns true iff the status indicates an MergeInProgress.
239 bool IsMergeInProgress() const { return code() == kMergeInProgress
; }
241 // Returns true iff the status indicates Incomplete
242 bool IsIncomplete() const { return code() == kIncomplete
; }
244 // Returns true iff the status indicates Shutdown In progress
245 bool IsShutdownInProgress() const { return code() == kShutdownInProgress
; }
247 bool IsTimedOut() const { return code() == kTimedOut
; }
249 bool IsAborted() const { return code() == kAborted
; }
251 bool IsLockLimit() const {
252 return code() == kAborted
&& subcode() == kLockLimit
;
255 // Returns true iff the status indicates that a resource is Busy and
256 // temporarily could not be acquired.
257 bool IsBusy() const { return code() == kBusy
; }
259 bool IsDeadlock() const { return code() == kBusy
&& subcode() == kDeadlock
; }
261 // Returns true iff the status indicated that the operation has Expired.
262 bool IsExpired() const { return code() == kExpired
; }
264 // Returns true iff the status indicates a TryAgain error.
265 // This usually means that the operation failed, but may succeed if
267 bool IsTryAgain() const { return code() == kTryAgain
; }
269 // Returns true iff the status indicates the proposed compaction is too large
270 bool IsCompactionTooLarge() const { return code() == kCompactionTooLarge
; }
272 // Returns true iff the status indicates Column Family Dropped
273 bool IsColumnFamilyDropped() const { return code() == kColumnFamilyDropped
; }
275 // Returns true iff the status indicates a NoSpace error
276 // This is caused by an I/O error returning the specific "out of space"
277 // error condition. Stricto sensu, an NoSpace error is an I/O error
278 // with a specific subcode, enabling users to take the appropriate action
280 bool IsNoSpace() const {
281 return (code() == kIOError
) && (subcode() == kNoSpace
);
284 // Returns true iff the status indicates a memory limit error. There may be
285 // cases where we limit the memory used in certain operations (eg. the size
286 // of a write batch) in order to avoid out of memory exceptions.
287 bool IsMemoryLimit() const {
288 return (code() == kAborted
) && (subcode() == kMemoryLimit
);
291 // Returns true iff the status indicates a PathNotFound error
292 // This is caused by an I/O error returning the specific "no such file or
293 // directory" error condition. A PathNotFound error is an I/O error with
294 // a specific subcode, enabling users to take appropriate action if necessary
295 bool IsPathNotFound() const {
296 return (code() == kIOError
) && (subcode() == kPathNotFound
);
299 // Returns true iff the status indicates manual compaction paused. This
300 // is caused by a call to PauseManualCompaction
301 bool IsManualCompactionPaused() const {
302 return (code() == kIncomplete
) && (subcode() == kManualCompactionPaused
);
305 // Return a string representation of this status suitable for printing.
306 // Returns the string "OK" for success.
307 std::string
ToString() const;
310 // A nullptr state_ (which is always the case for OK) means the message
312 // of the following form:
313 // state_[0..3] == length of message
314 // state_[4..] == message
320 explicit Status(Code _code
, SubCode _subcode
= kNone
)
321 : code_(_code
), subcode_(_subcode
), sev_(kNoError
), state_(nullptr) {}
323 Status(Code _code
, SubCode _subcode
, const Slice
& msg
, const Slice
& msg2
);
324 Status(Code _code
, const Slice
& msg
, const Slice
& msg2
)
325 : Status(_code
, kNone
, msg
, msg2
) {}
327 static const char* CopyState(const char* s
);
330 inline Status::Status(const Status
& s
)
331 : code_(s
.code_
), subcode_(s
.subcode_
), sev_(s
.sev_
) {
332 state_
= (s
.state_
== nullptr) ? nullptr : CopyState(s
.state_
);
334 inline Status::Status(const Status
& s
, Severity sev
)
335 : code_(s
.code_
), subcode_(s
.subcode_
), sev_(sev
) {
336 state_
= (s
.state_
== nullptr) ? nullptr : CopyState(s
.state_
);
338 inline Status
& Status::operator=(const Status
& s
) {
339 // The following condition catches both aliasing (when this == &s),
340 // and the common case where both s and *this are ok.
343 subcode_
= s
.subcode_
;
346 state_
= (s
.state_
== nullptr) ? nullptr : CopyState(s
.state_
);
351 inline Status::Status(Status
&& s
)
352 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
356 *this = std::move(s
);
359 inline Status
& Status::operator=(Status
&& s
)
360 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
365 code_
= std::move(s
.code_
);
367 subcode_
= std::move(s
.subcode_
);
369 sev_
= std::move(s
.sev_
);
373 std::swap(state_
, s
.state_
);
378 inline bool Status::operator==(const Status
& rhs
) const {
379 return (code_
== rhs
.code_
);
382 inline bool Status::operator!=(const Status
& rhs
) const {
383 return !(*this == rhs
);
386 } // namespace ROCKSDB_NAMESPACE