env_mirror.cc 7.9 KB

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