YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/utilities/env_mirror.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2015, Red Hat, Inc.  All rights reserved.
2
// This source code is licensed under the BSD-style license found in the
3
// LICENSE file in the root directory of this source tree. An additional grant
4
// of patent rights can be found in the PATENTS file in the same 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.
8
//
9
// The following only applies to changes made to this file as part of YugaByte development.
10
//
11
// Portions Copyright (c) YugaByte, Inc.
12
//
13
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
14
// in compliance with the License.  You may obtain a copy of the License at
15
//
16
// http://www.apache.org/licenses/LICENSE-2.0
17
//
18
// Unless required by applicable law or agreed to in writing, software distributed under the License
19
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
20
// or implied.  See the License for the specific language governing permissions and limitations
21
// under the License.
22
//
23
24
#ifndef ROCKSDB_LITE
25
26
#include <glog/logging.h>
27
28
#include "yb/rocksdb/utilities/env_mirror.h"
29
#include "yb/util/result.h"
30
#include "yb/util/status_format.h"
31
32
namespace rocksdb {
33
34
// An implementaiton of Env that mirrors all work over two backend
35
// Env's.  This is useful for debugging purposes.
36
class SequentialFileMirror : public SequentialFile {
37
 public:
38
  unique_ptr<SequentialFile> a_, b_;
39
  std::string fname;
40
0
  explicit SequentialFileMirror(std::string f) : fname(std::move(f)) {}
41
42
0
  Status Read(size_t n, Slice* result, uint8_t* scratch) override {
43
0
    Slice aslice;
44
0
    Status as = a_->Read(n, &aslice, scratch);
45
0
    if (as.ok()) {
46
0
      std::unique_ptr<uint8_t[]> bscratch(new uint8_t[n]);
47
0
      Slice bslice;
48
0
      size_t off = 0;
49
0
      size_t left = aslice.size();
50
0
      while (left) {
51
0
        Status bs = b_->Read(left, &bslice, bscratch.get());
52
0
        assert(as.code() == bs.code());
53
0
        assert(memcmp(bscratch.get(), scratch + off, bslice.size()) == 0);
54
0
        off += bslice.size();
55
0
        left -= bslice.size();
56
0
      }
57
0
      *result = aslice;
58
0
    } else {
59
0
      Status bs = b_->Read(n, result, scratch);
60
0
      assert(as.code() == bs.code());
61
0
    }
62
0
    return as;
63
0
  }
64
65
0
  Status Skip(uint64_t n) override {
66
0
    Status as = a_->Skip(n);
67
0
    Status bs = b_->Skip(n);
68
0
    assert(as.code() == bs.code());
69
0
    return as;
70
0
  }
71
72
0
  Status InvalidateCache(size_t offset, size_t length) override {
73
0
    Status as = a_->InvalidateCache(offset, length);
74
0
    Status bs = b_->InvalidateCache(offset, length);
75
0
    assert(as.code() == bs.code());
76
0
    return as;
77
0
  }
78
79
0
  const std::string& filename() const override { return fname; }
80
};
81
82
class RandomAccessFileMirror : public RandomAccessFile {
83
 public:
84
  unique_ptr<RandomAccessFile> a_, b_;
85
  std::string fname;
86
0
  explicit RandomAccessFileMirror(std::string f) : fname(std::move(f)) {}
87
88
0
  Status Read(uint64_t offset, size_t n, Slice* result, uint8_t* scratch) const override {
89
0
    Status as = a_->Read(offset, n, result, scratch);
90
0
    if (as.ok()) {
91
0
      uint8_t* bscratch = new uint8_t[n];
92
0
      Slice bslice;
93
0
      size_t off = 0;
94
0
      size_t left = result->size();
95
0
      while (left) {
96
0
        Status bs = b_->Read(offset + off, left, &bslice, bscratch);
97
0
        assert(as.code() == bs.code());
98
0
        assert(memcmp(bscratch, scratch + off, bslice.size()) == 0);
99
0
        off += bslice.size();
100
0
        left -= bslice.size();
101
0
      }
102
0
      delete[] bscratch;
103
0
    } else {
104
0
      Status bs = b_->Read(offset, n, result, scratch);
105
0
      assert(as.code() == bs.code());
106
0
    }
107
0
    return as;
108
0
  }
109
110
0
  yb::Result<uint64_t> Size() const override {
111
0
    const auto a_size = a_->Size();
112
0
    const auto b_size = b_->Size();
113
0
    CHECK_EQ(a_size.ok(), b_size.ok());
114
0
    if (a_size.ok()) {
115
0
      CHECK_EQ(*a_size, *b_size);
116
0
    }
117
0
    return a_size;
118
0
  }
119
120
0
  yb::Result<uint64_t> INode() const override {
121
0
    return STATUS(NotSupported, "INode", "Not supported in RandomAccessFileMirror");
122
0
  }
123
124
0
  bool ShouldForwardRawRequest() const override {
125
    // NOTE: not verified
126
0
    return a_->ShouldForwardRawRequest();
127
0
  }
128
129
0
  size_t GetUniqueId(char* id) const override {
130
    // NOTE: not verified
131
0
    return a_->GetUniqueId(id);
132
0
  }
133
134
0
  size_t memory_footprint() const override {
135
0
    LOG(FATAL) << "memory_footprint is not supported in RandomAccessFileMirror";
136
0
  }
137
138
0
  const std::string& filename() const override { return fname; }
139
};
140
141
class WritableFileMirror : public WritableFile {
142
 public:
143
  unique_ptr<WritableFile> a_, b_;
144
  std::string fname;
145
0
  explicit WritableFileMirror(std::string f) : fname(std::move(f)) {}
146
147
0
  Status Append(const Slice& data) override {
148
0
    Status as = a_->Append(data);
149
0
    Status bs = b_->Append(data);
150
0
    assert(as.code() == bs.code());
151
0
    return as;
152
0
  }
153
0
  Status PositionedAppend(const Slice& data, uint64_t offset) override {
154
0
    Status as = a_->PositionedAppend(data, offset);
155
0
    Status bs = b_->PositionedAppend(data, offset);
156
0
    assert(as.code() == bs.code());
157
0
    return as;
158
0
  }
159
0
  Status Truncate(uint64_t size) override {
160
0
    Status as = a_->Truncate(size);
161
0
    Status bs = b_->Truncate(size);
162
0
    assert(as.code() == bs.code());
163
0
    return as;
164
0
  }
165
0
  Status Close() override {
166
0
    Status as = a_->Close();
167
0
    Status bs = b_->Close();
168
0
    assert(as.code() == bs.code());
169
0
    return as;
170
0
  }
171
0
  Status Flush() override {
172
0
    Status as = a_->Flush();
173
0
    Status bs = b_->Flush();
174
0
    assert(as.code() == bs.code());
175
0
    return as;
176
0
  }
177
0
  Status Sync() override {
178
0
    Status as = a_->Sync();
179
0
    Status bs = b_->Sync();
180
0
    assert(as.code() == bs.code());
181
0
    return as;
182
0
  }
183
0
  Status Fsync() override {
184
0
    Status as = a_->Fsync();
185
0
    Status bs = b_->Fsync();
186
0
    assert(as.code() == bs.code());
187
0
    return as;
188
0
  }
189
0
  bool IsSyncThreadSafe() const override {
190
0
    bool as = a_->IsSyncThreadSafe();
191
0
    assert(as == b_->IsSyncThreadSafe());
192
0
    return as;
193
0
  }
194
0
  void SetIOPriority(Env::IOPriority pri) override {
195
0
    a_->SetIOPriority(pri);
196
0
    b_->SetIOPriority(pri);
197
0
  }
198
0
  Env::IOPriority GetIOPriority() override {
199
    // NOTE: we don't verify this one
200
0
    return a_->GetIOPriority();
201
0
  }
202
0
  uint64_t GetFileSize() override {
203
0
    uint64_t as = a_->GetFileSize();
204
0
    assert(as == b_->GetFileSize());
205
0
    return as;
206
0
  }
207
  void GetPreallocationStatus(size_t* block_size,
208
0
                              size_t* last_allocated_block) override {
209
    // NOTE: we don't verify this one
210
0
    return a_->GetPreallocationStatus(block_size, last_allocated_block);
211
0
  }
212
0
  size_t GetUniqueId(char* id) const override {
213
    // NOTE: we don't verify this one
214
0
    return a_->GetUniqueId(id);
215
0
  }
216
0
  Status InvalidateCache(size_t offset, size_t length) override {
217
0
    Status as = a_->InvalidateCache(offset, length);
218
0
    Status bs = b_->InvalidateCache(offset, length);
219
0
    assert(as.code() == bs.code());
220
0
    return as;
221
0
  }
222
223
 protected:
224
0
  Status Allocate(uint64_t offset, uint64_t length) override {
225
0
    Status as = a_->Allocate(offset, length);
226
0
    Status bs = b_->Allocate(offset, length);
227
0
    assert(as.code() == bs.code());
228
0
    return as;
229
0
  }
230
0
  Status RangeSync(uint64_t offset, uint64_t nbytes) override {
231
0
    Status as = a_->RangeSync(offset, nbytes);
232
0
    Status bs = b_->RangeSync(offset, nbytes);
233
0
    assert(as.code() == bs.code());
234
0
    return as;
235
0
  }
236
};
237
238
Status EnvMirror::NewSequentialFile(const std::string& f,
239
                                    unique_ptr<SequentialFile>* r,
240
0
                                    const EnvOptions& options) {
241
0
  if (f.find("/proc/") == 0) {
242
0
    return a_->NewSequentialFile(f, r, options);
243
0
  }
244
0
  SequentialFileMirror* mf = new SequentialFileMirror(f);
245
0
  Status as = a_->NewSequentialFile(f, &mf->a_, options);
246
0
  Status bs = b_->NewSequentialFile(f, &mf->b_, options);
247
0
  assert(as.code() == bs.code());
248
0
  if (as.ok())
249
0
    r->reset(mf);
250
0
  else
251
0
    delete mf;
252
0
  return as;
253
0
}
254
255
Status EnvMirror::NewRandomAccessFile(const std::string& f,
256
                                      unique_ptr<RandomAccessFile>* r,
257
0
                                      const EnvOptions& options) {
258
0
  if (f.find("/proc/") == 0) {
259
0
    return a_->NewRandomAccessFile(f, r, options);
260
0
  }
261
0
  RandomAccessFileMirror* mf = new RandomAccessFileMirror(f);
262
0
  Status as = a_->NewRandomAccessFile(f, &mf->a_, options);
263
0
  Status bs = b_->NewRandomAccessFile(f, &mf->b_, options);
264
0
  assert(as.code() == bs.code());
265
0
  if (as.ok())
266
0
    r->reset(mf);
267
0
  else
268
0
    delete mf;
269
0
  return as;
270
0
}
271
272
Status EnvMirror::NewWritableFile(const std::string& f,
273
                                  unique_ptr<WritableFile>* r,
274
0
                                  const EnvOptions& options) {
275
0
  if (f.find("/proc/") == 0) return a_->NewWritableFile(f, r, options);
276
0
  WritableFileMirror* mf = new WritableFileMirror(f);
277
0
  Status as = a_->NewWritableFile(f, &mf->a_, options);
278
0
  Status bs = b_->NewWritableFile(f, &mf->b_, options);
279
0
  assert(as.code() == bs.code());
280
0
  if (as.ok())
281
0
    r->reset(mf);
282
0
  else
283
0
    delete mf;
284
0
  return as;
285
0
}
286
287
Status EnvMirror::ReuseWritableFile(const std::string& fname,
288
                                    const std::string& old_fname,
289
                                    unique_ptr<WritableFile>* r,
290
0
                                    const EnvOptions& options) {
291
0
  if (fname.find("/proc/") == 0)
292
0
    return a_->ReuseWritableFile(fname, old_fname, r, options);
293
0
  WritableFileMirror* mf = new WritableFileMirror(fname);
294
0
  Status as = a_->ReuseWritableFile(fname, old_fname, &mf->a_, options);
295
0
  Status bs = b_->ReuseWritableFile(fname, old_fname, &mf->b_, options);
296
0
  assert(as.code() == bs.code());
297
0
  if (as.ok())
298
0
    r->reset(mf);
299
0
  else
300
0
    delete mf;
301
0
  return as;
302
0
}
303
304
Status EnvMirror::NewDirectory(const std::string& name,
305
0
                               unique_ptr<Directory>* result) {
306
0
  unique_ptr<Directory> br;
307
0
  Status as = a_->NewDirectory(name, result);
308
0
  Status bs = b_->NewDirectory(name, &br);
309
0
  assert(as.code() == bs.code());
310
0
  return as;
311
0
}
312
313
0
Status EnvMirror::FileExists(const std::string& f) {
314
0
  Status as = a_->FileExists(f);
315
0
  Status bs = b_->FileExists(f);
316
0
  assert(as.code() == bs.code());
317
0
  return as;
318
0
}
319
320
Status EnvMirror::GetChildren(const std::string& dir,
321
0
                              std::vector<std::string>* r) {
322
0
  std::vector<std::string> ar, br;
323
0
  Status as = a_->GetChildren(dir, &ar);
324
0
  Status bs = b_->GetChildren(dir, &br);
325
0
  assert(as.code() == bs.code());
326
0
  std::sort(ar.begin(), ar.end());
327
0
  std::sort(br.begin(), br.end());
328
0
  if (!as.ok() || ar != br) {
329
0
    assert(0 == "getchildren results don't match");
330
0
  }
331
0
  *r = ar;
332
0
  return as;
333
0
}
334
335
0
Status EnvMirror::DeleteFile(const std::string& f) {
336
0
  Status as = a_->DeleteFile(f);
337
0
  Status bs = b_->DeleteFile(f);
338
0
  assert(as.code() == bs.code());
339
0
  return as;
340
0
}
341
342
0
Status EnvMirror::CreateDir(const std::string& d) {
343
0
  Status as = a_->CreateDir(d);
344
0
  Status bs = b_->CreateDir(d);
345
0
  assert(as.code() == bs.code());
346
0
  return as;
347
0
}
348
349
0
Status EnvMirror::CreateDirIfMissing(const std::string& d) {
350
0
  Status as = a_->CreateDirIfMissing(d);
351
0
  Status bs = b_->CreateDirIfMissing(d);
352
0
  assert(as.code() == bs.code());
353
0
  return as;
354
0
}
355
356
0
Status EnvMirror::DeleteDir(const std::string& d) {
357
0
  Status as = a_->DeleteDir(d);
358
0
  Status bs = b_->DeleteDir(d);
359
0
  assert(as.code() == bs.code());
360
0
  return as;
361
0
}
362
363
0
Status EnvMirror::GetFileSize(const std::string& f, uint64_t* s) {
364
0
  uint64_t asize, bsize;
365
0
  Status as = a_->GetFileSize(f, &asize);
366
0
  Status bs = b_->GetFileSize(f, &bsize);
367
0
  assert(as.code() == bs.code());
368
0
  assert(!as.ok() || asize == bsize);
369
0
  *s = asize;
370
0
  return as;
371
0
}
372
373
Status EnvMirror::GetFileModificationTime(const std::string& fname,
374
0
                                          uint64_t* file_mtime) {
375
0
  uint64_t amtime, bmtime;
376
0
  Status as = a_->GetFileModificationTime(fname, &amtime);
377
0
  Status bs = b_->GetFileModificationTime(fname, &bmtime);
378
0
  assert(as.code() == bs.code());
379
0
  assert(!as.ok() || amtime - bmtime < 10000 || bmtime - amtime < 10000);
380
0
  *file_mtime = amtime;
381
0
  return as;
382
0
}
383
384
0
Status EnvMirror::RenameFile(const std::string& s, const std::string& t) {
385
0
  Status as = a_->RenameFile(s, t);
386
0
  Status bs = b_->RenameFile(s, t);
387
0
  assert(as.code() == bs.code());
388
0
  return as;
389
0
}
390
391
0
Status EnvMirror::LinkFile(const std::string& s, const std::string& t) {
392
0
  Status as = a_->LinkFile(s, t);
393
0
  Status bs = b_->LinkFile(s, t);
394
0
  assert(as.code() == bs.code());
395
0
  return as;
396
0
}
397
398
0
Status EnvMirror::LockFile(const std::string& f, FileLock** l) {
399
0
  FileLock* al, *bl;
400
0
  Status as = a_->LockFile(f, &al);
401
0
  Status bs = b_->LockFile(f, &bl);
402
0
  assert(as.code() == bs.code());
403
0
  if (as.ok()) *l = new FileLockMirror(al, bl);
404
0
  return as;
405
0
}
406
407
0
Status EnvMirror::UnlockFile(FileLock* l) {
408
0
  FileLockMirror* ml = static_cast<FileLockMirror*>(l);
409
0
  Status as = a_->UnlockFile(ml->a_);
410
0
  Status bs = b_->UnlockFile(ml->b_);
411
0
  assert(as.code() == bs.code());
412
0
  return as;
413
0
}
414
415
}  // namespace rocksdb
416
#endif