/src/rocksdb/utilities/counted_fs.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-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 "utilities/counted_fs.h" |
7 | | |
8 | | #include <sstream> |
9 | | |
10 | | #include "rocksdb/file_system.h" |
11 | | #include "rocksdb/utilities/options_type.h" |
12 | | |
13 | | namespace ROCKSDB_NAMESPACE { |
14 | | namespace { |
15 | | class CountedSequentialFile : public FSSequentialFileOwnerWrapper { |
16 | | private: |
17 | | CountedFileSystem* fs_; |
18 | | |
19 | | public: |
20 | | CountedSequentialFile(std::unique_ptr<FSSequentialFile>&& f, |
21 | | CountedFileSystem* fs) |
22 | 0 | : FSSequentialFileOwnerWrapper(std::move(f)), fs_(fs) {} |
23 | | |
24 | 0 | ~CountedSequentialFile() override { fs_->counters()->closes++; } |
25 | | |
26 | | IOStatus Read(size_t n, const IOOptions& options, Slice* result, |
27 | 0 | char* scratch, IODebugContext* dbg) override { |
28 | 0 | IOStatus rv = target()->Read(n, options, result, scratch, dbg); |
29 | 0 | fs_->counters()->reads.RecordOp(rv, result->size()); |
30 | 0 | return rv; |
31 | 0 | } |
32 | | |
33 | | IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options, |
34 | | Slice* result, char* scratch, |
35 | 0 | IODebugContext* dbg) override { |
36 | 0 | IOStatus rv = |
37 | 0 | target()->PositionedRead(offset, n, options, result, scratch, dbg); |
38 | 0 | fs_->counters()->reads.RecordOp(rv, result->size()); |
39 | 0 | return rv; |
40 | 0 | } |
41 | | }; |
42 | | |
43 | | class CountedRandomAccessFile : public FSRandomAccessFileOwnerWrapper { |
44 | | private: |
45 | | CountedFileSystem* fs_; |
46 | | |
47 | | public: |
48 | | CountedRandomAccessFile(std::unique_ptr<FSRandomAccessFile>&& f, |
49 | | CountedFileSystem* fs) |
50 | 0 | : FSRandomAccessFileOwnerWrapper(std::move(f)), fs_(fs) {} |
51 | | |
52 | 0 | ~CountedRandomAccessFile() override { fs_->counters()->closes++; } |
53 | | |
54 | | IOStatus Read(uint64_t offset, size_t n, const IOOptions& options, |
55 | | Slice* result, char* scratch, |
56 | 0 | IODebugContext* dbg) const override { |
57 | 0 | IOStatus rv = target()->Read(offset, n, options, result, scratch, dbg); |
58 | 0 | fs_->counters()->reads.RecordOp(rv, result->size()); |
59 | 0 | return rv; |
60 | 0 | } |
61 | | |
62 | | IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs, |
63 | 0 | const IOOptions& options, IODebugContext* dbg) override { |
64 | 0 | IOStatus rv = target()->MultiRead(reqs, num_reqs, options, dbg); |
65 | 0 | for (size_t r = 0; r < num_reqs; r++) { |
66 | 0 | fs_->counters()->reads.RecordOp(reqs[r].status, reqs[r].result.size()); |
67 | 0 | } |
68 | 0 | return rv; |
69 | 0 | } |
70 | | }; |
71 | | |
72 | | class CountedWritableFile : public FSWritableFileOwnerWrapper { |
73 | | private: |
74 | | CountedFileSystem* fs_; |
75 | | |
76 | | public: |
77 | | CountedWritableFile(std::unique_ptr<FSWritableFile>&& f, |
78 | | CountedFileSystem* fs) |
79 | 0 | : FSWritableFileOwnerWrapper(std::move(f)), fs_(fs) {} |
80 | | |
81 | | IOStatus Append(const Slice& data, const IOOptions& options, |
82 | 0 | IODebugContext* dbg) override { |
83 | 0 | IOStatus rv = target()->Append(data, options, dbg); |
84 | 0 | fs_->counters()->writes.RecordOp(rv, data.size()); |
85 | 0 | return rv; |
86 | 0 | } |
87 | | |
88 | | IOStatus Append(const Slice& data, const IOOptions& options, |
89 | | const DataVerificationInfo& info, |
90 | 0 | IODebugContext* dbg) override { |
91 | 0 | IOStatus rv = target()->Append(data, options, info, dbg); |
92 | 0 | fs_->counters()->writes.RecordOp(rv, data.size()); |
93 | 0 | return rv; |
94 | 0 | } |
95 | | |
96 | | IOStatus PositionedAppend(const Slice& data, uint64_t offset, |
97 | | const IOOptions& options, |
98 | 0 | IODebugContext* dbg) override { |
99 | 0 | IOStatus rv = target()->PositionedAppend(data, offset, options, dbg); |
100 | 0 | fs_->counters()->writes.RecordOp(rv, data.size()); |
101 | 0 | return rv; |
102 | 0 | } |
103 | | |
104 | | IOStatus PositionedAppend(const Slice& data, uint64_t offset, |
105 | | const IOOptions& options, |
106 | | const DataVerificationInfo& info, |
107 | 0 | IODebugContext* dbg) override { |
108 | 0 | IOStatus rv = target()->PositionedAppend(data, offset, options, info, dbg); |
109 | 0 | fs_->counters()->writes.RecordOp(rv, data.size()); |
110 | 0 | return rv; |
111 | 0 | } |
112 | | |
113 | 0 | IOStatus Close(const IOOptions& options, IODebugContext* dbg) override { |
114 | 0 | IOStatus rv = target()->Close(options, dbg); |
115 | 0 | if (rv.ok()) { |
116 | 0 | fs_->counters()->closes++; |
117 | 0 | } |
118 | 0 | return rv; |
119 | 0 | } |
120 | | |
121 | 0 | IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override { |
122 | 0 | IOStatus rv = target()->Flush(options, dbg); |
123 | 0 | if (rv.ok()) { |
124 | 0 | fs_->counters()->flushes++; |
125 | 0 | } |
126 | 0 | return rv; |
127 | 0 | } |
128 | | |
129 | 0 | IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override { |
130 | 0 | IOStatus rv = target()->Sync(options, dbg); |
131 | 0 | if (rv.ok()) { |
132 | 0 | fs_->counters()->syncs++; |
133 | 0 | } |
134 | 0 | return rv; |
135 | 0 | } |
136 | | |
137 | 0 | IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override { |
138 | 0 | IOStatus rv = target()->Fsync(options, dbg); |
139 | 0 | if (rv.ok()) { |
140 | 0 | fs_->counters()->fsyncs++; |
141 | 0 | } |
142 | 0 | return rv; |
143 | 0 | } |
144 | | |
145 | | IOStatus RangeSync(uint64_t offset, uint64_t nbytes, const IOOptions& options, |
146 | 0 | IODebugContext* dbg) override { |
147 | 0 | IOStatus rv = target()->RangeSync(offset, nbytes, options, dbg); |
148 | 0 | if (rv.ok()) { |
149 | 0 | fs_->counters()->syncs++; |
150 | 0 | } |
151 | 0 | return rv; |
152 | 0 | } |
153 | | }; |
154 | | |
155 | | class CountedRandomRWFile : public FSRandomRWFileOwnerWrapper { |
156 | | private: |
157 | | mutable CountedFileSystem* fs_; |
158 | | |
159 | | public: |
160 | | CountedRandomRWFile(std::unique_ptr<FSRandomRWFile>&& f, |
161 | | CountedFileSystem* fs) |
162 | 0 | : FSRandomRWFileOwnerWrapper(std::move(f)), fs_(fs) {} |
163 | | IOStatus Write(uint64_t offset, const Slice& data, const IOOptions& options, |
164 | 0 | IODebugContext* dbg) override { |
165 | 0 | IOStatus rv = target()->Write(offset, data, options, dbg); |
166 | 0 | fs_->counters()->writes.RecordOp(rv, data.size()); |
167 | 0 | return rv; |
168 | 0 | } |
169 | | |
170 | | IOStatus Read(uint64_t offset, size_t n, const IOOptions& options, |
171 | | Slice* result, char* scratch, |
172 | 0 | IODebugContext* dbg) const override { |
173 | 0 | IOStatus rv = target()->Read(offset, n, options, result, scratch, dbg); |
174 | 0 | fs_->counters()->reads.RecordOp(rv, result->size()); |
175 | 0 | return rv; |
176 | 0 | } |
177 | | |
178 | 0 | IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override { |
179 | 0 | IOStatus rv = target()->Flush(options, dbg); |
180 | 0 | if (rv.ok()) { |
181 | 0 | fs_->counters()->flushes++; |
182 | 0 | } |
183 | 0 | return rv; |
184 | 0 | } |
185 | | |
186 | 0 | IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override { |
187 | 0 | IOStatus rv = target()->Sync(options, dbg); |
188 | 0 | if (rv.ok()) { |
189 | 0 | fs_->counters()->syncs++; |
190 | 0 | } |
191 | 0 | return rv; |
192 | 0 | } |
193 | | |
194 | 0 | IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override { |
195 | 0 | IOStatus rv = target()->Fsync(options, dbg); |
196 | 0 | if (rv.ok()) { |
197 | 0 | fs_->counters()->fsyncs++; |
198 | 0 | } |
199 | 0 | return rv; |
200 | 0 | } |
201 | | |
202 | 0 | IOStatus Close(const IOOptions& options, IODebugContext* dbg) override { |
203 | 0 | IOStatus rv = target()->Close(options, dbg); |
204 | 0 | if (rv.ok()) { |
205 | 0 | fs_->counters()->closes++; |
206 | 0 | } |
207 | 0 | return rv; |
208 | 0 | } |
209 | | }; |
210 | | |
211 | | class CountedDirectory : public FSDirectoryWrapper { |
212 | | private: |
213 | | mutable CountedFileSystem* fs_; |
214 | | bool closed_ = false; |
215 | | |
216 | | public: |
217 | | CountedDirectory(std::unique_ptr<FSDirectory>&& f, CountedFileSystem* fs) |
218 | 0 | : FSDirectoryWrapper(std::move(f)), fs_(fs) {} |
219 | | |
220 | 0 | IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override { |
221 | 0 | IOStatus rv = FSDirectoryWrapper::Fsync(options, dbg); |
222 | 0 | if (rv.ok()) { |
223 | 0 | fs_->counters()->dsyncs++; |
224 | 0 | } |
225 | 0 | return rv; |
226 | 0 | } |
227 | | |
228 | 0 | IOStatus Close(const IOOptions& options, IODebugContext* dbg) override { |
229 | 0 | IOStatus rv = FSDirectoryWrapper::Close(options, dbg); |
230 | 0 | if (rv.ok()) { |
231 | 0 | fs_->counters()->closes++; |
232 | 0 | fs_->counters()->dir_closes++; |
233 | 0 | closed_ = true; |
234 | 0 | } |
235 | 0 | return rv; |
236 | 0 | } |
237 | | |
238 | | IOStatus FsyncWithDirOptions(const IOOptions& options, IODebugContext* dbg, |
239 | 0 | const DirFsyncOptions& dir_options) override { |
240 | 0 | IOStatus rv = |
241 | 0 | FSDirectoryWrapper::FsyncWithDirOptions(options, dbg, dir_options); |
242 | 0 | if (rv.ok()) { |
243 | 0 | fs_->counters()->dsyncs++; |
244 | 0 | } |
245 | 0 | return rv; |
246 | 0 | } |
247 | | |
248 | 0 | ~CountedDirectory() { |
249 | 0 | if (!closed_) { |
250 | | // TODO: fix DB+CF code to use explicit Close, not rely on destructor |
251 | 0 | fs_->counters()->closes++; |
252 | 0 | fs_->counters()->dir_closes++; |
253 | 0 | } |
254 | 0 | } |
255 | | }; |
256 | | } // anonymous namespace |
257 | | |
258 | 0 | std::string FileOpCounters::PrintCounters() const { |
259 | 0 | std::stringstream ss; |
260 | 0 | ss << "Num files opened: " << opens.load(std::memory_order_relaxed) |
261 | 0 | << std::endl; |
262 | 0 | ss << "Num files deleted: " << deletes.load(std::memory_order_relaxed) |
263 | 0 | << std::endl; |
264 | 0 | ss << "Num files renamed: " << renames.load(std::memory_order_relaxed) |
265 | 0 | << std::endl; |
266 | 0 | ss << "Num Flush(): " << flushes.load(std::memory_order_relaxed) << std::endl; |
267 | 0 | ss << "Num Sync(): " << syncs.load(std::memory_order_relaxed) << std::endl; |
268 | 0 | ss << "Num Fsync(): " << fsyncs.load(std::memory_order_relaxed) << std::endl; |
269 | 0 | ss << "Num Dir Fsync(): " << dsyncs.load(std::memory_order_relaxed) |
270 | 0 | << std::endl; |
271 | 0 | ss << "Num Close(): " << closes.load(std::memory_order_relaxed) << std::endl; |
272 | 0 | ss << "Num Dir Open(): " << dir_opens.load(std::memory_order_relaxed) |
273 | 0 | << std::endl; |
274 | 0 | ss << "Num Dir Close(): " << dir_closes.load(std::memory_order_relaxed) |
275 | 0 | << std::endl; |
276 | 0 | ss << "Num Read(): " << reads.ops.load(std::memory_order_relaxed) |
277 | 0 | << std::endl; |
278 | 0 | ss << "Num Append(): " << writes.ops.load(std::memory_order_relaxed) |
279 | 0 | << std::endl; |
280 | 0 | ss << "Num bytes read: " << reads.bytes.load(std::memory_order_relaxed) |
281 | 0 | << std::endl; |
282 | 0 | ss << "Num bytes written: " << writes.bytes.load(std::memory_order_relaxed) |
283 | 0 | << std::endl; |
284 | 0 | return ss.str(); |
285 | 0 | } |
286 | | |
287 | | CountedFileSystem::CountedFileSystem(const std::shared_ptr<FileSystem>& base) |
288 | 0 | : FileSystemWrapper(base) {} |
289 | | |
290 | | IOStatus CountedFileSystem::NewSequentialFile( |
291 | | const std::string& f, const FileOptions& options, |
292 | 0 | std::unique_ptr<FSSequentialFile>* r, IODebugContext* dbg) { |
293 | 0 | std::unique_ptr<FSSequentialFile> base; |
294 | 0 | IOStatus s = target()->NewSequentialFile(f, options, &base, dbg); |
295 | 0 | if (s.ok()) { |
296 | 0 | counters_.opens++; |
297 | 0 | r->reset(new CountedSequentialFile(std::move(base), this)); |
298 | 0 | } |
299 | 0 | return s; |
300 | 0 | } |
301 | | |
302 | | IOStatus CountedFileSystem::NewRandomAccessFile( |
303 | | const std::string& f, const FileOptions& options, |
304 | 0 | std::unique_ptr<FSRandomAccessFile>* r, IODebugContext* dbg) { |
305 | 0 | std::unique_ptr<FSRandomAccessFile> base; |
306 | 0 | IOStatus s = target()->NewRandomAccessFile(f, options, &base, dbg); |
307 | 0 | if (s.ok()) { |
308 | 0 | counters_.opens++; |
309 | 0 | r->reset(new CountedRandomAccessFile(std::move(base), this)); |
310 | 0 | } |
311 | 0 | return s; |
312 | 0 | } |
313 | | |
314 | | IOStatus CountedFileSystem::NewWritableFile(const std::string& f, |
315 | | const FileOptions& options, |
316 | | std::unique_ptr<FSWritableFile>* r, |
317 | 0 | IODebugContext* dbg) { |
318 | 0 | std::unique_ptr<FSWritableFile> base; |
319 | 0 | IOStatus s = target()->NewWritableFile(f, options, &base, dbg); |
320 | 0 | if (s.ok()) { |
321 | 0 | counters_.opens++; |
322 | 0 | r->reset(new CountedWritableFile(std::move(base), this)); |
323 | 0 | } |
324 | 0 | return s; |
325 | 0 | } |
326 | | |
327 | | IOStatus CountedFileSystem::ReopenWritableFile( |
328 | | const std::string& fname, const FileOptions& options, |
329 | 0 | std::unique_ptr<FSWritableFile>* result, IODebugContext* dbg) { |
330 | 0 | std::unique_ptr<FSWritableFile> base; |
331 | 0 | IOStatus s = target()->ReopenWritableFile(fname, options, &base, dbg); |
332 | 0 | if (s.ok()) { |
333 | 0 | counters_.opens++; |
334 | 0 | result->reset(new CountedWritableFile(std::move(base), this)); |
335 | 0 | } |
336 | 0 | return s; |
337 | 0 | } |
338 | | |
339 | | IOStatus CountedFileSystem::ReuseWritableFile( |
340 | | const std::string& fname, const std::string& old_fname, |
341 | | const FileOptions& options, std::unique_ptr<FSWritableFile>* result, |
342 | 0 | IODebugContext* dbg) { |
343 | 0 | std::unique_ptr<FSWritableFile> base; |
344 | 0 | IOStatus s = |
345 | 0 | target()->ReuseWritableFile(fname, old_fname, options, &base, dbg); |
346 | 0 | if (s.ok()) { |
347 | 0 | counters_.opens++; |
348 | 0 | result->reset(new CountedWritableFile(std::move(base), this)); |
349 | 0 | } |
350 | 0 | return s; |
351 | 0 | } |
352 | | |
353 | | IOStatus CountedFileSystem::NewRandomRWFile( |
354 | | const std::string& name, const FileOptions& options, |
355 | 0 | std::unique_ptr<FSRandomRWFile>* result, IODebugContext* dbg) { |
356 | 0 | std::unique_ptr<FSRandomRWFile> base; |
357 | 0 | IOStatus s = target()->NewRandomRWFile(name, options, &base, dbg); |
358 | 0 | if (s.ok()) { |
359 | 0 | counters_.opens++; |
360 | 0 | result->reset(new CountedRandomRWFile(std::move(base), this)); |
361 | 0 | } |
362 | 0 | return s; |
363 | 0 | } |
364 | | |
365 | | IOStatus CountedFileSystem::NewDirectory(const std::string& name, |
366 | | const IOOptions& options, |
367 | | std::unique_ptr<FSDirectory>* result, |
368 | 0 | IODebugContext* dbg) { |
369 | 0 | std::unique_ptr<FSDirectory> base; |
370 | 0 | IOStatus s = target()->NewDirectory(name, options, &base, dbg); |
371 | 0 | if (s.ok()) { |
372 | 0 | counters_.opens++; |
373 | 0 | counters_.dir_opens++; |
374 | 0 | result->reset(new CountedDirectory(std::move(base), this)); |
375 | 0 | } |
376 | 0 | return s; |
377 | 0 | } |
378 | | |
379 | | } // namespace ROCKSDB_NAMESPACE |