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