Coverage Report

Created: 2025-10-26 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/env/file_system.cc
Line
Count
Source
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
//
6
#include "rocksdb/file_system.h"
7
8
#include "env/composite_env_wrapper.h"
9
#include "env/env_chroot.h"
10
#include "env/env_encryption_ctr.h"
11
#include "env/fs_readonly.h"
12
#include "env/mock_env.h"
13
#include "logging/env_logger.h"
14
#include "options/db_options.h"
15
#include "rocksdb/convenience.h"
16
#include "rocksdb/utilities/customizable_util.h"
17
#include "rocksdb/utilities/object_registry.h"
18
#include "rocksdb/utilities/options_type.h"
19
#include "util/string_util.h"
20
#include "utilities/counted_fs.h"
21
#include "utilities/env_timed.h"
22
23
namespace ROCKSDB_NAMESPACE {
24
25
149k
FileSystem::FileSystem() = default;
26
27
149k
FileSystem::~FileSystem() = default;
28
29
static int RegisterBuiltinFileSystems(ObjectLibrary& library,
30
0
                                      const std::string& /*arg*/) {
31
0
  library.AddFactory<FileSystem>(
32
0
      TimedFileSystem::kClassName(),
33
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
34
0
         std::string* /* errmsg */) {
35
0
        guard->reset(new TimedFileSystem(nullptr));
36
0
        return guard->get();
37
0
      });
38
0
  library.AddFactory<FileSystem>(
39
0
      ReadOnlyFileSystem::kClassName(),
40
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
41
0
         std::string* /* errmsg */) {
42
0
        guard->reset(new ReadOnlyFileSystem(nullptr));
43
0
        return guard->get();
44
0
      });
45
0
  library.AddFactory<FileSystem>(
46
0
      EncryptedFileSystem::kClassName(),
47
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
48
0
         std::string* errmsg) {
49
0
        Status s = NewEncryptedFileSystemImpl(nullptr, nullptr, guard);
50
0
        if (!s.ok()) {
51
0
          *errmsg = s.ToString();
52
0
        }
53
0
        return guard->get();
54
0
      });
55
0
  library.AddFactory<FileSystem>(
56
0
      CountedFileSystem::kClassName(),
57
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
58
0
         std::string* /*errmsg*/) {
59
0
        guard->reset(new CountedFileSystem(FileSystem::Default()));
60
0
        return guard->get();
61
0
      });
62
0
  library.AddFactory<FileSystem>(
63
0
      MockFileSystem::kClassName(),
64
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
65
0
         std::string* /*errmsg*/) {
66
0
        guard->reset(new MockFileSystem(SystemClock::Default()));
67
0
        return guard->get();
68
0
      });
69
0
#ifndef OS_WIN
70
0
  library.AddFactory<FileSystem>(
71
0
      ChrootFileSystem::kClassName(),
72
0
      [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
73
0
         std::string* /* errmsg */) {
74
0
        guard->reset(new ChrootFileSystem(nullptr, ""));
75
0
        return guard->get();
76
0
      });
77
0
#endif  // OS_WIN
78
0
  size_t num_types;
79
0
  return static_cast<int>(library.GetFactoryCount(&num_types));
80
0
}
81
82
Status FileSystem::CreateFromString(const ConfigOptions& config_options,
83
                                    const std::string& value,
84
0
                                    std::shared_ptr<FileSystem>* result) {
85
0
  auto default_fs = FileSystem::Default();
86
0
  if (default_fs->IsInstanceOf(value)) {
87
0
    *result = default_fs;
88
0
    return Status::OK();
89
0
  } else {
90
0
    static std::once_flag once;
91
0
    std::call_once(once, [&]() {
92
0
      RegisterBuiltinFileSystems(*(ObjectLibrary::Default().get()), "");
93
0
    });
94
0
    return LoadSharedObject<FileSystem>(config_options, value, result);
95
0
  }
96
0
}
97
98
IOStatus FileSystem::ReuseWritableFile(const std::string& fname,
99
                                       const std::string& old_fname,
100
                                       const FileOptions& opts,
101
                                       std::unique_ptr<FSWritableFile>* result,
102
0
                                       IODebugContext* dbg) {
103
0
  IOStatus s = RenameFile(old_fname, fname, opts.io_options, dbg);
104
0
  if (!s.ok()) {
105
0
    return s;
106
0
  }
107
0
  return NewWritableFile(fname, opts, result, dbg);
108
0
}
109
110
IOStatus FileSystem::NewLogger(const std::string& fname,
111
                               const IOOptions& io_opts,
112
                               std::shared_ptr<Logger>* result,
113
57.6k
                               IODebugContext* dbg) {
114
57.6k
  FileOptions options;
115
57.6k
  options.io_options = io_opts;
116
  // TODO: Tune the buffer size.
117
57.6k
  options.writable_file_max_buffer_size = 1024 * 1024;
118
57.6k
  std::unique_ptr<FSWritableFile> writable_file;
119
57.6k
  const IOStatus status = NewWritableFile(fname, options, &writable_file, dbg);
120
57.6k
  if (!status.ok()) {
121
0
    return status;
122
0
  }
123
124
57.6k
  *result = std::make_shared<EnvLogger>(std::move(writable_file), fname,
125
57.6k
                                        options, Env::Default());
126
57.6k
  return IOStatus::OK();
127
57.6k
}
128
129
FileOptions FileSystem::OptimizeForLogRead(
130
39.2k
    const FileOptions& file_options) const {
131
39.2k
  FileOptions optimized_file_options(file_options);
132
39.2k
  optimized_file_options.use_direct_reads = false;
133
39.2k
  return optimized_file_options;
134
39.2k
}
135
136
FileOptions FileSystem::OptimizeForManifestRead(
137
48.4k
    const FileOptions& file_options) const {
138
48.4k
  FileOptions optimized_file_options(file_options);
139
48.4k
  optimized_file_options.use_direct_reads = false;
140
48.4k
  return optimized_file_options;
141
48.4k
}
142
143
FileOptions FileSystem::OptimizeForLogWrite(const FileOptions& file_options,
144
0
                                            const DBOptions& db_options) const {
145
0
  FileOptions optimized_file_options(file_options);
146
0
  optimized_file_options.bytes_per_sync = db_options.wal_bytes_per_sync;
147
0
  optimized_file_options.writable_file_max_buffer_size =
148
0
      db_options.writable_file_max_buffer_size;
149
0
  return optimized_file_options;
150
0
}
151
152
FileOptions FileSystem::OptimizeForManifestWrite(
153
0
    const FileOptions& file_options) const {
154
0
  return file_options;
155
0
}
156
157
FileOptions FileSystem::OptimizeForCompactionTableWrite(
158
    const FileOptions& file_options,
159
48.4k
    const ImmutableDBOptions& db_options) const {
160
48.4k
  FileOptions optimized_file_options(file_options);
161
48.4k
  optimized_file_options.use_direct_writes =
162
48.4k
      db_options.use_direct_io_for_flush_and_compaction;
163
48.4k
  return optimized_file_options;
164
48.4k
}
165
166
FileOptions FileSystem::OptimizeForCompactionTableRead(
167
    const FileOptions& file_options,
168
0
    const ImmutableDBOptions& db_options) const {
169
0
  FileOptions optimized_file_options(file_options);
170
0
  optimized_file_options.use_direct_reads = db_options.use_direct_reads;
171
0
  return optimized_file_options;
172
0
}
173
174
FileOptions FileSystem::OptimizeForBlobFileRead(
175
    const FileOptions& file_options,
176
0
    const ImmutableDBOptions& db_options) const {
177
0
  FileOptions optimized_file_options(file_options);
178
0
  optimized_file_options.use_direct_reads = db_options.use_direct_reads;
179
0
  return optimized_file_options;
180
0
}
181
182
IOStatus WriteStringToFile(FileSystem* fs, const Slice& data,
183
                           const std::string& fname, bool should_sync,
184
                           const IOOptions& io_options,
185
66.9k
                           const FileOptions& file_options) {
186
66.9k
  std::unique_ptr<FSWritableFile> file;
187
66.9k
  IOStatus s = fs->NewWritableFile(fname, file_options, &file, nullptr);
188
66.9k
  if (!s.ok()) {
189
0
    return s;
190
0
  }
191
66.9k
  s = file->Append(data, io_options, nullptr);
192
66.9k
  if (s.ok() && should_sync) {
193
66.9k
    s = file->Sync(io_options, nullptr);
194
66.9k
  }
195
66.9k
  if (!s.ok()) {
196
0
    fs->DeleteFile(fname, io_options, nullptr);
197
0
  }
198
66.9k
  return s;
199
66.9k
}
200
201
IOStatus ReadFileToString(FileSystem* fs, const std::string& fname,
202
0
                          std::string* data) {
203
0
  return ReadFileToString(fs, fname, IOOptions(), data);
204
0
}
205
206
IOStatus ReadFileToString(FileSystem* fs, const std::string& fname,
207
87.6k
                          const IOOptions& opts, std::string* data) {
208
87.6k
  FileOptions soptions;
209
87.6k
  data->clear();
210
87.6k
  std::unique_ptr<FSSequentialFile> file;
211
87.6k
  IOStatus s = status_to_io_status(
212
87.6k
      fs->NewSequentialFile(fname, soptions, &file, nullptr));
213
87.6k
  if (!s.ok()) {
214
0
    return s;
215
0
  }
216
87.6k
  static const int kBufferSize = 8192;
217
87.6k
  char* space = new char[kBufferSize];
218
175k
  while (true) {
219
175k
    Slice fragment;
220
175k
    s = file->Read(kBufferSize, opts, &fragment, space, nullptr);
221
175k
    if (!s.ok()) {
222
0
      break;
223
0
    }
224
175k
    data->append(fragment.data(), fragment.size());
225
175k
    if (fragment.empty()) {
226
87.6k
      break;
227
87.6k
    }
228
175k
  }
229
87.6k
  delete[] space;
230
87.6k
  return s;
231
87.6k
}
232
233
namespace {
234
static std::unordered_map<std::string, OptionTypeInfo> fs_wrapper_type_info = {
235
    {"target",
236
     OptionTypeInfo::AsCustomSharedPtr<FileSystem>(
237
         0, OptionVerificationType::kByName, OptionTypeFlags::kDontSerialize)},
238
};
239
}  // namespace
240
FileSystemWrapper::FileSystemWrapper(const std::shared_ptr<FileSystem>& t)
241
149k
    : target_(t) {
242
149k
  RegisterOptions("", &target_, &fs_wrapper_type_info);
243
149k
}
244
245
0
Status FileSystemWrapper::PrepareOptions(const ConfigOptions& options) {
246
0
  if (target_ == nullptr) {
247
0
    target_ = FileSystem::Default();
248
0
  }
249
0
  return FileSystem::PrepareOptions(options);
250
0
}
251
252
std::string FileSystemWrapper::SerializeOptions(
253
0
    const ConfigOptions& config_options, const std::string& header) const {
254
0
  auto parent = FileSystem::SerializeOptions(config_options, "");
255
0
  if (config_options.IsShallow() || target_ == nullptr ||
256
0
      target_->IsInstanceOf(FileSystem::kDefaultName())) {
257
0
    return parent;
258
0
  } else {
259
0
    std::string result = header;
260
0
    if (!StartsWith(parent, OptionTypeInfo::kIdPropName())) {
261
0
      result.append(OptionTypeInfo::kIdPropName()).append("=");
262
0
    }
263
0
    result.append(parent);
264
0
    if (!EndsWith(result, config_options.delimiter)) {
265
0
      result.append(config_options.delimiter);
266
0
    }
267
0
    result.append("target=").append(target_->ToString(config_options));
268
0
    return result;
269
0
  }
270
0
}
271
272
0
DirFsyncOptions::DirFsyncOptions() { reason = kDefault; }
273
274
149k
DirFsyncOptions::DirFsyncOptions(std::string file_renamed_new_name) {
275
149k
  reason = kFileRenamed;
276
149k
  renamed_new_name = file_renamed_new_name;
277
149k
}
278
279
4.10k
DirFsyncOptions::DirFsyncOptions(FsyncReason fsync_reason) {
280
  assert(fsync_reason != kFileRenamed);
281
4.10k
  reason = fsync_reason;
282
4.10k
}
283
}  // namespace ROCKSDB_NAMESPACE