1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/common/virtual_file_system.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/common/file_system.hpp" |
12 | #include "duckdb/common/map.hpp" |
13 | |
14 | namespace duckdb { |
15 | |
16 | // bunch of wrappers to allow registering protocol handlers |
17 | class VirtualFileSystem : public FileSystem { |
18 | public: |
19 | VirtualFileSystem(); |
20 | |
21 | unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK, |
22 | FileCompressionType compression = FileCompressionType::UNCOMPRESSED, |
23 | FileOpener *opener = nullptr) override; |
24 | |
25 | void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override { |
26 | handle.file_system.Read(handle, buffer, nr_bytes, location); |
27 | }; |
28 | |
29 | void Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override { |
30 | handle.file_system.Write(handle, buffer, nr_bytes, location); |
31 | } |
32 | |
33 | int64_t Read(FileHandle &handle, void *buffer, int64_t nr_bytes) override { |
34 | return handle.file_system.Read(handle, buffer, nr_bytes); |
35 | } |
36 | |
37 | int64_t Write(FileHandle &handle, void *buffer, int64_t nr_bytes) override { |
38 | return handle.file_system.Write(handle, buffer, nr_bytes); |
39 | } |
40 | |
41 | int64_t GetFileSize(FileHandle &handle) override { |
42 | return handle.file_system.GetFileSize(handle); |
43 | } |
44 | time_t GetLastModifiedTime(FileHandle &handle) override { |
45 | return handle.file_system.GetLastModifiedTime(handle); |
46 | } |
47 | FileType GetFileType(FileHandle &handle) override { |
48 | return handle.file_system.GetFileType(handle); |
49 | } |
50 | |
51 | void Truncate(FileHandle &handle, int64_t new_size) override { |
52 | handle.file_system.Truncate(handle, new_size); |
53 | } |
54 | |
55 | void FileSync(FileHandle &handle) override { |
56 | handle.file_system.FileSync(handle); |
57 | } |
58 | |
59 | // need to look up correct fs for this |
60 | bool DirectoryExists(const string &directory) override { |
61 | return FindFileSystem(path: directory)->DirectoryExists(directory); |
62 | } |
63 | void CreateDirectory(const string &directory) override { |
64 | FindFileSystem(path: directory)->CreateDirectory(directory); |
65 | } |
66 | |
67 | void RemoveDirectory(const string &directory) override { |
68 | FindFileSystem(path: directory)->RemoveDirectory(directory); |
69 | } |
70 | |
71 | bool ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback, |
72 | FileOpener *opener = nullptr) override { |
73 | return FindFileSystem(path: directory)->ListFiles(directory, callback, opener); |
74 | } |
75 | |
76 | void MoveFile(const string &source, const string &target) override { |
77 | FindFileSystem(path: source)->MoveFile(source, target); |
78 | } |
79 | |
80 | bool FileExists(const string &filename) override { |
81 | return FindFileSystem(path: filename)->FileExists(filename); |
82 | } |
83 | |
84 | bool IsPipe(const string &filename) override { |
85 | return FindFileSystem(path: filename)->IsPipe(filename); |
86 | } |
87 | virtual void RemoveFile(const string &filename) override { |
88 | FindFileSystem(path: filename)->RemoveFile(filename); |
89 | } |
90 | |
91 | virtual vector<string> Glob(const string &path, FileOpener *opener = nullptr) override { |
92 | return FindFileSystem(path)->Glob(path, opener); |
93 | } |
94 | |
95 | void RegisterSubSystem(unique_ptr<FileSystem> fs) override { |
96 | sub_systems.push_back(x: std::move(fs)); |
97 | } |
98 | |
99 | void UnregisterSubSystem(const string &name) override { |
100 | for (auto sub_system = sub_systems.begin(); sub_system != sub_systems.end(); sub_system++) { |
101 | if (sub_system->get()->GetName() == name) { |
102 | sub_systems.erase(position: sub_system); |
103 | return; |
104 | } |
105 | } |
106 | throw InvalidInputException("Could not find filesystem with name %s" , name); |
107 | } |
108 | |
109 | void RegisterSubSystem(FileCompressionType compression_type, unique_ptr<FileSystem> fs) override { |
110 | compressed_fs[compression_type] = std::move(fs); |
111 | } |
112 | |
113 | vector<string> ListSubSystems() override { |
114 | vector<string> names(sub_systems.size()); |
115 | for (idx_t i = 0; i < sub_systems.size(); i++) { |
116 | names[i] = sub_systems[i]->GetName(); |
117 | } |
118 | return names; |
119 | } |
120 | |
121 | std::string GetName() const override { |
122 | return "VirtualFileSystem" ; |
123 | } |
124 | |
125 | private: |
126 | FileSystem *FindFileSystem(const string &path) { |
127 | for (auto &sub_system : sub_systems) { |
128 | if (sub_system->CanHandleFile(fpath: path)) { |
129 | return sub_system.get(); |
130 | } |
131 | } |
132 | return default_fs.get(); |
133 | } |
134 | |
135 | private: |
136 | vector<unique_ptr<FileSystem>> sub_systems; |
137 | map<FileCompressionType, unique_ptr<FileSystem>> compressed_fs; |
138 | const unique_ptr<FileSystem> default_fs; |
139 | }; |
140 | |
141 | } // namespace duckdb |
142 | |