env_mirror.cc 8.6 KB

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