]>
Commit | Line | Data |
---|---|---|
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 | ||
24 | namespace ROCKSDB_NAMESPACE { | |
25 | ||
26 | class 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 | ||
155 | inline 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 | ||
177 | inline 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 | } | |
186 | inline 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 | ||
205 | inline 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 | ||
213 | inline 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 | ||
238 | inline 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 | ||
246 | inline 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 |
254 | inline 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 |