// Copyright (c) 2016-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). #pragma once #include #include #include "rocksdb/file_system.h" #include "rocksdb/io_status.h" #include "rocksdb/rocksdb_namespace.h" namespace ROCKSDB_NAMESPACE { class Logger; struct OpCounter { std::atomic ops; std::atomic bytes; OpCounter() : ops(0), bytes(0) {} void Reset() { ops = 0; bytes = 0; } void RecordOp(const IOStatus& io_s, size_t added_bytes) { if (!io_s.IsNotSupported()) { ops.fetch_add(1, std::memory_order_relaxed); } if (io_s.ok()) { bytes.fetch_add(added_bytes, std::memory_order_relaxed); } } }; struct FileOpCounters { static const char* kName() { return "FileOpCounters"; } std::atomic opens; std::atomic closes; std::atomic deletes; std::atomic renames; std::atomic flushes; std::atomic syncs; std::atomic dsyncs; std::atomic fsyncs; std::atomic dir_opens; std::atomic dir_closes; OpCounter reads; OpCounter writes; FileOpCounters() : opens(0), closes(0), deletes(0), renames(0), flushes(0), syncs(0), dsyncs(0), fsyncs(0), dir_opens(0), dir_closes(0) {} void Reset() { opens = 0; closes = 0; deletes = 0; renames = 0; flushes = 0; syncs = 0; dsyncs = 0; fsyncs = 0; dir_opens = 0; dir_closes = 0; reads.Reset(); writes.Reset(); } std::string PrintCounters() const; }; // A FileSystem class that counts operations (reads, writes, opens, closes, etc) class CountedFileSystem : public FileSystemWrapper { public: private: FileOpCounters counters_; public: explicit CountedFileSystem(const std::shared_ptr& base); static const char* kClassName() { return "CountedFileSystem"; } const char* Name() const override { return kClassName(); } IOStatus NewSequentialFile(const std::string& f, const FileOptions& options, std::unique_ptr* r, IODebugContext* dbg) override; IOStatus NewRandomAccessFile(const std::string& f, const FileOptions& file_opts, std::unique_ptr* r, IODebugContext* dbg) override; IOStatus NewWritableFile(const std::string& f, const FileOptions& options, std::unique_ptr* r, IODebugContext* dbg) override; IOStatus ReopenWritableFile(const std::string& fname, const FileOptions& options, std::unique_ptr* result, IODebugContext* dbg) override; IOStatus ReuseWritableFile(const std::string& fname, const std::string& old_fname, const FileOptions& file_opts, std::unique_ptr* result, IODebugContext* dbg) override; IOStatus NewRandomRWFile(const std::string& name, const FileOptions& options, std::unique_ptr* result, IODebugContext* dbg) override; IOStatus NewDirectory(const std::string& name, const IOOptions& io_opts, std::unique_ptr* result, IODebugContext* dbg) override; IOStatus DeleteFile(const std::string& fname, const IOOptions& options, IODebugContext* dbg) override { IOStatus s = target()->DeleteFile(fname, options, dbg); if (s.ok()) { counters_.deletes++; } return s; } IOStatus RenameFile(const std::string& s, const std::string& t, const IOOptions& options, IODebugContext* dbg) override { IOStatus st = target()->RenameFile(s, t, options, dbg); if (st.ok()) { counters_.renames++; } return st; } const FileOpCounters* counters() const { return &counters_; } FileOpCounters* counters() { return &counters_; } const void* GetOptionsPtr(const std::string& name) const override { if (name == FileOpCounters::kName()) { return counters(); } else { return FileSystemWrapper::GetOptionsPtr(name); } } // Prints the counters to a string std::string PrintCounters() const { return counters_.PrintCounters(); } void ResetCounters() { counters_.Reset(); } }; } // namespace ROCKSDB_NAMESPACE