file_system.cc 9.6 KB

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