1 // Copyright (c) Facebook, Inc. and its affiliates. 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 #ifndef ROCKSDB_LITE
7
8 #include "env/fs_remap.h"
9
10 namespace ROCKSDB_NAMESPACE {
11
RemapFileSystem(const std::shared_ptr<FileSystem> & base)12 RemapFileSystem::RemapFileSystem(const std::shared_ptr<FileSystem>& base)
13 : FileSystemWrapper(base) {}
14
EncodePathWithNewBasename(const std::string & path)15 std::pair<IOStatus, std::string> RemapFileSystem::EncodePathWithNewBasename(
16 const std::string& path) {
17 // No difference by default
18 return EncodePath(path);
19 }
20
RegisterDbPaths(const std::vector<std::string> & paths)21 Status RemapFileSystem::RegisterDbPaths(const std::vector<std::string>& paths) {
22 std::vector<std::string> encoded_paths;
23 encoded_paths.reserve(paths.size());
24 for (auto& path : paths) {
25 auto status_and_enc_path = EncodePathWithNewBasename(path);
26 if (!status_and_enc_path.first.ok()) {
27 return status_and_enc_path.first;
28 }
29 encoded_paths.emplace_back(status_and_enc_path.second);
30 }
31 return FileSystemWrapper::RegisterDbPaths(encoded_paths);
32 }
33
UnregisterDbPaths(const std::vector<std::string> & paths)34 Status RemapFileSystem::UnregisterDbPaths(
35 const std::vector<std::string>& paths) {
36 std::vector<std::string> encoded_paths;
37 encoded_paths.reserve(paths.size());
38 for (auto& path : paths) {
39 auto status_and_enc_path = EncodePathWithNewBasename(path);
40 if (!status_and_enc_path.first.ok()) {
41 return status_and_enc_path.first;
42 }
43 encoded_paths.emplace_back(status_and_enc_path.second);
44 }
45 return FileSystemWrapper::UnregisterDbPaths(encoded_paths);
46 }
47
NewSequentialFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSSequentialFile> * result,IODebugContext * dbg)48 IOStatus RemapFileSystem::NewSequentialFile(
49 const std::string& fname, const FileOptions& options,
50 std::unique_ptr<FSSequentialFile>* result, IODebugContext* dbg) {
51 auto status_and_enc_path = EncodePathWithNewBasename(fname);
52 if (!status_and_enc_path.first.ok()) {
53 return status_and_enc_path.first;
54 }
55 return FileSystemWrapper::NewSequentialFile(status_and_enc_path.second,
56 options, result, dbg);
57 }
58
NewRandomAccessFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomAccessFile> * result,IODebugContext * dbg)59 IOStatus RemapFileSystem::NewRandomAccessFile(
60 const std::string& fname, const FileOptions& options,
61 std::unique_ptr<FSRandomAccessFile>* result, IODebugContext* dbg) {
62 auto status_and_enc_path = EncodePathWithNewBasename(fname);
63 if (!status_and_enc_path.first.ok()) {
64 return status_and_enc_path.first;
65 }
66 return FileSystemWrapper::NewRandomAccessFile(status_and_enc_path.second,
67 options, result, dbg);
68 }
69
NewWritableFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)70 IOStatus RemapFileSystem::NewWritableFile(
71 const std::string& fname, const FileOptions& options,
72 std::unique_ptr<FSWritableFile>* result, IODebugContext* dbg) {
73 auto status_and_enc_path = EncodePathWithNewBasename(fname);
74 if (!status_and_enc_path.first.ok()) {
75 return status_and_enc_path.first;
76 }
77 return FileSystemWrapper::NewWritableFile(status_and_enc_path.second, options,
78 result, dbg);
79 }
80
ReuseWritableFile(const std::string & fname,const std::string & old_fname,const FileOptions & options,std::unique_ptr<FSWritableFile> * result,IODebugContext * dbg)81 IOStatus RemapFileSystem::ReuseWritableFile(
82 const std::string& fname, const std::string& old_fname,
83 const FileOptions& options, std::unique_ptr<FSWritableFile>* result,
84 IODebugContext* dbg) {
85 auto status_and_enc_path = EncodePathWithNewBasename(fname);
86 if (!status_and_enc_path.first.ok()) {
87 return status_and_enc_path.first;
88 }
89 auto status_and_old_enc_path = EncodePath(old_fname);
90 if (!status_and_old_enc_path.first.ok()) {
91 return status_and_old_enc_path.first;
92 }
93 return FileSystemWrapper::ReuseWritableFile(status_and_old_enc_path.second,
94 status_and_old_enc_path.second,
95 options, result, dbg);
96 }
97
NewRandomRWFile(const std::string & fname,const FileOptions & options,std::unique_ptr<FSRandomRWFile> * result,IODebugContext * dbg)98 IOStatus RemapFileSystem::NewRandomRWFile(
99 const std::string& fname, const FileOptions& options,
100 std::unique_ptr<FSRandomRWFile>* result, IODebugContext* dbg) {
101 auto status_and_enc_path = EncodePathWithNewBasename(fname);
102 if (!status_and_enc_path.first.ok()) {
103 return status_and_enc_path.first;
104 }
105 return FileSystemWrapper::NewRandomRWFile(status_and_enc_path.second, options,
106 result, dbg);
107 }
108
NewDirectory(const std::string & dir,const IOOptions & options,std::unique_ptr<FSDirectory> * result,IODebugContext * dbg)109 IOStatus RemapFileSystem::NewDirectory(const std::string& dir,
110 const IOOptions& options,
111 std::unique_ptr<FSDirectory>* result,
112 IODebugContext* dbg) {
113 auto status_and_enc_path = EncodePathWithNewBasename(dir);
114 if (!status_and_enc_path.first.ok()) {
115 return status_and_enc_path.first;
116 }
117 return FileSystemWrapper::NewDirectory(status_and_enc_path.second, options,
118 result, dbg);
119 }
120
FileExists(const std::string & fname,const IOOptions & options,IODebugContext * dbg)121 IOStatus RemapFileSystem::FileExists(const std::string& fname,
122 const IOOptions& options,
123 IODebugContext* dbg) {
124 auto status_and_enc_path = EncodePathWithNewBasename(fname);
125 if (!status_and_enc_path.first.ok()) {
126 return status_and_enc_path.first;
127 }
128 return FileSystemWrapper::FileExists(status_and_enc_path.second, options,
129 dbg);
130 }
131
GetChildren(const std::string & dir,const IOOptions & options,std::vector<std::string> * result,IODebugContext * dbg)132 IOStatus RemapFileSystem::GetChildren(const std::string& dir,
133 const IOOptions& options,
134 std::vector<std::string>* result,
135 IODebugContext* dbg) {
136 auto status_and_enc_path = EncodePath(dir);
137 if (!status_and_enc_path.first.ok()) {
138 return status_and_enc_path.first;
139 }
140 return FileSystemWrapper::GetChildren(status_and_enc_path.second, options,
141 result, dbg);
142 }
143
GetChildrenFileAttributes(const std::string & dir,const IOOptions & options,std::vector<FileAttributes> * result,IODebugContext * dbg)144 IOStatus RemapFileSystem::GetChildrenFileAttributes(
145 const std::string& dir, const IOOptions& options,
146 std::vector<FileAttributes>* result, IODebugContext* dbg) {
147 auto status_and_enc_path = EncodePath(dir);
148 if (!status_and_enc_path.first.ok()) {
149 return status_and_enc_path.first;
150 }
151 return FileSystemWrapper::GetChildrenFileAttributes(
152 status_and_enc_path.second, options, result, dbg);
153 }
154
DeleteFile(const std::string & fname,const IOOptions & options,IODebugContext * dbg)155 IOStatus RemapFileSystem::DeleteFile(const std::string& fname,
156 const IOOptions& options,
157 IODebugContext* dbg) {
158 auto status_and_enc_path = EncodePath(fname);
159 if (!status_and_enc_path.first.ok()) {
160 return status_and_enc_path.first;
161 }
162 return FileSystemWrapper::DeleteFile(status_and_enc_path.second, options,
163 dbg);
164 }
165
CreateDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)166 IOStatus RemapFileSystem::CreateDir(const std::string& dirname,
167 const IOOptions& options,
168 IODebugContext* dbg) {
169 auto status_and_enc_path = EncodePathWithNewBasename(dirname);
170 if (!status_and_enc_path.first.ok()) {
171 return status_and_enc_path.first;
172 }
173 return FileSystemWrapper::CreateDir(status_and_enc_path.second, options, dbg);
174 }
175
CreateDirIfMissing(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)176 IOStatus RemapFileSystem::CreateDirIfMissing(const std::string& dirname,
177 const IOOptions& options,
178 IODebugContext* dbg) {
179 auto status_and_enc_path = EncodePathWithNewBasename(dirname);
180 if (!status_and_enc_path.first.ok()) {
181 return status_and_enc_path.first;
182 }
183 return FileSystemWrapper::CreateDirIfMissing(status_and_enc_path.second,
184 options, dbg);
185 }
186
DeleteDir(const std::string & dirname,const IOOptions & options,IODebugContext * dbg)187 IOStatus RemapFileSystem::DeleteDir(const std::string& dirname,
188 const IOOptions& options,
189 IODebugContext* dbg) {
190 auto status_and_enc_path = EncodePath(dirname);
191 if (!status_and_enc_path.first.ok()) {
192 return status_and_enc_path.first;
193 }
194 return FileSystemWrapper::DeleteDir(status_and_enc_path.second, options, dbg);
195 }
196
GetFileSize(const std::string & fname,const IOOptions & options,uint64_t * file_size,IODebugContext * dbg)197 IOStatus RemapFileSystem::GetFileSize(const std::string& fname,
198 const IOOptions& options,
199 uint64_t* file_size,
200 IODebugContext* dbg) {
201 auto status_and_enc_path = EncodePath(fname);
202 if (!status_and_enc_path.first.ok()) {
203 return status_and_enc_path.first;
204 }
205 return FileSystemWrapper::GetFileSize(status_and_enc_path.second, options,
206 file_size, dbg);
207 }
208
GetFileModificationTime(const std::string & fname,const IOOptions & options,uint64_t * file_mtime,IODebugContext * dbg)209 IOStatus RemapFileSystem::GetFileModificationTime(const std::string& fname,
210 const IOOptions& options,
211 uint64_t* file_mtime,
212 IODebugContext* dbg) {
213 auto status_and_enc_path = EncodePath(fname);
214 if (!status_and_enc_path.first.ok()) {
215 return status_and_enc_path.first;
216 }
217 return FileSystemWrapper::GetFileModificationTime(status_and_enc_path.second,
218 options, file_mtime, dbg);
219 }
220
IsDirectory(const std::string & path,const IOOptions & options,bool * is_dir,IODebugContext * dbg)221 IOStatus RemapFileSystem::IsDirectory(const std::string& path,
222 const IOOptions& options, bool* is_dir,
223 IODebugContext* dbg) {
224 auto status_and_enc_path = EncodePath(path);
225 if (!status_and_enc_path.first.ok()) {
226 return status_and_enc_path.first;
227 }
228 return FileSystemWrapper::IsDirectory(status_and_enc_path.second, options,
229 is_dir, dbg);
230 }
231
RenameFile(const std::string & src,const std::string & dest,const IOOptions & options,IODebugContext * dbg)232 IOStatus RemapFileSystem::RenameFile(const std::string& src,
233 const std::string& dest,
234 const IOOptions& options,
235 IODebugContext* dbg) {
236 auto status_and_src_enc_path = EncodePath(src);
237 if (!status_and_src_enc_path.first.ok()) {
238 return status_and_src_enc_path.first;
239 }
240 auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
241 if (!status_and_dest_enc_path.first.ok()) {
242 return status_and_dest_enc_path.first;
243 }
244 return FileSystemWrapper::RenameFile(status_and_src_enc_path.second,
245 status_and_dest_enc_path.second, options,
246 dbg);
247 }
248
LinkFile(const std::string & src,const std::string & dest,const IOOptions & options,IODebugContext * dbg)249 IOStatus RemapFileSystem::LinkFile(const std::string& src,
250 const std::string& dest,
251 const IOOptions& options,
252 IODebugContext* dbg) {
253 auto status_and_src_enc_path = EncodePath(src);
254 if (!status_and_src_enc_path.first.ok()) {
255 return status_and_src_enc_path.first;
256 }
257 auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
258 if (!status_and_dest_enc_path.first.ok()) {
259 return status_and_dest_enc_path.first;
260 }
261 return FileSystemWrapper::LinkFile(status_and_src_enc_path.second,
262 status_and_dest_enc_path.second, options,
263 dbg);
264 }
265
LockFile(const std::string & fname,const IOOptions & options,FileLock ** lock,IODebugContext * dbg)266 IOStatus RemapFileSystem::LockFile(const std::string& fname,
267 const IOOptions& options, FileLock** lock,
268 IODebugContext* dbg) {
269 auto status_and_enc_path = EncodePathWithNewBasename(fname);
270 if (!status_and_enc_path.first.ok()) {
271 return status_and_enc_path.first;
272 }
273 // FileLock subclasses may store path (e.g., PosixFileLock stores it). We
274 // can skip stripping the chroot directory from this path because callers
275 // shouldn't use it.
276 return FileSystemWrapper::LockFile(status_and_enc_path.second, options, lock,
277 dbg);
278 }
279
NewLogger(const std::string & fname,const IOOptions & options,std::shared_ptr<Logger> * result,IODebugContext * dbg)280 IOStatus RemapFileSystem::NewLogger(const std::string& fname,
281 const IOOptions& options,
282 std::shared_ptr<Logger>* result,
283 IODebugContext* dbg) {
284 auto status_and_enc_path = EncodePathWithNewBasename(fname);
285 if (!status_and_enc_path.first.ok()) {
286 return status_and_enc_path.first;
287 }
288 return FileSystemWrapper::NewLogger(status_and_enc_path.second, options,
289 result, dbg);
290 }
291
GetAbsolutePath(const std::string & db_path,const IOOptions & options,std::string * output_path,IODebugContext * dbg)292 IOStatus RemapFileSystem::GetAbsolutePath(const std::string& db_path,
293 const IOOptions& options,
294 std::string* output_path,
295 IODebugContext* dbg) {
296 auto status_and_enc_path = EncodePath(db_path);
297 if (!status_and_enc_path.first.ok()) {
298 return status_and_enc_path.first;
299 }
300 return FileSystemWrapper::GetAbsolutePath(status_and_enc_path.second, options,
301 output_path, dbg);
302 }
303
304 } // namespace ROCKSDB_NAMESPACE
305
306 #endif // ROCKSDB_LITE
307