]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/include/rocksdb/io_status.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / include / rocksdb / io_status.h
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
129 // Return a string representation of this status suitable for printing.
130 // Returns the string "OK" for success.
131 // std::string ToString() const;
132
133 private:
134 friend IOStatus status_to_io_status(Status&&);
135 bool retryable_;
136 bool data_loss_;
137 IOErrorScope scope_;
138
139 explicit IOStatus(Code _code, SubCode _subcode = kNone)
140 : Status(_code, _subcode),
141 retryable_(false),
142 data_loss_(false),
143 scope_(kIOErrorScopeFileSystem) {}
144
145 IOStatus(Code _code, SubCode _subcode, const Slice& msg, const Slice& msg2);
146 IOStatus(Code _code, const Slice& msg, const Slice& msg2)
147 : IOStatus(_code, kNone, msg, msg2) {}
148 };
149
150 inline IOStatus::IOStatus(Code _code, SubCode _subcode, const Slice& msg,
151 const Slice& msg2)
152 : Status(_code, _subcode),
153 retryable_(false),
154 data_loss_(false),
155 scope_(kIOErrorScopeFileSystem) {
156 assert(code_ != kOk);
157 assert(subcode_ != kMaxSubCode);
158 const size_t len1 = msg.size();
159 const size_t len2 = msg2.size();
160 const size_t size = len1 + (len2 ? (2 + len2) : 0);
161 char* const result = new char[size + 1]; // +1 for null terminator
162 memcpy(result, msg.data(), len1);
163 if (len2) {
164 result[len1] = ':';
165 result[len1 + 1] = ' ';
166 memcpy(result + len1 + 2, msg2.data(), len2);
167 }
168 result[size] = '\0'; // null terminator for C style string
169 state_ = result;
170 }
171
172 inline IOStatus::IOStatus(const IOStatus& s) : Status(s.code_, s.subcode_) {
173 retryable_ = s.retryable_;
174 data_loss_ = s.data_loss_;
175 scope_ = s.scope_;
176 state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
177 }
178 inline IOStatus& IOStatus::operator=(const IOStatus& s) {
179 // The following condition catches both aliasing (when this == &s),
180 // and the common case where both s and *this are ok.
181 if (this != &s) {
182 code_ = s.code_;
183 subcode_ = s.subcode_;
184 retryable_ = s.retryable_;
185 data_loss_ = s.data_loss_;
186 scope_ = s.scope_;
187 delete[] state_;
188 state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_);
189 }
190 return *this;
191 }
192
193 inline IOStatus::IOStatus(IOStatus&& s)
194 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
195 noexcept
196 #endif
197 : IOStatus() {
198 *this = std::move(s);
199 }
200
201 inline IOStatus& IOStatus::operator=(IOStatus&& s)
202 #if !(defined _MSC_VER) || ((defined _MSC_VER) && (_MSC_VER >= 1900))
203 noexcept
204 #endif
205 {
206 if (this != &s) {
207 code_ = std::move(s.code_);
208 s.code_ = kOk;
209 subcode_ = std::move(s.subcode_);
210 s.subcode_ = kNone;
211 retryable_ = s.retryable_;
212 retryable_ = false;
213 data_loss_ = s.data_loss_;
214 data_loss_ = false;
215 scope_ = s.scope_;
216 scope_ = kIOErrorScopeFileSystem;
217 delete[] state_;
218 state_ = nullptr;
219 std::swap(state_, s.state_);
220 }
221 return *this;
222 }
223
224 inline bool IOStatus::operator==(const IOStatus& rhs) const {
225 return (code_ == rhs.code_);
226 }
227
228 inline bool IOStatus::operator!=(const IOStatus& rhs) const {
229 return !(*this == rhs);
230 }
231
232 } // namespace ROCKSDB_NAMESPACE