1 // Copyright (c) 2017-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 
6 #include "env/composite_env_wrapper.h"
7 #include "monitoring/perf_context_imp.h"
8 #include "rocksdb/env.h"
9 #include "rocksdb/file_system.h"
10 #include "rocksdb/status.h"
11 
12 namespace ROCKSDB_NAMESPACE {
13 
14 #ifndef ROCKSDB_LITE
15 namespace {
16 class TimedFileSystem : public FileSystemWrapper {
17  public:
TimedFileSystem(const std::shared_ptr<FileSystem> & base)18   explicit TimedFileSystem(const std::shared_ptr<FileSystem>& base)
19       : FileSystemWrapper(base) {}
20 
Name() const21   const char* Name() const override { return "TimedFS"; }
NewSequentialFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSSequentialFile> * result,IODebugContext * dbg)22   IOStatus NewSequentialFile(const std::string& fname,
23                              const FileOptions& options,
24                              std::unique_ptr<FSSequentialFile>* result,
25                              IODebugContext* dbg) override {
26     PERF_TIMER_GUARD(env_new_sequential_file_nanos);
27     return FileSystemWrapper::NewSequentialFile(fname, options, result, dbg);
28   }
29 
NewRandomAccessFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomAccessFile> * result,IODebugContext * dbg)30   IOStatus NewRandomAccessFile(const std::string& fname,
31                                const FileOptions& options,
32                                std::unique_ptr<FSRandomAccessFile>* result,
33                                IODebugContext* dbg) override {
34     PERF_TIMER_GUARD(env_new_random_access_file_nanos);
35     return FileSystemWrapper::NewRandomAccessFile(fname, options, result, dbg);
36   }
37 
NewWritableFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)38   IOStatus NewWritableFile(const std::string& fname, const FileOptions& options,
39                            std::unique_ptr<FSWritableFile>* result,
40                            IODebugContext* dbg) override {
41     PERF_TIMER_GUARD(env_new_writable_file_nanos);
42     return FileSystemWrapper::NewWritableFile(fname, options, result, dbg);
43   }
44 
ReuseWritableFile(const std::string & fname,const std::string & old_fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)45   IOStatus ReuseWritableFile(const std::string& fname,
46                              const std::string& old_fname,
47                              const FileOptions& options,
48                              std::unique_ptr<FSWritableFile>* result,
49                              IODebugContext* dbg) override {
50     PERF_TIMER_GUARD(env_reuse_writable_file_nanos);
51     return FileSystemWrapper::ReuseWritableFile(fname, old_fname, options,
52                                                 result, dbg);
53   }
54 
NewRandomRWFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomRWFile> * result,IODebugContext * dbg)55   IOStatus NewRandomRWFile(const std::string& fname, const FileOptions& options,
56                            std::unique_ptr<FSRandomRWFile>* result,
57                            IODebugContext* dbg) override {
58     PERF_TIMER_GUARD(env_new_random_rw_file_nanos);
59     return FileSystemWrapper::NewRandomRWFile(fname, options, result, dbg);
60   }
61 
NewDirectory(const std::string & name,const IOOptions & options,std::unique_ptr<FSDirectory> * result,IODebugContext * dbg)62   IOStatus NewDirectory(const std::string& name, const IOOptions& options,
63                         std::unique_ptr<FSDirectory>* result,
64                         IODebugContext* dbg) override {
65     PERF_TIMER_GUARD(env_new_directory_nanos);
66     return FileSystemWrapper::NewDirectory(name, options, result, dbg);
67   }
68 
FileExists(const std::string & fname,const IOOptions & options,IODebugContext * dbg)69   IOStatus FileExists(const std::string& fname, const IOOptions& options,
70                       IODebugContext* dbg) override {
71     PERF_TIMER_GUARD(env_file_exists_nanos);
72     return FileSystemWrapper::FileExists(fname, options, dbg);
73   }
74 
GetChildren(const std::string & dir,const IOOptions & options,std::vector<std::string> * result,IODebugContext * dbg)75   IOStatus GetChildren(const std::string& dir, const IOOptions& options,
76                        std::vector<std::string>* result,
77                        IODebugContext* dbg) override {
78     PERF_TIMER_GUARD(env_get_children_nanos);
79     return FileSystemWrapper::GetChildren(dir, options, result, dbg);
80   }
81 
GetChildrenFileAttributes(const std::string & dir,const IOOptions & options,std::vector<FileAttributes> * result,IODebugContext * dbg)82   IOStatus GetChildrenFileAttributes(const std::string& dir,
83                                      const IOOptions& options,
84                                      std::vector<FileAttributes>* result,
85                                      IODebugContext* dbg) override {
86     PERF_TIMER_GUARD(env_get_children_file_attributes_nanos);
87     return FileSystemWrapper::GetChildrenFileAttributes(dir, options, result,
88                                                         dbg);
89   }
90 
DeleteFile(const std::string & fname,const IOOptions & options,IODebugContext * dbg)91   IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
92                       IODebugContext* dbg) override {
93     PERF_TIMER_GUARD(env_delete_file_nanos);
94     return FileSystemWrapper::DeleteFile(fname, options, dbg);
95   }
96 
CreateDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)97   IOStatus CreateDir(const std::string& dirname, const IOOptions& options,
98                      IODebugContext* dbg) override {
99     PERF_TIMER_GUARD(env_create_dir_nanos);
100     return FileSystemWrapper::CreateDir(dirname, options, dbg);
101   }
102 
CreateDirIfMissing(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)103   IOStatus CreateDirIfMissing(const std::string& dirname,
104                               const IOOptions& options,
105                               IODebugContext* dbg) override {
106     PERF_TIMER_GUARD(env_create_dir_if_missing_nanos);
107     return FileSystemWrapper::CreateDirIfMissing(dirname, options, dbg);
108   }
109 
DeleteDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)110   IOStatus DeleteDir(const std::string& dirname, const IOOptions& options,
111                      IODebugContext* dbg) override {
112     PERF_TIMER_GUARD(env_delete_dir_nanos);
113     return FileSystemWrapper::DeleteDir(dirname, options, dbg);
114   }
115 
GetFileSize(const std::string & fname,const IOOptions & options,uint64_t * file_size,IODebugContext * dbg)116   IOStatus GetFileSize(const std::string& fname, const IOOptions& options,
117                        uint64_t* file_size, IODebugContext* dbg) override {
118     PERF_TIMER_GUARD(env_get_file_size_nanos);
119     return FileSystemWrapper::GetFileSize(fname, options, file_size, dbg);
120   }
121 
GetFileModificationTime(const std::string & fname,const IOOptions & options,uint64_t * file_mtime,IODebugContext * dbg)122   IOStatus GetFileModificationTime(const std::string& fname,
123                                    const IOOptions& options,
124                                    uint64_t* file_mtime,
125                                    IODebugContext* dbg) override {
126     PERF_TIMER_GUARD(env_get_file_modification_time_nanos);
127     return FileSystemWrapper::GetFileModificationTime(fname, options,
128                                                       file_mtime, dbg);
129   }
130 
RenameFile(const std::string & src,const std::string & dst,const IOOptions & options,IODebugContext * dbg)131   IOStatus RenameFile(const std::string& src, const std::string& dst,
132                       const IOOptions& options, IODebugContext* dbg) override {
133     PERF_TIMER_GUARD(env_rename_file_nanos);
134     return FileSystemWrapper::RenameFile(src, dst, options, dbg);
135   }
136 
LinkFile(const std::string & src,const std::string & dst,const IOOptions & options,IODebugContext * dbg)137   IOStatus LinkFile(const std::string& src, const std::string& dst,
138                     const IOOptions& options, IODebugContext* dbg) override {
139     PERF_TIMER_GUARD(env_link_file_nanos);
140     return FileSystemWrapper::LinkFile(src, dst, options, dbg);
141   }
142 
LockFile(const std::string & fname,const IOOptions & options,FileLock ** lock,IODebugContext * dbg)143   IOStatus LockFile(const std::string& fname, const IOOptions& options,
144                     FileLock** lock, IODebugContext* dbg) override {
145     PERF_TIMER_GUARD(env_lock_file_nanos);
146     return FileSystemWrapper::LockFile(fname, options, lock, dbg);
147   }
148 
UnlockFile(FileLock * lock,const IOOptions & options,IODebugContext * dbg)149   IOStatus UnlockFile(FileLock* lock, const IOOptions& options,
150                       IODebugContext* dbg) override {
151     PERF_TIMER_GUARD(env_unlock_file_nanos);
152     return FileSystemWrapper::UnlockFile(lock, options, dbg);
153   }
154 
NewLogger(const std::string & fname,const IOOptions & options,std::shared_ptr<Logger> * result,IODebugContext * dbg)155   IOStatus NewLogger(const std::string& fname, const IOOptions& options,
156                      std::shared_ptr<Logger>* result,
157                      IODebugContext* dbg) override {
158     PERF_TIMER_GUARD(env_new_logger_nanos);
159     return FileSystemWrapper::NewLogger(fname, options, result, dbg);
160   }
161 };
162 }  // namespace
163 
NewTimedFileSystem(const std::shared_ptr<FileSystem> & base)164 std::shared_ptr<FileSystem> NewTimedFileSystem(
165     const std::shared_ptr<FileSystem>& base) {
166   return std::make_shared<TimedFileSystem>(base);
167 }
168 
169 // An environment that measures function call times for filesystem
170 // operations, reporting results to variables in PerfContext.
NewTimedEnv(Env * base_env)171 Env* NewTimedEnv(Env* base_env) {
172   std::shared_ptr<FileSystem> timed_fs =
173       NewTimedFileSystem(base_env->GetFileSystem());
174   return new CompositeEnvWrapper(base_env, timed_fs);
175 }
176 
177 #else  // ROCKSDB_LITE
178 
179 Env* NewTimedEnv(Env* /*base_env*/) { return nullptr; }
180 
181 #endif  // !ROCKSDB_LITE
182 
183 }  // namespace ROCKSDB_NAMESPACE
184