file_system_tracer.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. // Copyright (c) 2019-present, Facebook, 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. #pragma once
  6. #include "rocksdb/file_system.h"
  7. #include "rocksdb/system_clock.h"
  8. #include "trace_replay/io_tracer.h"
  9. namespace ROCKSDB_NAMESPACE {
  10. // FileSystemTracingWrapper is a wrapper class above FileSystem that forwards
  11. // the call to the underlying storage system. It then invokes IOTracer to record
  12. // file operations and other contextual information in a binary format for
  13. // tracing. It overrides methods we are interested in tracing and extends
  14. // FileSystemWrapper, which forwards all methods that are not explicitly
  15. // overridden.
  16. class FileSystemTracingWrapper : public FileSystemWrapper {
  17. public:
  18. FileSystemTracingWrapper(const std::shared_ptr<FileSystem>& t,
  19. const std::shared_ptr<IOTracer>& io_tracer)
  20. : FileSystemWrapper(t),
  21. io_tracer_(io_tracer),
  22. clock_(SystemClock::Default().get()) {}
  23. ~FileSystemTracingWrapper() override {}
  24. static const char* kClassName() { return "FileSystemTracing"; }
  25. const char* Name() const override { return kClassName(); }
  26. IOStatus NewSequentialFile(const std::string& fname,
  27. const FileOptions& file_opts,
  28. std::unique_ptr<FSSequentialFile>* result,
  29. IODebugContext* dbg) override;
  30. IOStatus NewRandomAccessFile(const std::string& fname,
  31. const FileOptions& file_opts,
  32. std::unique_ptr<FSRandomAccessFile>* result,
  33. IODebugContext* dbg) override;
  34. IOStatus NewWritableFile(const std::string& fname,
  35. const FileOptions& file_opts,
  36. std::unique_ptr<FSWritableFile>* result,
  37. IODebugContext* dbg) override;
  38. IOStatus ReopenWritableFile(const std::string& fname,
  39. const FileOptions& file_opts,
  40. std::unique_ptr<FSWritableFile>* result,
  41. IODebugContext* dbg) override;
  42. IOStatus ReuseWritableFile(const std::string& fname,
  43. const std::string& old_fname,
  44. const FileOptions& file_opts,
  45. std::unique_ptr<FSWritableFile>* result,
  46. IODebugContext* dbg) override;
  47. IOStatus NewRandomRWFile(const std::string& fname, const FileOptions& options,
  48. std::unique_ptr<FSRandomRWFile>* result,
  49. IODebugContext* dbg) override;
  50. IOStatus NewDirectory(const std::string& name, const IOOptions& io_opts,
  51. std::unique_ptr<FSDirectory>* result,
  52. IODebugContext* dbg) override;
  53. IOStatus GetChildren(const std::string& dir, const IOOptions& io_opts,
  54. std::vector<std::string>* r,
  55. IODebugContext* dbg) override;
  56. IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
  57. IODebugContext* dbg) override;
  58. IOStatus CreateDir(const std::string& dirname, const IOOptions& options,
  59. IODebugContext* dbg) override;
  60. IOStatus CreateDirIfMissing(const std::string& dirname,
  61. const IOOptions& options,
  62. IODebugContext* dbg) override;
  63. IOStatus DeleteDir(const std::string& dirname, const IOOptions& options,
  64. IODebugContext* dbg) override;
  65. IOStatus GetFileSize(const std::string& fname, const IOOptions& options,
  66. uint64_t* file_size, IODebugContext* dbg) override;
  67. IOStatus Truncate(const std::string& fname, size_t size,
  68. const IOOptions& options, IODebugContext* dbg) override;
  69. private:
  70. std::shared_ptr<IOTracer> io_tracer_;
  71. SystemClock* clock_;
  72. };
  73. // The FileSystemPtr is a wrapper class that takes pointer to storage systems
  74. // (such as posix filesystems). It overloads operator -> and returns a pointer
  75. // of either FileSystem or FileSystemTracingWrapper based on whether tracing is
  76. // enabled or not. It is added to bypass FileSystemTracingWrapper when tracing
  77. // is disabled.
  78. class FileSystemPtr {
  79. public:
  80. FileSystemPtr(std::shared_ptr<FileSystem> fs,
  81. const std::shared_ptr<IOTracer>& io_tracer)
  82. : fs_(fs), io_tracer_(io_tracer) {
  83. fs_tracer_ = std::make_shared<FileSystemTracingWrapper>(fs_, io_tracer_);
  84. }
  85. std::shared_ptr<FileSystem> operator->() const {
  86. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  87. return fs_tracer_;
  88. } else {
  89. return fs_;
  90. }
  91. }
  92. /* Returns the underlying File System pointer */
  93. FileSystem* get() const {
  94. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  95. return fs_tracer_.get();
  96. } else {
  97. return fs_.get();
  98. }
  99. }
  100. private:
  101. std::shared_ptr<FileSystem> fs_;
  102. std::shared_ptr<IOTracer> io_tracer_;
  103. std::shared_ptr<FileSystemTracingWrapper> fs_tracer_;
  104. };
  105. // FSSequentialFileTracingWrapper is a wrapper class above FSSequentialFile that
  106. // forwards the call to the underlying storage system. It then invokes IOTracer
  107. // to record file operations and other contextual information in a binary format
  108. // for tracing. It overrides methods we are interested in tracing and extends
  109. // FSSequentialFileWrapper, which forwards all methods that are not explicitly
  110. // overridden.
  111. class FSSequentialFileTracingWrapper : public FSSequentialFileOwnerWrapper {
  112. public:
  113. FSSequentialFileTracingWrapper(std::unique_ptr<FSSequentialFile>&& t,
  114. std::shared_ptr<IOTracer> io_tracer,
  115. const std::string& file_name)
  116. : FSSequentialFileOwnerWrapper(std::move(t)),
  117. io_tracer_(io_tracer),
  118. clock_(SystemClock::Default().get()),
  119. file_name_(file_name) {}
  120. ~FSSequentialFileTracingWrapper() override {}
  121. IOStatus Read(size_t n, const IOOptions& options, Slice* result,
  122. char* scratch, IODebugContext* dbg) override;
  123. IOStatus InvalidateCache(size_t offset, size_t length) override;
  124. IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options,
  125. Slice* result, char* scratch,
  126. IODebugContext* dbg) override;
  127. private:
  128. std::shared_ptr<IOTracer> io_tracer_;
  129. SystemClock* clock_;
  130. std::string file_name_;
  131. };
  132. // The FSSequentialFilePtr is a wrapper class that takes pointer to storage
  133. // systems (such as posix filesystems). It overloads operator -> and returns a
  134. // pointer of either FSSequentialFile or FSSequentialFileTracingWrapper based on
  135. // whether tracing is enabled or not. It is added to bypass
  136. // FSSequentialFileTracingWrapper when tracing is disabled.
  137. class FSSequentialFilePtr {
  138. public:
  139. FSSequentialFilePtr() = delete;
  140. FSSequentialFilePtr(std::unique_ptr<FSSequentialFile>&& fs,
  141. const std::shared_ptr<IOTracer>& io_tracer,
  142. const std::string& file_name)
  143. : io_tracer_(io_tracer),
  144. fs_tracer_(std::move(fs), io_tracer_,
  145. file_name.substr(file_name.find_last_of("/\\") +
  146. 1) /* pass file name */) {}
  147. FSSequentialFile* operator->() const {
  148. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  149. return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_);
  150. } else {
  151. return fs_tracer_.target();
  152. }
  153. }
  154. FSSequentialFile* get() const {
  155. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  156. return const_cast<FSSequentialFileTracingWrapper*>(&fs_tracer_);
  157. } else {
  158. return fs_tracer_.target();
  159. }
  160. }
  161. private:
  162. std::shared_ptr<IOTracer> io_tracer_;
  163. FSSequentialFileTracingWrapper fs_tracer_;
  164. };
  165. // FSRandomAccessFileTracingWrapper is a wrapper class above FSRandomAccessFile
  166. // that forwards the call to the underlying storage system. It then invokes
  167. // IOTracer to record file operations and other contextual information in a
  168. // binary format for tracing. It overrides methods we are interested in tracing
  169. // and extends FSRandomAccessFileWrapper, which forwards all methods that are
  170. // not explicitly overridden.
  171. class FSRandomAccessFileTracingWrapper : public FSRandomAccessFileOwnerWrapper {
  172. public:
  173. FSRandomAccessFileTracingWrapper(std::unique_ptr<FSRandomAccessFile>&& t,
  174. std::shared_ptr<IOTracer> io_tracer,
  175. const std::string& file_name)
  176. : FSRandomAccessFileOwnerWrapper(std::move(t)),
  177. io_tracer_(io_tracer),
  178. clock_(SystemClock::Default().get()),
  179. file_name_(file_name) {}
  180. ~FSRandomAccessFileTracingWrapper() override {}
  181. IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
  182. Slice* result, char* scratch,
  183. IODebugContext* dbg) const override;
  184. IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs,
  185. const IOOptions& options, IODebugContext* dbg) override;
  186. IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& options,
  187. IODebugContext* dbg) override;
  188. IOStatus InvalidateCache(size_t offset, size_t length) override;
  189. IOStatus ReadAsync(FSReadRequest& req, const IOOptions& opts,
  190. std::function<void(FSReadRequest&, void*)> cb,
  191. void* cb_arg, void** io_handle, IOHandleDeleter* del_fn,
  192. IODebugContext* dbg) override;
  193. void ReadAsyncCallback(FSReadRequest& req, void* cb_arg);
  194. private:
  195. std::shared_ptr<IOTracer> io_tracer_;
  196. SystemClock* clock_;
  197. // Stores file name instead of full path.
  198. std::string file_name_;
  199. struct ReadAsyncCallbackInfo {
  200. uint64_t start_time_;
  201. std::function<void(FSReadRequest&, void*)> cb_;
  202. void* cb_arg_;
  203. std::string file_op_;
  204. };
  205. };
  206. // The FSRandomAccessFilePtr is a wrapper class that takes pointer to storage
  207. // systems (such as posix filesystems). It overloads operator -> and returns a
  208. // pointer of either FSRandomAccessFile or FSRandomAccessFileTracingWrapper
  209. // based on whether tracing is enabled or not. It is added to bypass
  210. // FSRandomAccessFileTracingWrapper when tracing is disabled.
  211. class FSRandomAccessFilePtr {
  212. public:
  213. FSRandomAccessFilePtr(std::unique_ptr<FSRandomAccessFile>&& fs,
  214. const std::shared_ptr<IOTracer>& io_tracer,
  215. const std::string& file_name)
  216. : io_tracer_(io_tracer),
  217. fs_tracer_(std::move(fs), io_tracer_,
  218. file_name.substr(file_name.find_last_of("/\\") +
  219. 1) /* pass file name */) {}
  220. FSRandomAccessFile* operator->() const {
  221. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  222. return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_);
  223. } else {
  224. return fs_tracer_.target();
  225. }
  226. }
  227. FSRandomAccessFile* get() const {
  228. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  229. return const_cast<FSRandomAccessFileTracingWrapper*>(&fs_tracer_);
  230. } else {
  231. return fs_tracer_.target();
  232. }
  233. }
  234. private:
  235. std::shared_ptr<IOTracer> io_tracer_;
  236. FSRandomAccessFileTracingWrapper fs_tracer_;
  237. };
  238. // FSWritableFileTracingWrapper is a wrapper class above FSWritableFile that
  239. // forwards the call to the underlying storage system. It then invokes IOTracer
  240. // to record file operations and other contextual information in a binary format
  241. // for tracing. It overrides methods we are interested in tracing and extends
  242. // FSWritableFileWrapper, which forwards all methods that are not explicitly
  243. // overridden.
  244. class FSWritableFileTracingWrapper : public FSWritableFileOwnerWrapper {
  245. public:
  246. FSWritableFileTracingWrapper(std::unique_ptr<FSWritableFile>&& t,
  247. std::shared_ptr<IOTracer> io_tracer,
  248. const std::string& file_name)
  249. : FSWritableFileOwnerWrapper(std::move(t)),
  250. io_tracer_(io_tracer),
  251. clock_(SystemClock::Default().get()),
  252. file_name_(file_name) {}
  253. ~FSWritableFileTracingWrapper() override {}
  254. IOStatus Append(const Slice& data, const IOOptions& options,
  255. IODebugContext* dbg) override;
  256. IOStatus Append(const Slice& data, const IOOptions& options,
  257. const DataVerificationInfo& /*verification_info*/,
  258. IODebugContext* dbg) override {
  259. return Append(data, options, dbg);
  260. }
  261. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  262. const IOOptions& options,
  263. IODebugContext* dbg) override;
  264. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  265. const IOOptions& options,
  266. const DataVerificationInfo& /*verification_info*/,
  267. IODebugContext* dbg) override {
  268. return PositionedAppend(data, offset, options, dbg);
  269. }
  270. IOStatus Truncate(uint64_t size, const IOOptions& options,
  271. IODebugContext* dbg) override;
  272. IOStatus Close(const IOOptions& options, IODebugContext* dbg) override;
  273. uint64_t GetFileSize(const IOOptions& options, IODebugContext* dbg) override;
  274. IOStatus InvalidateCache(size_t offset, size_t length) override;
  275. private:
  276. std::shared_ptr<IOTracer> io_tracer_;
  277. SystemClock* clock_;
  278. // Stores file name instead of full path.
  279. std::string file_name_;
  280. };
  281. // The FSWritableFilePtr is a wrapper class that takes pointer to storage
  282. // systems (such as posix filesystems). It overloads operator -> and returns a
  283. // pointer of either FSWritableFile or FSWritableFileTracingWrapper based on
  284. // whether tracing is enabled or not. It is added to bypass
  285. // FSWritableFileTracingWrapper when tracing is disabled.
  286. class FSWritableFilePtr {
  287. public:
  288. FSWritableFilePtr(std::unique_ptr<FSWritableFile>&& fs,
  289. const std::shared_ptr<IOTracer>& io_tracer,
  290. const std::string& file_name)
  291. : io_tracer_(io_tracer) {
  292. fs_tracer_.reset(new FSWritableFileTracingWrapper(
  293. std::move(fs), io_tracer_,
  294. file_name.substr(file_name.find_last_of("/\\") +
  295. 1) /* pass file name */));
  296. }
  297. FSWritableFile* operator->() const {
  298. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  299. return fs_tracer_.get();
  300. } else {
  301. return fs_tracer_->target();
  302. }
  303. }
  304. FSWritableFile* get() const {
  305. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  306. return fs_tracer_.get();
  307. } else if (fs_tracer_) {
  308. return fs_tracer_->target();
  309. } else {
  310. return nullptr;
  311. }
  312. }
  313. void reset() {
  314. fs_tracer_.reset();
  315. io_tracer_ = nullptr;
  316. }
  317. private:
  318. std::shared_ptr<IOTracer> io_tracer_;
  319. std::unique_ptr<FSWritableFileTracingWrapper> fs_tracer_;
  320. };
  321. // FSRandomRWFileTracingWrapper is a wrapper class above FSRandomRWFile that
  322. // forwards the call to the underlying storage system. It then invokes IOTracer
  323. // to record file operations and other contextual information in a binary format
  324. // for tracing. It overrides methods we are interested in tracing and extends
  325. // FSRandomRWFileWrapper, which forwards all methods that are not explicitly
  326. // overridden.
  327. class FSRandomRWFileTracingWrapper : public FSRandomRWFileOwnerWrapper {
  328. public:
  329. FSRandomRWFileTracingWrapper(std::unique_ptr<FSRandomRWFile>&& t,
  330. std::shared_ptr<IOTracer> io_tracer,
  331. const std::string& file_name)
  332. : FSRandomRWFileOwnerWrapper(std::move(t)),
  333. io_tracer_(io_tracer),
  334. clock_(SystemClock::Default().get()),
  335. file_name_(file_name) {}
  336. ~FSRandomRWFileTracingWrapper() override {}
  337. IOStatus Write(uint64_t offset, const Slice& data, const IOOptions& options,
  338. IODebugContext* dbg) override;
  339. IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
  340. Slice* result, char* scratch,
  341. IODebugContext* dbg) const override;
  342. IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override;
  343. IOStatus Close(const IOOptions& options, IODebugContext* dbg) override;
  344. IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override;
  345. IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override;
  346. private:
  347. std::shared_ptr<IOTracer> io_tracer_;
  348. SystemClock* clock_;
  349. // Stores file name instead of full path.
  350. std::string file_name_;
  351. };
  352. // The FSRandomRWFilePtr is a wrapper class that takes pointer to storage
  353. // systems (such as posix filesystems). It overloads operator -> and returns a
  354. // pointer of either FSRandomRWFile or FSRandomRWFileTracingWrapper based on
  355. // whether tracing is enabled or not. It is added to bypass
  356. // FSRandomRWFileTracingWrapper when tracing is disabled.
  357. class FSRandomRWFilePtr {
  358. public:
  359. FSRandomRWFilePtr(std::unique_ptr<FSRandomRWFile>&& fs,
  360. std::shared_ptr<IOTracer> io_tracer,
  361. const std::string& file_name)
  362. : io_tracer_(io_tracer),
  363. fs_tracer_(std::move(fs), io_tracer_,
  364. file_name.substr(file_name.find_last_of("/\\") +
  365. 1) /* pass file name */) {}
  366. FSRandomRWFile* operator->() const {
  367. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  368. return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_);
  369. } else {
  370. return fs_tracer_.target();
  371. }
  372. }
  373. FSRandomRWFile* get() const {
  374. if (io_tracer_ && io_tracer_->is_tracing_enabled()) {
  375. return const_cast<FSRandomRWFileTracingWrapper*>(&fs_tracer_);
  376. } else {
  377. return fs_tracer_.target();
  378. }
  379. }
  380. private:
  381. std::shared_ptr<IOTracer> io_tracer_;
  382. FSRandomRWFileTracingWrapper fs_tracer_;
  383. };
  384. } // namespace ROCKSDB_NAMESPACE