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
14namespace duckdb {
15
16// bunch of wrappers to allow registering protocol handlers
17class VirtualFileSystem : public FileSystem {
18public:
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
125private:
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
135private:
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