]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/utilities/env_mirror.cc
1 // Copyright (c) 2015, Red Hat, 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 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
11 #include "rocksdb/utilities/env_mirror.h"
15 // An implementation of Env that mirrors all work over two backend
16 // Env's. This is useful for debugging purposes.
17 class SequentialFileMirror
: public SequentialFile
{
19 std::unique_ptr
<SequentialFile
> a_
, b_
;
21 explicit SequentialFileMirror(std::string f
) : fname(f
) {}
23 Status
Read(size_t n
, Slice
* result
, char* scratch
) override
{
25 Status as
= a_
->Read(n
, &aslice
, scratch
);
26 if (as
== Status::OK()) {
27 char* bscratch
= new char[n
];
30 size_t left
= aslice
.size();
32 Status bs
= b_
->Read(left
, &bslice
, bscratch
);
34 assert(memcmp(bscratch
, scratch
+ off
, bslice
.size()) == 0);
36 left
-= bslice
.size();
41 Status bs
= b_
->Read(n
, result
, scratch
);
47 Status
Skip(uint64_t n
) override
{
48 Status as
= a_
->Skip(n
);
49 Status bs
= b_
->Skip(n
);
53 Status
InvalidateCache(size_t offset
, size_t length
) override
{
54 Status as
= a_
->InvalidateCache(offset
, length
);
55 Status bs
= b_
->InvalidateCache(offset
, length
);
61 class RandomAccessFileMirror
: public RandomAccessFile
{
63 std::unique_ptr
<RandomAccessFile
> a_
, b_
;
65 explicit RandomAccessFileMirror(std::string f
) : fname(f
) {}
67 Status
Read(uint64_t offset
, size_t n
, Slice
* result
,
68 char* scratch
) const override
{
69 Status as
= a_
->Read(offset
, n
, result
, scratch
);
70 if (as
== Status::OK()) {
71 char* bscratch
= new char[n
];
74 size_t left
= result
->size();
76 Status bs
= b_
->Read(offset
+ off
, left
, &bslice
, bscratch
);
78 assert(memcmp(bscratch
, scratch
+ off
, bslice
.size()) == 0);
80 left
-= bslice
.size();
84 Status bs
= b_
->Read(offset
, n
, result
, scratch
);
90 size_t GetUniqueId(char* id
, size_t max_size
) const override
{
92 return a_
->GetUniqueId(id
, max_size
);
96 class WritableFileMirror
: public WritableFile
{
98 std::unique_ptr
<WritableFile
> a_
, b_
;
100 explicit WritableFileMirror(std::string f
) : fname(f
) {}
102 Status
Append(const Slice
& data
) override
{
103 Status as
= a_
->Append(data
);
104 Status bs
= b_
->Append(data
);
108 Status
PositionedAppend(const Slice
& data
, uint64_t offset
) override
{
109 Status as
= a_
->PositionedAppend(data
, offset
);
110 Status bs
= b_
->PositionedAppend(data
, offset
);
114 Status
Truncate(uint64_t size
) override
{
115 Status as
= a_
->Truncate(size
);
116 Status bs
= b_
->Truncate(size
);
120 Status
Close() override
{
121 Status as
= a_
->Close();
122 Status bs
= b_
->Close();
126 Status
Flush() override
{
127 Status as
= a_
->Flush();
128 Status bs
= b_
->Flush();
132 Status
Sync() override
{
133 Status as
= a_
->Sync();
134 Status bs
= b_
->Sync();
138 Status
Fsync() override
{
139 Status as
= a_
->Fsync();
140 Status bs
= b_
->Fsync();
144 bool IsSyncThreadSafe() const override
{
145 bool as
= a_
->IsSyncThreadSafe();
146 assert(as
== b_
->IsSyncThreadSafe());
149 void SetIOPriority(Env::IOPriority pri
) override
{
150 a_
->SetIOPriority(pri
);
151 b_
->SetIOPriority(pri
);
153 Env::IOPriority
GetIOPriority() override
{
154 // NOTE: we don't verify this one
155 return a_
->GetIOPriority();
157 uint64_t GetFileSize() override
{
158 uint64_t as
= a_
->GetFileSize();
159 assert(as
== b_
->GetFileSize());
162 void GetPreallocationStatus(size_t* block_size
,
163 size_t* last_allocated_block
) override
{
164 // NOTE: we don't verify this one
165 return a_
->GetPreallocationStatus(block_size
, last_allocated_block
);
167 size_t GetUniqueId(char* id
, size_t max_size
) const override
{
168 // NOTE: we don't verify this one
169 return a_
->GetUniqueId(id
, max_size
);
171 Status
InvalidateCache(size_t offset
, size_t length
) override
{
172 Status as
= a_
->InvalidateCache(offset
, length
);
173 Status bs
= b_
->InvalidateCache(offset
, length
);
179 Status
Allocate(uint64_t offset
, uint64_t length
) override
{
180 Status as
= a_
->Allocate(offset
, length
);
181 Status bs
= b_
->Allocate(offset
, length
);
185 Status
RangeSync(uint64_t offset
, uint64_t nbytes
) override
{
186 Status as
= a_
->RangeSync(offset
, nbytes
);
187 Status bs
= b_
->RangeSync(offset
, nbytes
);
193 Status
EnvMirror::NewSequentialFile(const std::string
& f
,
194 std::unique_ptr
<SequentialFile
>* r
,
195 const EnvOptions
& options
) {
196 if (f
.find("/proc/") == 0) {
197 return a_
->NewSequentialFile(f
, r
, options
);
199 SequentialFileMirror
* mf
= new SequentialFileMirror(f
);
200 Status as
= a_
->NewSequentialFile(f
, &mf
->a_
, options
);
201 Status bs
= b_
->NewSequentialFile(f
, &mf
->b_
, options
);
210 Status
EnvMirror::NewRandomAccessFile(const std::string
& f
,
211 std::unique_ptr
<RandomAccessFile
>* r
,
212 const EnvOptions
& options
) {
213 if (f
.find("/proc/") == 0) {
214 return a_
->NewRandomAccessFile(f
, r
, options
);
216 RandomAccessFileMirror
* mf
= new RandomAccessFileMirror(f
);
217 Status as
= a_
->NewRandomAccessFile(f
, &mf
->a_
, options
);
218 Status bs
= b_
->NewRandomAccessFile(f
, &mf
->b_
, options
);
227 Status
EnvMirror::NewWritableFile(const std::string
& f
,
228 std::unique_ptr
<WritableFile
>* r
,
229 const EnvOptions
& options
) {
230 if (f
.find("/proc/") == 0) return a_
->NewWritableFile(f
, r
, options
);
231 WritableFileMirror
* mf
= new WritableFileMirror(f
);
232 Status as
= a_
->NewWritableFile(f
, &mf
->a_
, options
);
233 Status bs
= b_
->NewWritableFile(f
, &mf
->b_
, options
);
242 Status
EnvMirror::ReuseWritableFile(const std::string
& fname
,
243 const std::string
& old_fname
,
244 std::unique_ptr
<WritableFile
>* r
,
245 const EnvOptions
& options
) {
246 if (fname
.find("/proc/") == 0)
247 return a_
->ReuseWritableFile(fname
, old_fname
, r
, options
);
248 WritableFileMirror
* mf
= new WritableFileMirror(fname
);
249 Status as
= a_
->ReuseWritableFile(fname
, old_fname
, &mf
->a_
, options
);
250 Status bs
= b_
->ReuseWritableFile(fname
, old_fname
, &mf
->b_
, options
);
259 } // namespace rocksdb