Coverage Report

Created: 2025-07-23 07:17

/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