]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/utilities/env_mirror.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / utilities / env_mirror.cc
CommitLineData
f67539c2 1// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
7c673cae 2// Copyright (c) 2015, Red Hat, Inc. All rights reserved.
11fdf7f2
TL
3// This source code is licensed under both the GPLv2 (found in the
4// COPYING file in the root directory) and Apache 2.0 License
5// (found in the LICENSE.Apache file in the root directory).
7c673cae
FG
6// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7// Use of this source code is governed by a BSD-style license that can be
8// found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10#ifndef ROCKSDB_LITE
11
12#include "rocksdb/utilities/env_mirror.h"
13
f67539c2 14namespace ROCKSDB_NAMESPACE {
7c673cae 15
11fdf7f2 16// An implementation of Env that mirrors all work over two backend
7c673cae
FG
17// Env's. This is useful for debugging purposes.
18class SequentialFileMirror : public SequentialFile {
19 public:
494da23a 20 std::unique_ptr<SequentialFile> a_, b_;
7c673cae
FG
21 std::string fname;
22 explicit SequentialFileMirror(std::string f) : fname(f) {}
23
11fdf7f2 24 Status Read(size_t n, Slice* result, char* scratch) override {
7c673cae
FG
25 Slice aslice;
26 Status as = a_->Read(n, &aslice, scratch);
27 if (as == Status::OK()) {
28 char* bscratch = new char[n];
29 Slice bslice;
1e59de90 30#ifndef NDEBUG
7c673cae 31 size_t off = 0;
1e59de90 32#endif
7c673cae
FG
33 size_t left = aslice.size();
34 while (left) {
35 Status bs = b_->Read(left, &bslice, bscratch);
1e59de90 36#ifndef NDEBUG
7c673cae
FG
37 assert(as == bs);
38 assert(memcmp(bscratch, scratch + off, bslice.size()) == 0);
39 off += bslice.size();
1e59de90 40#endif
7c673cae
FG
41 left -= bslice.size();
42 }
43 delete[] bscratch;
44 *result = aslice;
45 } else {
46 Status bs = b_->Read(n, result, scratch);
47 assert(as == bs);
48 }
49 return as;
50 }
51
11fdf7f2 52 Status Skip(uint64_t n) override {
7c673cae
FG
53 Status as = a_->Skip(n);
54 Status bs = b_->Skip(n);
55 assert(as == bs);
56 return as;
57 }
11fdf7f2 58 Status InvalidateCache(size_t offset, size_t length) override {
7c673cae
FG
59 Status as = a_->InvalidateCache(offset, length);
60 Status bs = b_->InvalidateCache(offset, length);
61 assert(as == bs);
62 return as;
63 };
64};
65
66class RandomAccessFileMirror : public RandomAccessFile {
67 public:
494da23a 68 std::unique_ptr<RandomAccessFile> a_, b_;
7c673cae
FG
69 std::string fname;
70 explicit RandomAccessFileMirror(std::string f) : fname(f) {}
71
11fdf7f2
TL
72 Status Read(uint64_t offset, size_t n, Slice* result,
73 char* scratch) const override {
7c673cae
FG
74 Status as = a_->Read(offset, n, result, scratch);
75 if (as == Status::OK()) {
76 char* bscratch = new char[n];
77 Slice bslice;
78 size_t off = 0;
79 size_t left = result->size();
80 while (left) {
81 Status bs = b_->Read(offset + off, left, &bslice, bscratch);
82 assert(as == bs);
83 assert(memcmp(bscratch, scratch + off, bslice.size()) == 0);
84 off += bslice.size();
85 left -= bslice.size();
86 }
87 delete[] bscratch;
88 } else {
89 Status bs = b_->Read(offset, n, result, scratch);
90 assert(as == bs);
91 }
92 return as;
93 }
94
11fdf7f2 95 size_t GetUniqueId(char* id, size_t max_size) const override {
7c673cae
FG
96 // NOTE: not verified
97 return a_->GetUniqueId(id, max_size);
98 }
99};
100
101class WritableFileMirror : public WritableFile {
102 public:
494da23a 103 std::unique_ptr<WritableFile> a_, b_;
7c673cae 104 std::string fname;
f67539c2
TL
105 explicit WritableFileMirror(std::string f, const EnvOptions& options)
106 : WritableFile(options), fname(f) {}
7c673cae
FG
107
108 Status Append(const Slice& data) override {
109 Status as = a_->Append(data);
110 Status bs = b_->Append(data);
111 assert(as == bs);
112 return as;
113 }
1e59de90
TL
114 Status Append(const Slice& data,
115 const DataVerificationInfo& /* verification_info */) override {
116 return Append(data);
117 }
7c673cae
FG
118 Status PositionedAppend(const Slice& data, uint64_t offset) override {
119 Status as = a_->PositionedAppend(data, offset);
120 Status bs = b_->PositionedAppend(data, offset);
121 assert(as == bs);
122 return as;
123 }
1e59de90
TL
124 Status PositionedAppend(
125 const Slice& data, uint64_t offset,
126 const DataVerificationInfo& /* verification_info */) override {
127 return PositionedAppend(data, offset);
128 }
7c673cae
FG
129 Status Truncate(uint64_t size) override {
130 Status as = a_->Truncate(size);
131 Status bs = b_->Truncate(size);
132 assert(as == bs);
133 return as;
134 }
135 Status Close() override {
136 Status as = a_->Close();
137 Status bs = b_->Close();
138 assert(as == bs);
139 return as;
140 }
141 Status Flush() override {
142 Status as = a_->Flush();
143 Status bs = b_->Flush();
144 assert(as == bs);
145 return as;
146 }
147 Status Sync() override {
148 Status as = a_->Sync();
149 Status bs = b_->Sync();
150 assert(as == bs);
151 return as;
152 }
153 Status Fsync() override {
154 Status as = a_->Fsync();
155 Status bs = b_->Fsync();
156 assert(as == bs);
157 return as;
158 }
159 bool IsSyncThreadSafe() const override {
160 bool as = a_->IsSyncThreadSafe();
161 assert(as == b_->IsSyncThreadSafe());
162 return as;
163 }
164 void SetIOPriority(Env::IOPriority pri) override {
165 a_->SetIOPriority(pri);
166 b_->SetIOPriority(pri);
167 }
168 Env::IOPriority GetIOPriority() override {
169 // NOTE: we don't verify this one
170 return a_->GetIOPriority();
171 }
172 uint64_t GetFileSize() override {
173 uint64_t as = a_->GetFileSize();
174 assert(as == b_->GetFileSize());
175 return as;
176 }
177 void GetPreallocationStatus(size_t* block_size,
178 size_t* last_allocated_block) override {
179 // NOTE: we don't verify this one
180 return a_->GetPreallocationStatus(block_size, last_allocated_block);
181 }
182 size_t GetUniqueId(char* id, size_t max_size) const override {
183 // NOTE: we don't verify this one
184 return a_->GetUniqueId(id, max_size);
185 }
186 Status InvalidateCache(size_t offset, size_t length) override {
187 Status as = a_->InvalidateCache(offset, length);
188 Status bs = b_->InvalidateCache(offset, length);
189 assert(as == bs);
190 return as;
191 }
192
193 protected:
194 Status Allocate(uint64_t offset, uint64_t length) override {
195 Status as = a_->Allocate(offset, length);
196 Status bs = b_->Allocate(offset, length);
197 assert(as == bs);
198 return as;
199 }
200 Status RangeSync(uint64_t offset, uint64_t nbytes) override {
201 Status as = a_->RangeSync(offset, nbytes);
202 Status bs = b_->RangeSync(offset, nbytes);
203 assert(as == bs);
204 return as;
205 }
206};
207
208Status EnvMirror::NewSequentialFile(const std::string& f,
494da23a 209 std::unique_ptr<SequentialFile>* r,
7c673cae
FG
210 const EnvOptions& options) {
211 if (f.find("/proc/") == 0) {
212 return a_->NewSequentialFile(f, r, options);
213 }
214 SequentialFileMirror* mf = new SequentialFileMirror(f);
215 Status as = a_->NewSequentialFile(f, &mf->a_, options);
216 Status bs = b_->NewSequentialFile(f, &mf->b_, options);
217 assert(as == bs);
218 if (as.ok())
219 r->reset(mf);
220 else
221 delete mf;
222 return as;
223}
224
225Status EnvMirror::NewRandomAccessFile(const std::string& f,
494da23a 226 std::unique_ptr<RandomAccessFile>* r,
7c673cae
FG
227 const EnvOptions& options) {
228 if (f.find("/proc/") == 0) {
229 return a_->NewRandomAccessFile(f, r, options);
230 }
231 RandomAccessFileMirror* mf = new RandomAccessFileMirror(f);
232 Status as = a_->NewRandomAccessFile(f, &mf->a_, options);
233 Status bs = b_->NewRandomAccessFile(f, &mf->b_, options);
234 assert(as == bs);
235 if (as.ok())
236 r->reset(mf);
237 else
238 delete mf;
239 return as;
240}
241
242Status EnvMirror::NewWritableFile(const std::string& f,
494da23a 243 std::unique_ptr<WritableFile>* r,
7c673cae
FG
244 const EnvOptions& options) {
245 if (f.find("/proc/") == 0) return a_->NewWritableFile(f, r, options);
f67539c2 246 WritableFileMirror* mf = new WritableFileMirror(f, options);
7c673cae
FG
247 Status as = a_->NewWritableFile(f, &mf->a_, options);
248 Status bs = b_->NewWritableFile(f, &mf->b_, options);
249 assert(as == bs);
250 if (as.ok())
251 r->reset(mf);
252 else
253 delete mf;
254 return as;
255}
256
257Status EnvMirror::ReuseWritableFile(const std::string& fname,
258 const std::string& old_fname,
494da23a 259 std::unique_ptr<WritableFile>* r,
7c673cae
FG
260 const EnvOptions& options) {
261 if (fname.find("/proc/") == 0)
262 return a_->ReuseWritableFile(fname, old_fname, r, options);
f67539c2 263 WritableFileMirror* mf = new WritableFileMirror(fname, options);
7c673cae
FG
264 Status as = a_->ReuseWritableFile(fname, old_fname, &mf->a_, options);
265 Status bs = b_->ReuseWritableFile(fname, old_fname, &mf->b_, options);
266 assert(as == bs);
267 if (as.ok())
268 r->reset(mf);
269 else
270 delete mf;
271 return as;
272}
273
f67539c2 274} // namespace ROCKSDB_NAMESPACE
7c673cae 275#endif