status.h 13.8 KB
Newer Older
1
// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
Siying Dong's avatar
Siying Dong 已提交
2
3
4
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
5
6
7
8
9
10
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// A Status encapsulates the result of an operation.  It may indicate success,
// or it may indicate an error with an associated error message.
11
12
13
14
15
//
// Multiple threads can invoke const methods on a Status without
// external synchronization, but if any of the threads may call a
// non-const method, all threads accessing the same Status must use
// external synchronization.
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
16

17
#pragma once
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
18

19
20
21
22
23
#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
#include <stdio.h>
#include <stdlib.h>
#endif

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
24
#include <string>
25
26
27
28
29

#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
#include "port/stack_trace.h"
#endif

30
#include "rocksdb/slice.h"
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
31

32
namespace ROCKSDB_NAMESPACE {
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
33
34
35
36

class Status {
 public:
  // Create a success status.
37
  Status() : code_(kOk), subcode_(kNone), sev_(kNoError), state_(nullptr) {}
38
39
40
41
42
43
44
45
46
47
  ~Status() {
#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
    if (!checked_) {
      fprintf(stderr, "Failed to check Status\n");
      port::PrintStack();
      abort();
    }
#endif  // ROCKSDB_ASSERT_STATUS_CHECKED
    delete[] state_;
  }
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
48
49
50

  // Copy the specified status.
  Status(const Status& s);
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
51
52
53
  Status& operator=(const Status& s);
  Status(Status&& s)
#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
54
      noexcept
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
55
#endif
56
      ;
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
57
58
  Status& operator=(Status&& s)
#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
59
      noexcept
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
60
#endif
61
      ;
agiardullo's avatar
agiardullo 已提交
62
63
  bool operator==(const Status& rhs) const;
  bool operator!=(const Status& rhs) const;
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
64

65
  enum Code : unsigned char {
agiardullo's avatar
agiardullo 已提交
66
67
68
69
70
71
72
73
74
75
76
77
78
    kOk = 0,
    kNotFound = 1,
    kCorruption = 2,
    kNotSupported = 3,
    kInvalidArgument = 4,
    kIOError = 5,
    kMergeInProgress = 6,
    kIncomplete = 7,
    kShutdownInProgress = 8,
    kTimedOut = 9,
    kAborted = 10,
    kBusy = 11,
    kExpired = 12,
79
    kTryAgain = 13,
80
81
82
    kCompactionTooLarge = 14,
    kColumnFamilyDropped = 15,
    kMaxCode
agiardullo's avatar
agiardullo 已提交
83
84
85
86
  };

  Code code() const { return code_; }

87
  enum SubCode : unsigned char {
agiardullo's avatar
agiardullo 已提交
88
89
90
91
    kNone = 0,
    kMutexTimeout = 1,
    kLockTimeout = 2,
    kLockLimit = 3,
92
    kNoSpace = 4,
Manuel Ung's avatar
Manuel Ung 已提交
93
    kDeadlock = 5,
94
    kStaleFile = 6,
95
    kMemoryLimit = 7,
96
    kSpaceLimit = 8,
97
    kPathNotFound = 9,
98
    KMergeOperandsInsufficientCapacity = 10,
99
    kManualCompactionPaused = 11,
100
    kOverwritten = 12,
101
    kTxnNotPrepared = 13,
agiardullo's avatar
agiardullo 已提交
102
103
104
105
106
    kMaxSubCode
  };

  SubCode subcode() const { return subcode_; }

107
108
109
110
111
112
113
114
115
116
117
118
  enum Severity : unsigned char {
    kNoError = 0,
    kSoftError = 1,
    kHardError = 2,
    kFatalError = 3,
    kUnrecoverableError = 4,
    kMaxSeverity
  };

  Status(const Status& s, Severity sev);
  Severity severity() const { return sev_; }

Adam Retter's avatar
Adam Retter 已提交
119
  // Returns a C style string indicating the message of the Status
120
121
  const char* getState() const { return state_; }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
122
123
124
  // Return a success status.
  static Status OK() { return Status(); }

125
126
127
128
129
130
  // Successful, though an existing something was overwritten
  // Note: using variants of OK status for program logic is discouraged,
  // but it can be useful for communicating statistical information without
  // changing public APIs.
  static Status OkOverwritten() { return Status(kOk, kOverwritten); }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
131
132
  // Return error status of an appropriate type.
  static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
133
    return Status(kNotFound, msg, msg2);
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
134
  }
135
  // Fast path for not found without malloc;
agiardullo's avatar
agiardullo 已提交
136
137
  static Status NotFound(SubCode msg = kNone) { return Status(kNotFound, msg); }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
138
139
140
  static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kCorruption, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
141
142
143
144
  static Status Corruption(SubCode msg = kNone) {
    return Status(kCorruption, msg);
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
145
146
147
  static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kNotSupported, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
148
149
150
151
  static Status NotSupported(SubCode msg = kNone) {
    return Status(kNotSupported, msg);
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
152
153
154
  static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kInvalidArgument, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
155
156
157
158
  static Status InvalidArgument(SubCode msg = kNone) {
    return Status(kInvalidArgument, msg);
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
159
160
161
  static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kIOError, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
162
163
164
165
166
167
168
169
170
  static Status IOError(SubCode msg = kNone) { return Status(kIOError, msg); }

  static Status MergeInProgress(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kMergeInProgress, msg, msg2);
  }
  static Status MergeInProgress(SubCode msg = kNone) {
    return Status(kMergeInProgress, msg);
  }

171
172
173
  static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kIncomplete, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
174
175
176
177
178
179
  static Status Incomplete(SubCode msg = kNone) {
    return Status(kIncomplete, msg);
  }

  static Status ShutdownInProgress(SubCode msg = kNone) {
    return Status(kShutdownInProgress, msg);
180
  }
Lei Jin's avatar
Lei Jin 已提交
181
182
183
184
  static Status ShutdownInProgress(const Slice& msg,
                                   const Slice& msg2 = Slice()) {
    return Status(kShutdownInProgress, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
185
  static Status Aborted(SubCode msg = kNone) { return Status(kAborted, msg); }
186
187
188
  static Status Aborted(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kAborted, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
189
190

  static Status Busy(SubCode msg = kNone) { return Status(kBusy, msg); }
agiardullo's avatar
agiardullo 已提交
191
192
193
  static Status Busy(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kBusy, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
194
195

  static Status TimedOut(SubCode msg = kNone) { return Status(kTimedOut, msg); }
agiardullo's avatar
agiardullo 已提交
196
197
198
  static Status TimedOut(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kTimedOut, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
199
200

  static Status Expired(SubCode msg = kNone) { return Status(kExpired, msg); }
agiardullo's avatar
agiardullo 已提交
201
202
203
  static Status Expired(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kExpired, msg, msg2);
  }
agiardullo's avatar
agiardullo 已提交
204
205

  static Status TryAgain(SubCode msg = kNone) { return Status(kTryAgain, msg); }
agiardullo's avatar
agiardullo 已提交
206
207
208
  static Status TryAgain(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kTryAgain, msg, msg2);
  }
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
209

210
211
212
213
214
215
216
217
  static Status CompactionTooLarge(SubCode msg = kNone) {
    return Status(kCompactionTooLarge, msg);
  }
  static Status CompactionTooLarge(const Slice& msg,
                                   const Slice& msg2 = Slice()) {
    return Status(kCompactionTooLarge, msg, msg2);
  }

218
219
220
221
222
223
224
225
226
  static Status ColumnFamilyDropped(SubCode msg = kNone) {
    return Status(kColumnFamilyDropped, msg);
  }

  static Status ColumnFamilyDropped(const Slice& msg,
                                    const Slice& msg2 = Slice()) {
    return Status(kColumnFamilyDropped, msg, msg2);
  }

227
228
229
230
231
  static Status NoSpace() { return Status(kIOError, kNoSpace); }
  static Status NoSpace(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kIOError, kNoSpace, msg, msg2);
  }

232
233
234
235
236
  static Status MemoryLimit() { return Status(kAborted, kMemoryLimit); }
  static Status MemoryLimit(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kAborted, kMemoryLimit, msg, msg2);
  }

237
238
239
240
241
  static Status SpaceLimit() { return Status(kIOError, kSpaceLimit); }
  static Status SpaceLimit(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kIOError, kSpaceLimit, msg, msg2);
  }

242
243
244
245
246
  static Status PathNotFound() { return Status(kIOError, kPathNotFound); }
  static Status PathNotFound(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kIOError, kPathNotFound, msg, msg2);
  }

247
248
249
250
251
252
253
  static Status TxnNotPrepared() {
    return Status(kInvalidArgument, kTxnNotPrepared);
  }
  static Status TxnNotPrepared(const Slice& msg, const Slice& msg2 = Slice()) {
    return Status(kInvalidArgument, kTxnNotPrepared, msg, msg2);
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
254
  // Returns true iff the status indicates success.
255
  bool ok() const { return code() == kOk; }
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
256

257
258
259
260
261
262
  // Returns true iff the status indicates success *with* something
  // overwritten
  bool IsOkOverwritten() const {
    return code() == kOk && subcode() == kOverwritten;
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
263
264
265
  // Returns true iff the status indicates a NotFound error.
  bool IsNotFound() const { return code() == kNotFound; }

266
267
268
  // Returns true iff the status indicates a Corruption error.
  bool IsCorruption() const { return code() == kCorruption; }

269
270
271
272
273
274
  // Returns true iff the status indicates a NotSupported error.
  bool IsNotSupported() const { return code() == kNotSupported; }

  // Returns true iff the status indicates an InvalidArgument error.
  bool IsInvalidArgument() const { return code() == kInvalidArgument; }

275
276
277
  // Returns true iff the status indicates an IOError.
  bool IsIOError() const { return code() == kIOError; }

278
279
280
  // Returns true iff the status indicates an MergeInProgress.
  bool IsMergeInProgress() const { return code() == kMergeInProgress; }

281
282
283
  // Returns true iff the status indicates Incomplete
  bool IsIncomplete() const { return code() == kIncomplete; }

Feng Zhu's avatar
Feng Zhu 已提交
284
  // Returns true iff the status indicates Shutdown In progress
Lei Jin's avatar
Lei Jin 已提交
285
286
  bool IsShutdownInProgress() const { return code() == kShutdownInProgress; }

287
288
  bool IsTimedOut() const { return code() == kTimedOut; }

289
290
  bool IsAborted() const { return code() == kAborted; }

Manuel Ung's avatar
Manuel Ung 已提交
291
292
293
294
  bool IsLockLimit() const {
    return code() == kAborted && subcode() == kLockLimit;
  }

agiardullo's avatar
agiardullo 已提交
295
296
297
298
  // Returns true iff the status indicates that a resource is Busy and
  // temporarily could not be acquired.
  bool IsBusy() const { return code() == kBusy; }

Manuel Ung's avatar
Manuel Ung 已提交
299
300
  bool IsDeadlock() const { return code() == kBusy && subcode() == kDeadlock; }

agiardullo's avatar
agiardullo 已提交
301
302
303
304
305
306
307
308
  // Returns true iff the status indicated that the operation has Expired.
  bool IsExpired() const { return code() == kExpired; }

  // Returns true iff the status indicates a TryAgain error.
  // This usually means that the operation failed, but may succeed if
  // re-attempted.
  bool IsTryAgain() const { return code() == kTryAgain; }

309
310
311
  // Returns true iff the status indicates the proposed compaction is too large
  bool IsCompactionTooLarge() const { return code() == kCompactionTooLarge; }

312
313
314
  // Returns true iff the status indicates Column Family Dropped
  bool IsColumnFamilyDropped() const { return code() == kColumnFamilyDropped; }

315
316
317
318
319
320
321
322
323
  // Returns true iff the status indicates a NoSpace error
  // This is caused by an I/O error returning the specific "out of space"
  // error condition. Stricto sensu, an NoSpace error is an I/O error
  // with a specific subcode, enabling users to take the appropriate action
  // if needed
  bool IsNoSpace() const {
    return (code() == kIOError) && (subcode() == kNoSpace);
  }

324
325
326
327
328
329
330
  // Returns true iff the status indicates a memory limit error.  There may be
  // cases where we limit the memory used in certain operations (eg. the size
  // of a write batch) in order to avoid out of memory exceptions.
  bool IsMemoryLimit() const {
    return (code() == kAborted) && (subcode() == kMemoryLimit);
  }

331
332
333
334
335
336
337
338
  // Returns true iff the status indicates a PathNotFound error
  // This is caused by an I/O error returning the specific "no such file or
  // directory" error condition. A PathNotFound error is an I/O error with
  // a specific subcode, enabling users to take appropriate action if necessary
  bool IsPathNotFound() const {
    return (code() == kIOError) && (subcode() == kPathNotFound);
  }

339
340
341
342
343
344
  // Returns true iff the status indicates manual compaction paused. This
  // is caused by a call to PauseManualCompaction
  bool IsManualCompactionPaused() const {
    return (code() == kIncomplete) && (subcode() == kManualCompactionPaused);
  }

345
346
347
348
349
  // Returns true iff the status indicates a TxnNotPrepared error.
  bool IsTxnNotPrepared() const {
    return (code() == kInvalidArgument) && (subcode() == kTxnNotPrepared);
  }

jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
350
351
352
353
  // Return a string representation of this status suitable for printing.
  // Returns the string "OK" for success.
  std::string ToString() const;

354
 protected:
355
356
357
358
359
360
  // A nullptr state_ (which is always the case for OK) means the message
  // is empty.
  // of the following form:
  //    state_[0..3] == length of message
  //    state_[4..]  == message
  Code code_;
agiardullo's avatar
agiardullo 已提交
361
  SubCode subcode_;
362
  Severity sev_;
363
364
  const char* state_;

agiardullo's avatar
agiardullo 已提交
365
  explicit Status(Code _code, SubCode _subcode = kNone)
366
      : code_(_code), subcode_(_subcode), sev_(kNoError), state_(nullptr) {}
agiardullo's avatar
agiardullo 已提交
367

368
369
370
371
  Status(Code _code, SubCode _subcode, const Slice& msg, const Slice& msg2);
  Status(Code _code, const Slice& msg, const Slice& msg2)
      : Status(_code, kNone, msg, msg2) {}

372
  static const char* CopyState(const char* s);
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
373
374
};

375
376
inline Status::Status(const Status& s)
    : code_(s.code_), subcode_(s.subcode_), sev_(s.sev_) {
377
378
379
  state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
}
inline Status::Status(const Status& s, Severity sev)
380
    : code_(s.code_), subcode_(s.subcode_), sev_(sev) {
Abhishek Kona's avatar
Abhishek Kona 已提交
381
  state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
382
}
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
383
inline Status& Status::operator=(const Status& s) {
384
  if (this != &s) {
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
385
386
    code_ = s.code_;
    subcode_ = s.subcode_;
387
    sev_ = s.sev_;
Tamir Duberstein's avatar
Tamir Duberstein 已提交
388
    delete[] state_;
Abhishek Kona's avatar
Abhishek Kona 已提交
389
    state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
390
  }
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
391
392
393
394
395
  return *this;
}

inline Status::Status(Status&& s)
#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
396
    noexcept
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
397
#endif
398
    : Status() {
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
399
400
401
  *this = std::move(s);
}

402
inline Status& Status::operator=(Status&& s)
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
403
#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
404
    noexcept
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
405
406
#endif
{
407
  if (this != &s) {
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
408
409
410
411
    code_ = std::move(s.code_);
    s.code_ = kOk;
    subcode_ = std::move(s.subcode_);
    s.subcode_ = kNone;
412
413
    sev_ = std::move(s.sev_);
    s.sev_ = kNoError;
Tamir Duberstein's avatar
Tamir Duberstein 已提交
414
    delete[] state_;
Dmitri Smirnov's avatar
Dmitri Smirnov 已提交
415
416
417
418
    state_ = nullptr;
    std::swap(state_, s.state_);
  }
  return *this;
jorlow@chromium.org's avatar
jorlow@chromium.org 已提交
419
420
}

agiardullo's avatar
agiardullo 已提交
421
422
423
424
425
426
427
428
inline bool Status::operator==(const Status& rhs) const {
  return (code_ == rhs.code_);
}

inline bool Status::operator!=(const Status& rhs) const {
  return !(*this == rhs);
}

429
}  // namespace ROCKSDB_NAMESPACE