]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/include/rocksdb/io_status.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / include / rocksdb / io_status.h
CommitLineData
f67539c2
TL
1// Copyright (c) 2019-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//
6// An IOStatus encapsulates the result of an operation. It may indicate
7// success, or it may indicate an error with an associated error message.
8//
9// Multiple threads can invoke const methods on an IOStatus without
10// external synchronization, but if any of the threads may call a
11// non-const method, all threads accessing the same IOStatus must use
12// external synchronization.
13
14#pragma once
15
16#include <string>
17#include "rocksdb/slice.h"
18#ifdef OS_WIN
19#include <string.h>
20#endif
21#include <cstring>
22#include "status.h"
23
24namespace ROCKSDB_NAMESPACE {
25
26class IOStatus : public Status {
27 public:
28 using Code = Status::Code;
29 using SubCode = Status::SubCode;
30
31 enum IOErrorScope {
32 kIOErrorScopeFileSystem,
33 kIOErrorScopeFile,
34 kIOErrorScopeRange,
35 kIOErrorScopeMax,
36 };
37
38 // Create a success status.
39 IOStatus() : IOStatus(kOk, kNone) {}
40 ~IOStatus() {}
41
42 // Copy the specified status.
43 IOStatus(const IOStatus& s);
44 IOStatus& operator=(const IOStatus& s);
45 IOStatus(IOStatus&& s)
46#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
47 noexcept
48#endif
49 ;
50 IOStatus& operator=(IOStatus&& s)
51#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
52 noexcept
53#endif
54 ;
55 bool operator==(const IOStatus& rhs) const;
56 bool operator!=(const IOStatus& rhs) const;
57
58 void SetRetryable(bool retryable) { retryable_ = retryable; }
59 void SetDataLoss(bool data_loss) { data_loss_ = data_loss; }
60 void SetScope(IOErrorScope scope) { scope_ = scope; }
61
62 bool GetRetryable() const { return retryable_; }
63 bool GetDataLoss() const { return data_loss_; }
64 IOErrorScope GetScope() const { return scope_; }
65
66 // Return a success status.
67 static IOStatus OK() { return IOStatus(); }
68
69 static IOStatus NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
70 return IOStatus(kNotSupported, msg, msg2);
71 }
72 static IOStatus NotSupported(SubCode msg = kNone) {
73 return IOStatus(kNotSupported, msg);
74 }
75
76 // Return error status of an appropriate type.
77 static IOStatus NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
78 return IOStatus(kNotFound, msg, msg2);
79 }
80 // Fast path for not found without malloc;
81 static IOStatus NotFound(SubCode msg = kNone) {
82 return IOStatus(kNotFound, msg);
83 }
84
85 static IOStatus Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
86 return IOStatus(kCorruption, msg, msg2);
87 }
88 static IOStatus Corruption(SubCode msg = kNone) {
89 return IOStatus(kCorruption, msg);
90 }
91
92 static IOStatus InvalidArgument(const Slice& msg,
93 const Slice& msg2 = Slice()) {
94 return IOStatus(kInvalidArgument, msg, msg2);
95 }
96 static IOStatus InvalidArgument(SubCode msg = kNone) {
97 return IOStatus(kInvalidArgument, msg);
98 }
99
100 static IOStatus IOError(const Slice& msg, const Slice& msg2 = Slice()) {
101 return IOStatus(kIOError, msg, msg2);
102 }
103 static IOStatus IOError(SubCode msg = kNone) {
104 return IOStatus(kIOError, msg);
105 }
106
107 static IOStatus Busy(SubCode msg = kNone) { return IOStatus(kBusy, msg); }
108 static IOStatus Busy(const Slice& msg, const Slice& msg2 = Slice()) {
109 return IOStatus(kBusy, msg, msg2);
110 }
111
112 static IOStatus TimedOut(SubCode msg = kNone) {
113 return IOStatus(kTimedOut, msg);
114 }
115 static IOStatus TimedOut(const Slice& msg, const Slice& msg2 = Slice()) {
116 return IOStatus(kTimedOut, msg, msg2);
117 }
118
119 static IOStatus NoSpace() { return IOStatus(kIOError, kNoSpace); }
120 static IOStatus NoSpace(const Slice& msg, const Slice& msg2 = Slice()) {
121 return IOStatus(kIOError, kNoSpace, msg, msg2);
122 }
123
124 static IOStatus PathNotFound() { return IOStatus(kIOError, kPathNotFound); }
125 static IOStatus PathNotFound(const Slice& msg, const Slice& msg2 = Slice()) {
126 return IOStatus(kIOError, kPathNotFound, msg, msg2);
127 }
128
20effc67
TL
129 static IOStatus IOFenced() { return IOStatus(kIOError, kIOFenced); }
130 static IOStatus IOFenced(const Slice& msg, const Slice& msg2 = Slice()) {
131 return IOStatus(kIOError, kIOFenced, msg, msg2);
132 }
133
f67539c2
TL
134 // Return a string representation of this status suitable for printing.
135 // Returns the string "OK" for success.
136 // std::string ToString() const;
137
138 private:
139 friend IOStatus status_to_io_status(Status&&);
140 bool retryable_;
141 bool data_loss_;
142 IOErrorScope scope_;
143
144 explicit IOStatus(Code _code, SubCode _subcode = kNone)
145 : Status(_code, _subcode),
146 retryable_(false),
147 data_loss_(false),
148 scope_(kIOErrorScopeFileSystem) {}
149
150 IOStatus(Code _code, SubCode _subcode, const Slice& msg, const Slice& msg2);
151 IOStatus(Code _code, const Slice& msg, const Slice& msg2)
152 : IOStatus(_code, kNone, msg, msg2) {}
153};
154
155inline IOStatus::IOStatus(Code _code, SubCode _subcode, const Slice& msg,
156 const Slice& msg2)
157 : Status(_code, _subcode),
158 retryable_(false),
159 data_loss_(false),
160 scope_(kIOErrorScopeFileSystem) {
161 assert(code_ != kOk);
162 assert(subcode_ != kMaxSubCode);
163 const size_t len1 = msg.size();
164 const size_t len2 = msg2.size();
165 const size_t size = len1 + (len2 ? (2 + len2) : 0);
166 char* const result = new char[size + 1]; // +1 for null terminator
167 memcpy(result, msg.data(), len1);
168 if (len2) {
169 result[len1] = ':';
170 result[len1 + 1] = ' ';
171 memcpy(result + len1 + 2, msg2.data(), len2);
172 }
173 result[size] = '\0'; // null terminator for C style string
174 state_ = result;
175}
176
177inline IOStatus::IOStatus(const IOStatus& s) : Status(s.code_, s.subcode_) {
20effc67
TL
178#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
179 s.checked_ = true;
180#endif // ROCKSDB_ASSERT_STATUS_CHECKED
f67539c2
TL
181 retryable_ = s.retryable_;
182 data_loss_ = s.data_loss_;
183 scope_ = s.scope_;
184 state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
185}
186inline IOStatus& IOStatus::operator=(const IOStatus& s) {
187 // The following condition catches both aliasing (when this == &s),
188 // and the common case where both s and *this are ok.
189 if (this != &s) {
20effc67
TL
190#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
191 s.checked_ = true;
192 checked_ = false;
193#endif // ROCKSDB_ASSERT_STATUS_CHECKED
f67539c2
TL
194 code_ = s.code_;
195 subcode_ = s.subcode_;
196 retryable_ = s.retryable_;
197 data_loss_ = s.data_loss_;
198 scope_ = s.scope_;
199 delete[] state_;
200 state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
201 }
202 return *this;
203}
204
205inline IOStatus::IOStatus(IOStatus&& s)
206#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
207 noexcept
208#endif
209 : IOStatus() {
210 *this = std::move(s);
211}
212
213inline IOStatus& IOStatus::operator=(IOStatus&& s)
214#if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
215 noexcept
216#endif
217{
218 if (this != &s) {
20effc67
TL
219#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
220 s.checked_ = true;
221 checked_ = false;
222#endif // ROCKSDB_ASSERT_STATUS_CHECKED
f67539c2
TL
223 code_ = std::move(s.code_);
224 s.code_ = kOk;
225 subcode_ = std::move(s.subcode_);
226 s.subcode_ = kNone;
227 retryable_ = s.retryable_;
f67539c2 228 data_loss_ = s.data_loss_;
f67539c2 229 scope_ = s.scope_;
20effc67 230 s.scope_ = kIOErrorScopeFileSystem;
f67539c2
TL
231 delete[] state_;
232 state_ = nullptr;
233 std::swap(state_, s.state_);
234 }
235 return *this;
236}
237
238inline bool IOStatus::operator==(const IOStatus& rhs) const {
20effc67
TL
239#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
240 checked_ = true;
241 rhs.checked_ = true;
242#endif // ROCKSDB_ASSERT_STATUS_CHECKED
f67539c2
TL
243 return (code_ == rhs.code_);
244}
245
246inline bool IOStatus::operator!=(const IOStatus& rhs) const {
20effc67
TL
247#ifdef ROCKSDB_ASSERT_STATUS_CHECKED
248 checked_ = true;
249 rhs.checked_ = true;
250#endif // ROCKSDB_ASSERT_STATUS_CHECKED
f67539c2
TL
251 return !(*this == rhs);
252}
253
20effc67
TL
254inline IOStatus status_to_io_status(Status&& status) {
255 if (status.ok()) {
256 // Fast path
257 return IOStatus::OK();
258 } else {
259 const char* state = status.getState();
260 if (state) {
261 return IOStatus(status.code(), status.subcode(),
262 Slice(state, strlen(status.getState()) + 1), Slice());
263 } else {
264 return IOStatus(status.code(), status.subcode());
265 }
266 }
267}
268
f67539c2 269} // namespace ROCKSDB_NAMESPACE