]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
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). | |
7c673cae FG |
5 | // |
6 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. | |
7 | // Use of this source code is governed by a BSD-style license that can be | |
8 | // found in the LICENSE file. See the AUTHORS file for names of contributors. | |
9 | ||
10 | #include "rocksdb/env.h" | |
11 | ||
12 | #include <thread> | |
1e59de90 | 13 | |
f67539c2 | 14 | #include "env/composite_env_wrapper.h" |
1e59de90 TL |
15 | #include "env/emulated_clock.h" |
16 | #include "env/mock_env.h" | |
17 | #include "env/unique_id_gen.h" | |
f67539c2 TL |
18 | #include "logging/env_logger.h" |
19 | #include "memory/arena.h" | |
7c673cae FG |
20 | #include "options/db_options.h" |
21 | #include "port/port.h" | |
1e59de90 | 22 | #include "rocksdb/convenience.h" |
7c673cae | 23 | #include "rocksdb/options.h" |
1e59de90 TL |
24 | #include "rocksdb/system_clock.h" |
25 | #include "rocksdb/utilities/customizable_util.h" | |
f67539c2 | 26 | #include "rocksdb/utilities/object_registry.h" |
1e59de90 | 27 | #include "rocksdb/utilities/options_type.h" |
7c673cae FG |
28 | #include "util/autovector.h" |
29 | ||
f67539c2 | 30 | namespace ROCKSDB_NAMESPACE { |
1e59de90 TL |
31 | namespace { |
32 | #ifndef ROCKSDB_LITE | |
33 | static int RegisterBuiltinEnvs(ObjectLibrary& library, | |
34 | const std::string& /*arg*/) { | |
35 | library.AddFactory<Env>(MockEnv::kClassName(), [](const std::string& /*uri*/, | |
36 | std::unique_ptr<Env>* guard, | |
37 | std::string* /* errmsg */) { | |
38 | guard->reset(MockEnv::Create(Env::Default())); | |
39 | return guard->get(); | |
40 | }); | |
41 | library.AddFactory<Env>( | |
42 | CompositeEnvWrapper::kClassName(), | |
43 | [](const std::string& /*uri*/, std::unique_ptr<Env>* guard, | |
44 | std::string* /* errmsg */) { | |
45 | guard->reset(new CompositeEnvWrapper(Env::Default())); | |
46 | return guard->get(); | |
47 | }); | |
48 | size_t num_types; | |
49 | return static_cast<int>(library.GetFactoryCount(&num_types)); | |
50 | } | |
51 | #endif // ROCKSDB_LITE | |
52 | ||
53 | static void RegisterSystemEnvs() { | |
54 | #ifndef ROCKSDB_LITE | |
55 | static std::once_flag loaded; | |
56 | std::call_once(loaded, [&]() { | |
57 | RegisterBuiltinEnvs(*(ObjectLibrary::Default().get()), ""); | |
58 | }); | |
59 | #endif // ROCKSDB_LITE | |
60 | } | |
61 | ||
62 | class LegacySystemClock : public SystemClock { | |
63 | private: | |
64 | Env* env_; | |
65 | ||
66 | public: | |
67 | explicit LegacySystemClock(Env* env) : env_(env) {} | |
68 | const char* Name() const override { return "LegacySystemClock"; } | |
69 | ||
70 | // Returns the number of micro-seconds since some fixed point in time. | |
71 | // It is often used as system time such as in GenericRateLimiter | |
72 | // and other places so a port needs to return system time in order to work. | |
73 | uint64_t NowMicros() override { return env_->NowMicros(); } | |
74 | ||
75 | // Returns the number of nano-seconds since some fixed point in time. Only | |
76 | // useful for computing deltas of time in one run. | |
77 | // Default implementation simply relies on NowMicros. | |
78 | // In platform-specific implementations, NowNanos() should return time points | |
79 | // that are MONOTONIC. | |
80 | uint64_t NowNanos() override { return env_->NowNanos(); } | |
81 | ||
82 | uint64_t CPUMicros() override { return CPUNanos() / 1000; } | |
83 | uint64_t CPUNanos() override { return env_->NowCPUNanos(); } | |
84 | ||
85 | // Sleep/delay the thread for the prescribed number of micro-seconds. | |
86 | void SleepForMicroseconds(int micros) override { | |
87 | env_->SleepForMicroseconds(micros); | |
88 | } | |
89 | ||
90 | // Get the number of seconds since the Epoch, 1970-01-01 00:00:00 (UTC). | |
91 | // Only overwrites *unix_time on success. | |
92 | Status GetCurrentTime(int64_t* unix_time) override { | |
93 | return env_->GetCurrentTime(unix_time); | |
94 | } | |
95 | // Converts seconds-since-Jan-01-1970 to a printable string | |
96 | std::string TimeToString(uint64_t time) override { | |
97 | return env_->TimeToString(time); | |
98 | } | |
99 | ||
100 | #ifndef ROCKSDB_LITE | |
101 | std::string SerializeOptions(const ConfigOptions& /*config_options*/, | |
102 | const std::string& /*prefix*/) const override { | |
103 | // We do not want the LegacySystemClock to appear in the serialized output. | |
104 | // This clock is an internal class for those who do not implement one and | |
105 | // would be part of the Env. As such, do not serialize it here. | |
106 | return ""; | |
107 | } | |
108 | #endif // ROCKSDB_LITE | |
109 | }; | |
110 | ||
111 | class LegacySequentialFileWrapper : public FSSequentialFile { | |
112 | public: | |
113 | explicit LegacySequentialFileWrapper( | |
114 | std::unique_ptr<SequentialFile>&& _target) | |
115 | : target_(std::move(_target)) {} | |
116 | ||
117 | IOStatus Read(size_t n, const IOOptions& /*options*/, Slice* result, | |
118 | char* scratch, IODebugContext* /*dbg*/) override { | |
119 | return status_to_io_status(target_->Read(n, result, scratch)); | |
120 | } | |
121 | IOStatus Skip(uint64_t n) override { | |
122 | return status_to_io_status(target_->Skip(n)); | |
123 | } | |
124 | bool use_direct_io() const override { return target_->use_direct_io(); } | |
125 | size_t GetRequiredBufferAlignment() const override { | |
126 | return target_->GetRequiredBufferAlignment(); | |
127 | } | |
128 | IOStatus InvalidateCache(size_t offset, size_t length) override { | |
129 | return status_to_io_status(target_->InvalidateCache(offset, length)); | |
130 | } | |
131 | IOStatus PositionedRead(uint64_t offset, size_t n, | |
132 | const IOOptions& /*options*/, Slice* result, | |
133 | char* scratch, IODebugContext* /*dbg*/) override { | |
134 | return status_to_io_status( | |
135 | target_->PositionedRead(offset, n, result, scratch)); | |
136 | } | |
137 | ||
138 | private: | |
139 | std::unique_ptr<SequentialFile> target_; | |
140 | }; | |
141 | ||
142 | class LegacyRandomAccessFileWrapper : public FSRandomAccessFile { | |
143 | public: | |
144 | explicit LegacyRandomAccessFileWrapper( | |
145 | std::unique_ptr<RandomAccessFile>&& target) | |
146 | : target_(std::move(target)) {} | |
147 | ||
148 | IOStatus Read(uint64_t offset, size_t n, const IOOptions& /*options*/, | |
149 | Slice* result, char* scratch, | |
150 | IODebugContext* /*dbg*/) const override { | |
151 | return status_to_io_status(target_->Read(offset, n, result, scratch)); | |
152 | } | |
153 | ||
154 | IOStatus MultiRead(FSReadRequest* fs_reqs, size_t num_reqs, | |
155 | const IOOptions& /*options*/, | |
156 | IODebugContext* /*dbg*/) override { | |
157 | std::vector<ReadRequest> reqs; | |
158 | Status status; | |
159 | ||
160 | reqs.reserve(num_reqs); | |
161 | for (size_t i = 0; i < num_reqs; ++i) { | |
162 | ReadRequest req; | |
163 | ||
164 | req.offset = fs_reqs[i].offset; | |
165 | req.len = fs_reqs[i].len; | |
166 | req.scratch = fs_reqs[i].scratch; | |
167 | req.status = Status::OK(); | |
168 | ||
169 | reqs.emplace_back(req); | |
170 | } | |
171 | status = target_->MultiRead(reqs.data(), num_reqs); | |
172 | for (size_t i = 0; i < num_reqs; ++i) { | |
173 | fs_reqs[i].result = reqs[i].result; | |
174 | fs_reqs[i].status = status_to_io_status(std::move(reqs[i].status)); | |
175 | } | |
176 | return status_to_io_status(std::move(status)); | |
177 | } | |
178 | ||
179 | IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& /*options*/, | |
180 | IODebugContext* /*dbg*/) override { | |
181 | return status_to_io_status(target_->Prefetch(offset, n)); | |
182 | } | |
183 | size_t GetUniqueId(char* id, size_t max_size) const override { | |
184 | return target_->GetUniqueId(id, max_size); | |
185 | } | |
186 | void Hint(AccessPattern pattern) override { | |
187 | target_->Hint((RandomAccessFile::AccessPattern)pattern); | |
188 | } | |
189 | bool use_direct_io() const override { return target_->use_direct_io(); } | |
190 | size_t GetRequiredBufferAlignment() const override { | |
191 | return target_->GetRequiredBufferAlignment(); | |
192 | } | |
193 | IOStatus InvalidateCache(size_t offset, size_t length) override { | |
194 | return status_to_io_status(target_->InvalidateCache(offset, length)); | |
195 | } | |
196 | ||
197 | private: | |
198 | std::unique_ptr<RandomAccessFile> target_; | |
199 | }; | |
200 | ||
201 | class LegacyRandomRWFileWrapper : public FSRandomRWFile { | |
202 | public: | |
203 | explicit LegacyRandomRWFileWrapper(std::unique_ptr<RandomRWFile>&& target) | |
204 | : target_(std::move(target)) {} | |
205 | ||
206 | bool use_direct_io() const override { return target_->use_direct_io(); } | |
207 | size_t GetRequiredBufferAlignment() const override { | |
208 | return target_->GetRequiredBufferAlignment(); | |
209 | } | |
210 | IOStatus Write(uint64_t offset, const Slice& data, | |
211 | const IOOptions& /*options*/, | |
212 | IODebugContext* /*dbg*/) override { | |
213 | return status_to_io_status(target_->Write(offset, data)); | |
214 | } | |
215 | IOStatus Read(uint64_t offset, size_t n, const IOOptions& /*options*/, | |
216 | Slice* result, char* scratch, | |
217 | IODebugContext* /*dbg*/) const override { | |
218 | return status_to_io_status(target_->Read(offset, n, result, scratch)); | |
219 | } | |
220 | IOStatus Flush(const IOOptions& /*options*/, | |
221 | IODebugContext* /*dbg*/) override { | |
222 | return status_to_io_status(target_->Flush()); | |
223 | } | |
224 | IOStatus Sync(const IOOptions& /*options*/, | |
225 | IODebugContext* /*dbg*/) override { | |
226 | return status_to_io_status(target_->Sync()); | |
227 | } | |
228 | IOStatus Fsync(const IOOptions& /*options*/, | |
229 | IODebugContext* /*dbg*/) override { | |
230 | return status_to_io_status(target_->Fsync()); | |
231 | } | |
232 | IOStatus Close(const IOOptions& /*options*/, | |
233 | IODebugContext* /*dbg*/) override { | |
234 | return status_to_io_status(target_->Close()); | |
235 | } | |
236 | ||
237 | private: | |
238 | std::unique_ptr<RandomRWFile> target_; | |
239 | }; | |
240 | ||
241 | class LegacyWritableFileWrapper : public FSWritableFile { | |
242 | public: | |
243 | explicit LegacyWritableFileWrapper(std::unique_ptr<WritableFile>&& _target) | |
244 | : target_(std::move(_target)) {} | |
245 | ||
246 | IOStatus Append(const Slice& data, const IOOptions& /*options*/, | |
247 | IODebugContext* /*dbg*/) override { | |
248 | return status_to_io_status(target_->Append(data)); | |
249 | } | |
250 | IOStatus Append(const Slice& data, const IOOptions& /*options*/, | |
251 | const DataVerificationInfo& /*verification_info*/, | |
252 | IODebugContext* /*dbg*/) override { | |
253 | return status_to_io_status(target_->Append(data)); | |
254 | } | |
255 | IOStatus PositionedAppend(const Slice& data, uint64_t offset, | |
256 | const IOOptions& /*options*/, | |
257 | IODebugContext* /*dbg*/) override { | |
258 | return status_to_io_status(target_->PositionedAppend(data, offset)); | |
259 | } | |
260 | IOStatus PositionedAppend(const Slice& data, uint64_t offset, | |
261 | const IOOptions& /*options*/, | |
262 | const DataVerificationInfo& /*verification_info*/, | |
263 | IODebugContext* /*dbg*/) override { | |
264 | return status_to_io_status(target_->PositionedAppend(data, offset)); | |
265 | } | |
266 | IOStatus Truncate(uint64_t size, const IOOptions& /*options*/, | |
267 | IODebugContext* /*dbg*/) override { | |
268 | return status_to_io_status(target_->Truncate(size)); | |
269 | } | |
270 | IOStatus Close(const IOOptions& /*options*/, | |
271 | IODebugContext* /*dbg*/) override { | |
272 | return status_to_io_status(target_->Close()); | |
273 | } | |
274 | IOStatus Flush(const IOOptions& /*options*/, | |
275 | IODebugContext* /*dbg*/) override { | |
276 | return status_to_io_status(target_->Flush()); | |
277 | } | |
278 | IOStatus Sync(const IOOptions& /*options*/, | |
279 | IODebugContext* /*dbg*/) override { | |
280 | return status_to_io_status(target_->Sync()); | |
281 | } | |
282 | IOStatus Fsync(const IOOptions& /*options*/, | |
283 | IODebugContext* /*dbg*/) override { | |
284 | return status_to_io_status(target_->Fsync()); | |
285 | } | |
286 | bool IsSyncThreadSafe() const override { return target_->IsSyncThreadSafe(); } | |
287 | ||
288 | bool use_direct_io() const override { return target_->use_direct_io(); } | |
289 | ||
290 | size_t GetRequiredBufferAlignment() const override { | |
291 | return target_->GetRequiredBufferAlignment(); | |
292 | } | |
293 | ||
294 | void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) override { | |
295 | target_->SetWriteLifeTimeHint(hint); | |
296 | } | |
297 | ||
298 | Env::WriteLifeTimeHint GetWriteLifeTimeHint() override { | |
299 | return target_->GetWriteLifeTimeHint(); | |
300 | } | |
301 | ||
302 | uint64_t GetFileSize(const IOOptions& /*options*/, | |
303 | IODebugContext* /*dbg*/) override { | |
304 | return target_->GetFileSize(); | |
305 | } | |
306 | ||
307 | void SetPreallocationBlockSize(size_t size) override { | |
308 | target_->SetPreallocationBlockSize(size); | |
309 | } | |
310 | ||
311 | void GetPreallocationStatus(size_t* block_size, | |
312 | size_t* last_allocated_block) override { | |
313 | target_->GetPreallocationStatus(block_size, last_allocated_block); | |
314 | } | |
315 | ||
316 | size_t GetUniqueId(char* id, size_t max_size) const override { | |
317 | return target_->GetUniqueId(id, max_size); | |
318 | } | |
319 | ||
320 | IOStatus InvalidateCache(size_t offset, size_t length) override { | |
321 | return status_to_io_status(target_->InvalidateCache(offset, length)); | |
322 | } | |
323 | ||
324 | IOStatus RangeSync(uint64_t offset, uint64_t nbytes, | |
325 | const IOOptions& /*options*/, | |
326 | IODebugContext* /*dbg*/) override { | |
327 | return status_to_io_status(target_->RangeSync(offset, nbytes)); | |
328 | } | |
329 | ||
330 | void PrepareWrite(size_t offset, size_t len, const IOOptions& /*options*/, | |
331 | IODebugContext* /*dbg*/) override { | |
332 | target_->PrepareWrite(offset, len); | |
333 | } | |
334 | ||
335 | IOStatus Allocate(uint64_t offset, uint64_t len, const IOOptions& /*options*/, | |
336 | IODebugContext* /*dbg*/) override { | |
337 | return status_to_io_status(target_->Allocate(offset, len)); | |
338 | } | |
339 | ||
340 | private: | |
341 | std::unique_ptr<WritableFile> target_; | |
342 | }; | |
343 | ||
344 | class LegacyDirectoryWrapper : public FSDirectory { | |
345 | public: | |
346 | explicit LegacyDirectoryWrapper(std::unique_ptr<Directory>&& target) | |
347 | : target_(std::move(target)) {} | |
348 | ||
349 | IOStatus Fsync(const IOOptions& /*options*/, | |
350 | IODebugContext* /*dbg*/) override { | |
351 | return status_to_io_status(target_->Fsync()); | |
352 | } | |
353 | IOStatus Close(const IOOptions& /*options*/, | |
354 | IODebugContext* /*dbg*/) override { | |
355 | return status_to_io_status(target_->Close()); | |
356 | } | |
357 | size_t GetUniqueId(char* id, size_t max_size) const override { | |
358 | return target_->GetUniqueId(id, max_size); | |
359 | } | |
360 | ||
361 | private: | |
362 | std::unique_ptr<Directory> target_; | |
363 | }; | |
364 | ||
365 | class LegacyFileSystemWrapper : public FileSystem { | |
366 | public: | |
367 | // Initialize an EnvWrapper that delegates all calls to *t | |
368 | explicit LegacyFileSystemWrapper(Env* t) : target_(t) {} | |
369 | ~LegacyFileSystemWrapper() override {} | |
370 | ||
371 | static const char* kClassName() { return "LegacyFileSystem"; } | |
372 | const char* Name() const override { return kClassName(); } | |
373 | ||
374 | // Return the target to which this Env forwards all calls | |
375 | Env* target() const { return target_; } | |
376 | ||
377 | // The following text is boilerplate that forwards all methods to target() | |
378 | IOStatus NewSequentialFile(const std::string& f, const FileOptions& file_opts, | |
379 | std::unique_ptr<FSSequentialFile>* r, | |
380 | IODebugContext* /*dbg*/) override { | |
381 | std::unique_ptr<SequentialFile> file; | |
382 | Status s = target_->NewSequentialFile(f, &file, file_opts); | |
383 | if (s.ok()) { | |
384 | r->reset(new LegacySequentialFileWrapper(std::move(file))); | |
385 | } | |
386 | return status_to_io_status(std::move(s)); | |
387 | } | |
388 | IOStatus NewRandomAccessFile(const std::string& f, | |
389 | const FileOptions& file_opts, | |
390 | std::unique_ptr<FSRandomAccessFile>* r, | |
391 | IODebugContext* /*dbg*/) override { | |
392 | std::unique_ptr<RandomAccessFile> file; | |
393 | Status s = target_->NewRandomAccessFile(f, &file, file_opts); | |
394 | if (s.ok()) { | |
395 | r->reset(new LegacyRandomAccessFileWrapper(std::move(file))); | |
396 | } | |
397 | return status_to_io_status(std::move(s)); | |
398 | } | |
399 | IOStatus NewWritableFile(const std::string& f, const FileOptions& file_opts, | |
400 | std::unique_ptr<FSWritableFile>* r, | |
401 | IODebugContext* /*dbg*/) override { | |
402 | std::unique_ptr<WritableFile> file; | |
403 | Status s = target_->NewWritableFile(f, &file, file_opts); | |
404 | if (s.ok()) { | |
405 | r->reset(new LegacyWritableFileWrapper(std::move(file))); | |
406 | } | |
407 | return status_to_io_status(std::move(s)); | |
408 | } | |
409 | IOStatus ReopenWritableFile(const std::string& fname, | |
410 | const FileOptions& file_opts, | |
411 | std::unique_ptr<FSWritableFile>* result, | |
412 | IODebugContext* /*dbg*/) override { | |
413 | std::unique_ptr<WritableFile> file; | |
414 | Status s = target_->ReopenWritableFile(fname, &file, file_opts); | |
415 | if (s.ok()) { | |
416 | result->reset(new LegacyWritableFileWrapper(std::move(file))); | |
417 | } | |
418 | return status_to_io_status(std::move(s)); | |
419 | } | |
420 | IOStatus ReuseWritableFile(const std::string& fname, | |
421 | const std::string& old_fname, | |
422 | const FileOptions& file_opts, | |
423 | std::unique_ptr<FSWritableFile>* r, | |
424 | IODebugContext* /*dbg*/) override { | |
425 | std::unique_ptr<WritableFile> file; | |
426 | Status s = target_->ReuseWritableFile(fname, old_fname, &file, file_opts); | |
427 | if (s.ok()) { | |
428 | r->reset(new LegacyWritableFileWrapper(std::move(file))); | |
429 | } | |
430 | return status_to_io_status(std::move(s)); | |
431 | } | |
432 | IOStatus NewRandomRWFile(const std::string& fname, | |
433 | const FileOptions& file_opts, | |
434 | std::unique_ptr<FSRandomRWFile>* result, | |
435 | IODebugContext* /*dbg*/) override { | |
436 | std::unique_ptr<RandomRWFile> file; | |
437 | Status s = target_->NewRandomRWFile(fname, &file, file_opts); | |
438 | if (s.ok()) { | |
439 | result->reset(new LegacyRandomRWFileWrapper(std::move(file))); | |
440 | } | |
441 | return status_to_io_status(std::move(s)); | |
442 | } | |
443 | IOStatus NewMemoryMappedFileBuffer( | |
444 | const std::string& fname, | |
445 | std::unique_ptr<MemoryMappedFileBuffer>* result) override { | |
446 | return status_to_io_status( | |
447 | target_->NewMemoryMappedFileBuffer(fname, result)); | |
448 | } | |
449 | IOStatus NewDirectory(const std::string& name, const IOOptions& /*io_opts*/, | |
450 | std::unique_ptr<FSDirectory>* result, | |
451 | IODebugContext* /*dbg*/) override { | |
452 | std::unique_ptr<Directory> dir; | |
453 | Status s = target_->NewDirectory(name, &dir); | |
454 | if (s.ok()) { | |
455 | result->reset(new LegacyDirectoryWrapper(std::move(dir))); | |
456 | } | |
457 | return status_to_io_status(std::move(s)); | |
458 | } | |
459 | IOStatus FileExists(const std::string& f, const IOOptions& /*io_opts*/, | |
460 | IODebugContext* /*dbg*/) override { | |
461 | return status_to_io_status(target_->FileExists(f)); | |
462 | } | |
463 | IOStatus GetChildren(const std::string& dir, const IOOptions& /*io_opts*/, | |
464 | std::vector<std::string>* r, | |
465 | IODebugContext* /*dbg*/) override { | |
466 | return status_to_io_status(target_->GetChildren(dir, r)); | |
467 | } | |
468 | IOStatus GetChildrenFileAttributes(const std::string& dir, | |
469 | const IOOptions& /*options*/, | |
470 | std::vector<FileAttributes>* result, | |
471 | IODebugContext* /*dbg*/) override { | |
472 | return status_to_io_status(target_->GetChildrenFileAttributes(dir, result)); | |
473 | } | |
474 | IOStatus DeleteFile(const std::string& f, const IOOptions& /*options*/, | |
475 | IODebugContext* /*dbg*/) override { | |
476 | return status_to_io_status(target_->DeleteFile(f)); | |
477 | } | |
478 | IOStatus Truncate(const std::string& fname, size_t size, | |
479 | const IOOptions& /*options*/, | |
480 | IODebugContext* /*dbg*/) override { | |
481 | return status_to_io_status(target_->Truncate(fname, size)); | |
482 | } | |
483 | IOStatus CreateDir(const std::string& d, const IOOptions& /*options*/, | |
484 | IODebugContext* /*dbg*/) override { | |
485 | return status_to_io_status(target_->CreateDir(d)); | |
486 | } | |
487 | IOStatus CreateDirIfMissing(const std::string& d, | |
488 | const IOOptions& /*options*/, | |
489 | IODebugContext* /*dbg*/) override { | |
490 | return status_to_io_status(target_->CreateDirIfMissing(d)); | |
491 | } | |
492 | IOStatus DeleteDir(const std::string& d, const IOOptions& /*options*/, | |
493 | IODebugContext* /*dbg*/) override { | |
494 | return status_to_io_status(target_->DeleteDir(d)); | |
495 | } | |
496 | IOStatus GetFileSize(const std::string& f, const IOOptions& /*options*/, | |
497 | uint64_t* s, IODebugContext* /*dbg*/) override { | |
498 | return status_to_io_status(target_->GetFileSize(f, s)); | |
499 | } | |
500 | ||
501 | IOStatus GetFileModificationTime(const std::string& fname, | |
502 | const IOOptions& /*options*/, | |
503 | uint64_t* file_mtime, | |
504 | IODebugContext* /*dbg*/) override { | |
505 | return status_to_io_status( | |
506 | target_->GetFileModificationTime(fname, file_mtime)); | |
507 | } | |
508 | ||
509 | IOStatus GetAbsolutePath(const std::string& db_path, | |
510 | const IOOptions& /*options*/, | |
511 | std::string* output_path, | |
512 | IODebugContext* /*dbg*/) override { | |
513 | return status_to_io_status(target_->GetAbsolutePath(db_path, output_path)); | |
514 | } | |
515 | ||
516 | IOStatus RenameFile(const std::string& s, const std::string& t, | |
517 | const IOOptions& /*options*/, | |
518 | IODebugContext* /*dbg*/) override { | |
519 | return status_to_io_status(target_->RenameFile(s, t)); | |
520 | } | |
521 | ||
522 | IOStatus LinkFile(const std::string& s, const std::string& t, | |
523 | const IOOptions& /*options*/, | |
524 | IODebugContext* /*dbg*/) override { | |
525 | return status_to_io_status(target_->LinkFile(s, t)); | |
526 | } | |
527 | ||
528 | IOStatus NumFileLinks(const std::string& fname, const IOOptions& /*options*/, | |
529 | uint64_t* count, IODebugContext* /*dbg*/) override { | |
530 | return status_to_io_status(target_->NumFileLinks(fname, count)); | |
531 | } | |
532 | ||
533 | IOStatus AreFilesSame(const std::string& first, const std::string& second, | |
534 | const IOOptions& /*options*/, bool* res, | |
535 | IODebugContext* /*dbg*/) override { | |
536 | return status_to_io_status(target_->AreFilesSame(first, second, res)); | |
537 | } | |
538 | ||
539 | IOStatus LockFile(const std::string& f, const IOOptions& /*options*/, | |
540 | FileLock** l, IODebugContext* /*dbg*/) override { | |
541 | return status_to_io_status(target_->LockFile(f, l)); | |
542 | } | |
543 | ||
544 | IOStatus UnlockFile(FileLock* l, const IOOptions& /*options*/, | |
545 | IODebugContext* /*dbg*/) override { | |
546 | return status_to_io_status(target_->UnlockFile(l)); | |
547 | } | |
548 | ||
549 | IOStatus GetTestDirectory(const IOOptions& /*options*/, std::string* path, | |
550 | IODebugContext* /*dbg*/) override { | |
551 | return status_to_io_status(target_->GetTestDirectory(path)); | |
552 | } | |
553 | IOStatus NewLogger(const std::string& fname, const IOOptions& /*options*/, | |
554 | std::shared_ptr<Logger>* result, | |
555 | IODebugContext* /*dbg*/) override { | |
556 | return status_to_io_status(target_->NewLogger(fname, result)); | |
557 | } | |
558 | ||
559 | void SanitizeFileOptions(FileOptions* opts) const override { | |
560 | target_->SanitizeEnvOptions(opts); | |
561 | } | |
562 | ||
563 | FileOptions OptimizeForLogRead( | |
564 | const FileOptions& file_options) const override { | |
565 | return target_->OptimizeForLogRead(file_options); | |
566 | } | |
567 | FileOptions OptimizeForManifestRead( | |
568 | const FileOptions& file_options) const override { | |
569 | return target_->OptimizeForManifestRead(file_options); | |
570 | } | |
571 | FileOptions OptimizeForLogWrite(const FileOptions& file_options, | |
572 | const DBOptions& db_options) const override { | |
573 | return target_->OptimizeForLogWrite(file_options, db_options); | |
574 | } | |
575 | FileOptions OptimizeForManifestWrite( | |
576 | const FileOptions& file_options) const override { | |
577 | return target_->OptimizeForManifestWrite(file_options); | |
578 | } | |
579 | FileOptions OptimizeForCompactionTableWrite( | |
580 | const FileOptions& file_options, | |
581 | const ImmutableDBOptions& immutable_ops) const override { | |
582 | return target_->OptimizeForCompactionTableWrite(file_options, | |
583 | immutable_ops); | |
584 | } | |
585 | FileOptions OptimizeForCompactionTableRead( | |
586 | const FileOptions& file_options, | |
587 | const ImmutableDBOptions& db_options) const override { | |
588 | return target_->OptimizeForCompactionTableRead(file_options, db_options); | |
589 | } | |
590 | FileOptions OptimizeForBlobFileRead( | |
591 | const FileOptions& file_options, | |
592 | const ImmutableDBOptions& db_options) const override { | |
593 | return target_->OptimizeForBlobFileRead(file_options, db_options); | |
594 | } | |
595 | ||
596 | #ifdef GetFreeSpace | |
597 | #undef GetFreeSpace | |
598 | #endif | |
599 | IOStatus GetFreeSpace(const std::string& path, const IOOptions& /*options*/, | |
600 | uint64_t* diskfree, IODebugContext* /*dbg*/) override { | |
601 | return status_to_io_status(target_->GetFreeSpace(path, diskfree)); | |
602 | } | |
603 | IOStatus IsDirectory(const std::string& path, const IOOptions& /*options*/, | |
604 | bool* is_dir, IODebugContext* /*dbg*/) override { | |
605 | return status_to_io_status(target_->IsDirectory(path, is_dir)); | |
606 | } | |
607 | ||
608 | #ifndef ROCKSDB_LITE | |
609 | std::string SerializeOptions(const ConfigOptions& /*config_options*/, | |
610 | const std::string& /*prefix*/) const override { | |
611 | // We do not want the LegacyFileSystem to appear in the serialized output. | |
612 | // This clock is an internal class for those who do not implement one and | |
613 | // would be part of the Env. As such, do not serialize it here. | |
614 | return ""; | |
615 | } | |
616 | #endif // ROCKSDB_LITE | |
617 | private: | |
618 | Env* target_; | |
619 | }; | |
620 | } // end anonymous namespace | |
7c673cae | 621 | |
20effc67 TL |
622 | Env::Env() : thread_status_updater_(nullptr) { |
623 | file_system_ = std::make_shared<LegacyFileSystemWrapper>(this); | |
1e59de90 | 624 | system_clock_ = std::make_shared<LegacySystemClock>(this); |
20effc67 TL |
625 | } |
626 | ||
1e59de90 TL |
627 | Env::Env(const std::shared_ptr<FileSystem>& fs) |
628 | : thread_status_updater_(nullptr), file_system_(fs) { | |
629 | system_clock_ = std::make_shared<LegacySystemClock>(this); | |
7c673cae FG |
630 | } |
631 | ||
1e59de90 TL |
632 | Env::Env(const std::shared_ptr<FileSystem>& fs, |
633 | const std::shared_ptr<SystemClock>& clock) | |
634 | : thread_status_updater_(nullptr), file_system_(fs), system_clock_(clock) {} | |
635 | ||
636 | Env::~Env() {} | |
637 | ||
f67539c2 TL |
638 | Status Env::NewLogger(const std::string& fname, |
639 | std::shared_ptr<Logger>* result) { | |
640 | return NewEnvLogger(fname, this, result); | |
641 | } | |
642 | ||
643 | Status Env::LoadEnv(const std::string& value, Env** result) { | |
1e59de90 TL |
644 | return CreateFromString(ConfigOptions(), value, result); |
645 | } | |
646 | ||
647 | Status Env::CreateFromString(const ConfigOptions& config_options, | |
648 | const std::string& value, Env** result) { | |
649 | Env* base = Env::Default(); | |
650 | if (value.empty() || base->IsInstanceOf(value)) { | |
651 | *result = base; | |
652 | return Status::OK(); | |
653 | } else { | |
654 | RegisterSystemEnvs(); | |
655 | Env* env = *result; | |
656 | Status s = LoadStaticObject<Env>(config_options, value, nullptr, &env); | |
657 | if (s.ok()) { | |
658 | *result = env; | |
659 | } | |
660 | return s; | |
f67539c2 | 661 | } |
f67539c2 TL |
662 | } |
663 | ||
664 | Status Env::LoadEnv(const std::string& value, Env** result, | |
665 | std::shared_ptr<Env>* guard) { | |
1e59de90 TL |
666 | return CreateFromString(ConfigOptions(), value, result, guard); |
667 | } | |
668 | ||
669 | Status Env::CreateFromString(const ConfigOptions& config_options, | |
670 | const std::string& value, Env** result, | |
671 | std::shared_ptr<Env>* guard) { | |
f67539c2 | 672 | assert(result); |
f67539c2 | 673 | assert(guard != nullptr); |
1e59de90 TL |
674 | std::unique_ptr<Env> uniq; |
675 | ||
676 | Env* env = *result; | |
677 | std::string id; | |
678 | std::unordered_map<std::string, std::string> opt_map; | |
679 | ||
680 | Status status = | |
681 | Customizable::GetOptionsMap(config_options, env, value, &id, &opt_map); | |
682 | if (!status.ok()) { // GetOptionsMap failed | |
683 | return status; | |
f67539c2 | 684 | } |
1e59de90 TL |
685 | Env* base = Env::Default(); |
686 | if (id.empty() || base->IsInstanceOf(id)) { | |
687 | env = base; | |
688 | status = Status::OK(); | |
689 | } else { | |
690 | RegisterSystemEnvs(); | |
691 | #ifndef ROCKSDB_LITE | |
692 | // First, try to load the Env as a unique object. | |
693 | status = config_options.registry->NewObject<Env>(id, &env, &uniq); | |
f67539c2 | 694 | #else |
1e59de90 TL |
695 | status = |
696 | Status::NotSupported("Cannot load environment in LITE mode", value); | |
f67539c2 | 697 | #endif |
1e59de90 TL |
698 | } |
699 | if (config_options.ignore_unsupported_options && status.IsNotSupported()) { | |
700 | status = Status::OK(); | |
701 | } else if (status.ok()) { | |
702 | status = Customizable::ConfigureNewObject(config_options, env, opt_map); | |
703 | } | |
704 | if (status.ok()) { | |
705 | guard->reset(uniq.release()); | |
706 | *result = env; | |
707 | } | |
708 | return status; | |
709 | } | |
710 | ||
711 | Status Env::CreateFromUri(const ConfigOptions& config_options, | |
712 | const std::string& env_uri, const std::string& fs_uri, | |
713 | Env** result, std::shared_ptr<Env>* guard) { | |
714 | *result = config_options.env; | |
715 | if (env_uri.empty() && fs_uri.empty()) { | |
716 | // Neither specified. Use the default | |
717 | guard->reset(); | |
718 | return Status::OK(); | |
719 | } else if (!env_uri.empty() && !fs_uri.empty()) { | |
720 | // Both specified. Cannot choose. Return Invalid | |
721 | return Status::InvalidArgument("cannot specify both fs_uri and env_uri"); | |
722 | } else if (fs_uri.empty()) { // Only have an ENV URI. Create an Env from it | |
723 | return CreateFromString(config_options, env_uri, result, guard); | |
724 | } else { | |
725 | std::shared_ptr<FileSystem> fs; | |
726 | Status s = FileSystem::CreateFromString(config_options, fs_uri, &fs); | |
727 | if (s.ok()) { | |
728 | guard->reset(new CompositeEnvWrapper(*result, fs)); | |
729 | *result = guard->get(); | |
730 | } | |
731 | return s; | |
732 | } | |
f67539c2 TL |
733 | } |
734 | ||
11fdf7f2 TL |
735 | std::string Env::PriorityToString(Env::Priority priority) { |
736 | switch (priority) { | |
737 | case Env::Priority::BOTTOM: | |
738 | return "Bottom"; | |
739 | case Env::Priority::LOW: | |
740 | return "Low"; | |
741 | case Env::Priority::HIGH: | |
742 | return "High"; | |
494da23a TL |
743 | case Env::Priority::USER: |
744 | return "User"; | |
11fdf7f2 TL |
745 | case Env::Priority::TOTAL: |
746 | assert(false); | |
747 | } | |
748 | return "Invalid"; | |
749 | } | |
750 | ||
7c673cae FG |
751 | uint64_t Env::GetThreadID() const { |
752 | std::hash<std::thread::id> hasher; | |
753 | return hasher(std::this_thread::get_id()); | |
754 | } | |
755 | ||
756 | Status Env::ReuseWritableFile(const std::string& fname, | |
757 | const std::string& old_fname, | |
494da23a | 758 | std::unique_ptr<WritableFile>* result, |
7c673cae FG |
759 | const EnvOptions& options) { |
760 | Status s = RenameFile(old_fname, fname); | |
761 | if (!s.ok()) { | |
762 | return s; | |
763 | } | |
764 | return NewWritableFile(fname, result, options); | |
765 | } | |
766 | ||
767 | Status Env::GetChildrenFileAttributes(const std::string& dir, | |
768 | std::vector<FileAttributes>* result) { | |
769 | assert(result != nullptr); | |
770 | std::vector<std::string> child_fnames; | |
771 | Status s = GetChildren(dir, &child_fnames); | |
772 | if (!s.ok()) { | |
773 | return s; | |
774 | } | |
775 | result->resize(child_fnames.size()); | |
776 | size_t result_size = 0; | |
777 | for (size_t i = 0; i < child_fnames.size(); ++i) { | |
778 | const std::string path = dir + "/" + child_fnames[i]; | |
779 | if (!(s = GetFileSize(path, &(*result)[result_size].size_bytes)).ok()) { | |
780 | if (FileExists(path).IsNotFound()) { | |
781 | // The file may have been deleted since we listed the directory | |
782 | continue; | |
783 | } | |
784 | return s; | |
785 | } | |
786 | (*result)[result_size].name = std::move(child_fnames[i]); | |
787 | result_size++; | |
788 | } | |
789 | result->resize(result_size); | |
790 | return Status::OK(); | |
791 | } | |
792 | ||
20effc67 | 793 | Status Env::GetHostNameString(std::string* result) { |
1e59de90 | 794 | std::array<char, kMaxHostNameLen> hostname_buf{}; |
20effc67 TL |
795 | Status s = GetHostName(hostname_buf.data(), hostname_buf.size()); |
796 | if (s.ok()) { | |
797 | hostname_buf[hostname_buf.size() - 1] = '\0'; | |
798 | result->assign(hostname_buf.data()); | |
799 | } | |
800 | return s; | |
801 | } | |
802 | ||
1e59de90 TL |
803 | std::string Env::GenerateUniqueId() { |
804 | std::string result; | |
805 | bool success = port::GenerateRfcUuid(&result); | |
806 | if (!success) { | |
807 | // Fall back on our own way of generating a unique ID and adapt it to | |
808 | // RFC 4122 variant 1 version 4 (a random ID). | |
809 | // https://en.wikipedia.org/wiki/Universally_unique_identifier | |
810 | // We already tried GenerateRfcUuid so no need to try it again in | |
811 | // GenerateRawUniqueId | |
812 | constexpr bool exclude_port_uuid = true; | |
813 | uint64_t upper, lower; | |
814 | GenerateRawUniqueId(&upper, &lower, exclude_port_uuid); | |
815 | ||
816 | // Set 4-bit version to 4 | |
817 | upper = (upper & (~uint64_t{0xf000})) | 0x4000; | |
818 | // Set unary-encoded variant to 1 (0b10) | |
819 | lower = (lower & (~(uint64_t{3} << 62))) | (uint64_t{2} << 62); | |
820 | ||
821 | // Use 36 character format of RFC 4122 | |
822 | result.resize(36U); | |
823 | char* buf = &result[0]; | |
824 | PutBaseChars<16>(&buf, 8, upper >> 32, /*!uppercase*/ false); | |
825 | *(buf++) = '-'; | |
826 | PutBaseChars<16>(&buf, 4, upper >> 16, /*!uppercase*/ false); | |
827 | *(buf++) = '-'; | |
828 | PutBaseChars<16>(&buf, 4, upper, /*!uppercase*/ false); | |
829 | *(buf++) = '-'; | |
830 | PutBaseChars<16>(&buf, 4, lower >> 48, /*!uppercase*/ false); | |
831 | *(buf++) = '-'; | |
832 | PutBaseChars<16>(&buf, 12, lower, /*!uppercase*/ false); | |
833 | assert(buf == &result[36]); | |
834 | ||
835 | // Verify variant 1 version 4 | |
836 | assert(result[14] == '4'); | |
837 | assert(result[19] == '8' || result[19] == '9' || result[19] == 'a' || | |
838 | result[19] == 'b'); | |
839 | } | |
840 | return result; | |
7c673cae FG |
841 | } |
842 | ||
1e59de90 | 843 | SequentialFile::~SequentialFile() {} |
7c673cae | 844 | |
1e59de90 TL |
845 | RandomAccessFile::~RandomAccessFile() {} |
846 | ||
847 | WritableFile::~WritableFile() {} | |
7c673cae | 848 | |
11fdf7f2 TL |
849 | MemoryMappedFileBuffer::~MemoryMappedFileBuffer() {} |
850 | ||
851 | Logger::~Logger() {} | |
852 | ||
853 | Status Logger::Close() { | |
854 | if (!closed_) { | |
855 | closed_ = true; | |
856 | return CloseImpl(); | |
857 | } else { | |
858 | return Status::OK(); | |
859 | } | |
7c673cae FG |
860 | } |
861 | ||
11fdf7f2 TL |
862 | Status Logger::CloseImpl() { return Status::NotSupported(); } |
863 | ||
1e59de90 | 864 | FileLock::~FileLock() {} |
7c673cae | 865 | |
1e59de90 | 866 | void LogFlush(Logger* info_log) { |
7c673cae FG |
867 | if (info_log) { |
868 | info_log->Flush(); | |
869 | } | |
870 | } | |
871 | ||
1e59de90 | 872 | static void Logv(Logger* info_log, const char* format, va_list ap) { |
7c673cae | 873 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL) { |
7c673cae | 874 | info_log->Logv(InfoLogLevel::INFO_LEVEL, format, ap); |
7c673cae FG |
875 | } |
876 | } | |
877 | ||
11fdf7f2 TL |
878 | void Log(Logger* info_log, const char* format, ...) { |
879 | va_list ap; | |
880 | va_start(ap, format); | |
881 | Logv(info_log, format, ap); | |
882 | va_end(ap); | |
883 | } | |
884 | ||
1e59de90 TL |
885 | void Logger::Logv(const InfoLogLevel log_level, const char* format, |
886 | va_list ap) { | |
887 | static const char* kInfoLogLevelNames[5] = {"DEBUG", "INFO", "WARN", "ERROR", | |
888 | "FATAL"}; | |
7c673cae FG |
889 | if (log_level < log_level_) { |
890 | return; | |
891 | } | |
892 | ||
893 | if (log_level == InfoLogLevel::INFO_LEVEL) { | |
894 | // Doesn't print log level if it is INFO level. | |
895 | // This is to avoid unexpected performance regression after we add | |
896 | // the feature of log level. All the logs before we add the feature | |
897 | // are INFO level. We don't want to add extra costs to those existing | |
898 | // logging. | |
899 | Logv(format, ap); | |
494da23a TL |
900 | } else if (log_level == InfoLogLevel::HEADER_LEVEL) { |
901 | LogHeader(format, ap); | |
7c673cae FG |
902 | } else { |
903 | char new_format[500]; | |
904 | snprintf(new_format, sizeof(new_format) - 1, "[%s] %s", | |
1e59de90 | 905 | kInfoLogLevelNames[log_level], format); |
7c673cae FG |
906 | Logv(new_format, ap); |
907 | } | |
20effc67 TL |
908 | |
909 | if (log_level >= InfoLogLevel::WARN_LEVEL && | |
910 | log_level != InfoLogLevel::HEADER_LEVEL) { | |
911 | // Log messages with severity of warning or higher should be rare and are | |
912 | // sometimes followed by an unclean crash. We want to be sure important | |
913 | // messages are not lost in an application buffer when that happens. | |
914 | Flush(); | |
915 | } | |
7c673cae FG |
916 | } |
917 | ||
1e59de90 TL |
918 | static void Logv(const InfoLogLevel log_level, Logger* info_log, |
919 | const char* format, va_list ap) { | |
7c673cae | 920 | if (info_log && info_log->GetInfoLogLevel() <= log_level) { |
7c673cae FG |
921 | if (log_level == InfoLogLevel::HEADER_LEVEL) { |
922 | info_log->LogHeader(format, ap); | |
923 | } else { | |
924 | info_log->Logv(log_level, format, ap); | |
925 | } | |
7c673cae FG |
926 | } |
927 | } | |
928 | ||
11fdf7f2 TL |
929 | void Log(const InfoLogLevel log_level, Logger* info_log, const char* format, |
930 | ...) { | |
931 | va_list ap; | |
932 | va_start(ap, format); | |
933 | Logv(log_level, info_log, format, ap); | |
934 | va_end(ap); | |
935 | } | |
936 | ||
1e59de90 | 937 | static void Headerv(Logger* info_log, const char* format, va_list ap) { |
7c673cae | 938 | if (info_log) { |
7c673cae | 939 | info_log->LogHeader(format, ap); |
7c673cae FG |
940 | } |
941 | } | |
942 | ||
11fdf7f2 TL |
943 | void Header(Logger* info_log, const char* format, ...) { |
944 | va_list ap; | |
945 | va_start(ap, format); | |
946 | Headerv(info_log, format, ap); | |
947 | va_end(ap); | |
948 | } | |
949 | ||
950 | static void Debugv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 951 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::DEBUG_LEVEL) { |
7c673cae | 952 | info_log->Logv(InfoLogLevel::DEBUG_LEVEL, format, ap); |
7c673cae FG |
953 | } |
954 | } | |
955 | ||
11fdf7f2 TL |
956 | void Debug(Logger* info_log, const char* format, ...) { |
957 | va_list ap; | |
958 | va_start(ap, format); | |
959 | Debugv(info_log, format, ap); | |
960 | va_end(ap); | |
961 | } | |
962 | ||
963 | static void Infov(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 964 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL) { |
7c673cae | 965 | info_log->Logv(InfoLogLevel::INFO_LEVEL, format, ap); |
7c673cae FG |
966 | } |
967 | } | |
968 | ||
11fdf7f2 TL |
969 | void Info(Logger* info_log, const char* format, ...) { |
970 | va_list ap; | |
971 | va_start(ap, format); | |
972 | Infov(info_log, format, ap); | |
973 | va_end(ap); | |
974 | } | |
975 | ||
976 | static void Warnv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 977 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::WARN_LEVEL) { |
7c673cae | 978 | info_log->Logv(InfoLogLevel::WARN_LEVEL, format, ap); |
7c673cae FG |
979 | } |
980 | } | |
11fdf7f2 TL |
981 | |
982 | void Warn(Logger* info_log, const char* format, ...) { | |
983 | va_list ap; | |
984 | va_start(ap, format); | |
985 | Warnv(info_log, format, ap); | |
986 | va_end(ap); | |
987 | } | |
988 | ||
989 | static void Errorv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 990 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::ERROR_LEVEL) { |
7c673cae | 991 | info_log->Logv(InfoLogLevel::ERROR_LEVEL, format, ap); |
7c673cae FG |
992 | } |
993 | } | |
11fdf7f2 TL |
994 | |
995 | void Error(Logger* info_log, const char* format, ...) { | |
996 | va_list ap; | |
997 | va_start(ap, format); | |
998 | Errorv(info_log, format, ap); | |
999 | va_end(ap); | |
1000 | } | |
1001 | ||
1002 | static void Fatalv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 1003 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::FATAL_LEVEL) { |
7c673cae | 1004 | info_log->Logv(InfoLogLevel::FATAL_LEVEL, format, ap); |
7c673cae FG |
1005 | } |
1006 | } | |
1007 | ||
11fdf7f2 TL |
1008 | void Fatal(Logger* info_log, const char* format, ...) { |
1009 | va_list ap; | |
1010 | va_start(ap, format); | |
1011 | Fatalv(info_log, format, ap); | |
1012 | va_end(ap); | |
1013 | } | |
1014 | ||
494da23a | 1015 | void LogFlush(const std::shared_ptr<Logger>& info_log) { |
11fdf7f2 | 1016 | LogFlush(info_log.get()); |
7c673cae FG |
1017 | } |
1018 | ||
494da23a | 1019 | void Log(const InfoLogLevel log_level, const std::shared_ptr<Logger>& info_log, |
7c673cae | 1020 | const char* format, ...) { |
11fdf7f2 TL |
1021 | va_list ap; |
1022 | va_start(ap, format); | |
1023 | Logv(log_level, info_log.get(), format, ap); | |
1024 | va_end(ap); | |
7c673cae FG |
1025 | } |
1026 | ||
494da23a | 1027 | void Header(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1028 | va_list ap; |
1029 | va_start(ap, format); | |
1030 | Headerv(info_log.get(), format, ap); | |
1031 | va_end(ap); | |
7c673cae FG |
1032 | } |
1033 | ||
494da23a | 1034 | void Debug(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1035 | va_list ap; |
1036 | va_start(ap, format); | |
1037 | Debugv(info_log.get(), format, ap); | |
1038 | va_end(ap); | |
7c673cae FG |
1039 | } |
1040 | ||
494da23a | 1041 | void Info(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1042 | va_list ap; |
1043 | va_start(ap, format); | |
1044 | Infov(info_log.get(), format, ap); | |
1045 | va_end(ap); | |
7c673cae FG |
1046 | } |
1047 | ||
494da23a | 1048 | void Warn(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1049 | va_list ap; |
1050 | va_start(ap, format); | |
1051 | Warnv(info_log.get(), format, ap); | |
1052 | va_end(ap); | |
7c673cae FG |
1053 | } |
1054 | ||
494da23a | 1055 | void Error(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1056 | va_list ap; |
1057 | va_start(ap, format); | |
1058 | Errorv(info_log.get(), format, ap); | |
1059 | va_end(ap); | |
7c673cae FG |
1060 | } |
1061 | ||
494da23a | 1062 | void Fatal(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1063 | va_list ap; |
1064 | va_start(ap, format); | |
1065 | Fatalv(info_log.get(), format, ap); | |
1066 | va_end(ap); | |
7c673cae FG |
1067 | } |
1068 | ||
494da23a | 1069 | void Log(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
1070 | va_list ap; |
1071 | va_start(ap, format); | |
1072 | Logv(info_log.get(), format, ap); | |
1073 | va_end(ap); | |
7c673cae FG |
1074 | } |
1075 | ||
1076 | Status WriteStringToFile(Env* env, const Slice& data, const std::string& fname, | |
1077 | bool should_sync) { | |
1e59de90 TL |
1078 | const auto& fs = env->GetFileSystem(); |
1079 | return WriteStringToFile(fs.get(), data, fname, should_sync); | |
7c673cae FG |
1080 | } |
1081 | ||
1082 | Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { | |
1e59de90 TL |
1083 | const auto& fs = env->GetFileSystem(); |
1084 | return ReadFileToString(fs.get(), fname, data); | |
7c673cae FG |
1085 | } |
1086 | ||
1087 | namespace { // anonymous namespace | |
1088 | ||
1089 | void AssignEnvOptions(EnvOptions* env_options, const DBOptions& options) { | |
1090 | env_options->use_mmap_reads = options.allow_mmap_reads; | |
1091 | env_options->use_mmap_writes = options.allow_mmap_writes; | |
1092 | env_options->use_direct_reads = options.use_direct_reads; | |
1093 | env_options->set_fd_cloexec = options.is_fd_close_on_exec; | |
1094 | env_options->bytes_per_sync = options.bytes_per_sync; | |
1095 | env_options->compaction_readahead_size = options.compaction_readahead_size; | |
1096 | env_options->random_access_max_buffer_size = | |
1097 | options.random_access_max_buffer_size; | |
1098 | env_options->rate_limiter = options.rate_limiter.get(); | |
1099 | env_options->writable_file_max_buffer_size = | |
1100 | options.writable_file_max_buffer_size; | |
1101 | env_options->allow_fallocate = options.allow_fallocate; | |
f67539c2 TL |
1102 | env_options->strict_bytes_per_sync = options.strict_bytes_per_sync; |
1103 | options.env->SanitizeEnvOptions(env_options); | |
7c673cae FG |
1104 | } |
1105 | ||
1e59de90 | 1106 | } // namespace |
7c673cae FG |
1107 | |
1108 | EnvOptions Env::OptimizeForLogWrite(const EnvOptions& env_options, | |
1109 | const DBOptions& db_options) const { | |
1110 | EnvOptions optimized_env_options(env_options); | |
1111 | optimized_env_options.bytes_per_sync = db_options.wal_bytes_per_sync; | |
11fdf7f2 TL |
1112 | optimized_env_options.writable_file_max_buffer_size = |
1113 | db_options.writable_file_max_buffer_size; | |
7c673cae FG |
1114 | return optimized_env_options; |
1115 | } | |
1116 | ||
1117 | EnvOptions Env::OptimizeForManifestWrite(const EnvOptions& env_options) const { | |
1118 | return env_options; | |
1119 | } | |
1120 | ||
11fdf7f2 TL |
1121 | EnvOptions Env::OptimizeForLogRead(const EnvOptions& env_options) const { |
1122 | EnvOptions optimized_env_options(env_options); | |
1123 | optimized_env_options.use_direct_reads = false; | |
1124 | return optimized_env_options; | |
1125 | } | |
1126 | ||
1127 | EnvOptions Env::OptimizeForManifestRead(const EnvOptions& env_options) const { | |
1128 | EnvOptions optimized_env_options(env_options); | |
1129 | optimized_env_options.use_direct_reads = false; | |
1130 | return optimized_env_options; | |
1131 | } | |
1132 | ||
7c673cae FG |
1133 | EnvOptions Env::OptimizeForCompactionTableWrite( |
1134 | const EnvOptions& env_options, const ImmutableDBOptions& db_options) const { | |
1135 | EnvOptions optimized_env_options(env_options); | |
1136 | optimized_env_options.use_direct_writes = | |
1137 | db_options.use_direct_io_for_flush_and_compaction; | |
1138 | return optimized_env_options; | |
1139 | } | |
1140 | ||
1141 | EnvOptions Env::OptimizeForCompactionTableRead( | |
1142 | const EnvOptions& env_options, const ImmutableDBOptions& db_options) const { | |
1143 | EnvOptions optimized_env_options(env_options); | |
11fdf7f2 | 1144 | optimized_env_options.use_direct_reads = db_options.use_direct_reads; |
7c673cae FG |
1145 | return optimized_env_options; |
1146 | } | |
1e59de90 TL |
1147 | EnvOptions Env::OptimizeForBlobFileRead( |
1148 | const EnvOptions& env_options, const ImmutableDBOptions& db_options) const { | |
1149 | EnvOptions optimized_env_options(env_options); | |
1150 | optimized_env_options.use_direct_reads = db_options.use_direct_reads; | |
1151 | return optimized_env_options; | |
1152 | } | |
7c673cae FG |
1153 | |
1154 | EnvOptions::EnvOptions(const DBOptions& options) { | |
1155 | AssignEnvOptions(this, options); | |
1156 | } | |
1157 | ||
1158 | EnvOptions::EnvOptions() { | |
1159 | DBOptions options; | |
1160 | AssignEnvOptions(this, options); | |
1161 | } | |
1162 | ||
f67539c2 TL |
1163 | Status NewEnvLogger(const std::string& fname, Env* env, |
1164 | std::shared_ptr<Logger>* result) { | |
1e59de90 | 1165 | FileOptions options; |
f67539c2 TL |
1166 | // TODO: Tune the buffer size. |
1167 | options.writable_file_max_buffer_size = 1024 * 1024; | |
1e59de90 TL |
1168 | std::unique_ptr<FSWritableFile> writable_file; |
1169 | const auto status = env->GetFileSystem()->NewWritableFile( | |
1170 | fname, options, &writable_file, nullptr); | |
f67539c2 TL |
1171 | if (!status.ok()) { |
1172 | return status; | |
1173 | } | |
1174 | ||
1e59de90 TL |
1175 | *result = std::make_shared<EnvLogger>(std::move(writable_file), fname, |
1176 | options, env); | |
f67539c2 TL |
1177 | return Status::OK(); |
1178 | } | |
7c673cae | 1179 | |
20effc67 TL |
1180 | const std::shared_ptr<FileSystem>& Env::GetFileSystem() const { |
1181 | return file_system_; | |
1182 | } | |
1183 | ||
1e59de90 TL |
1184 | const std::shared_ptr<SystemClock>& Env::GetSystemClock() const { |
1185 | return system_clock_; | |
1186 | } | |
1187 | namespace { | |
1188 | static std::unordered_map<std::string, OptionTypeInfo> sc_wrapper_type_info = { | |
1189 | #ifndef ROCKSDB_LITE | |
1190 | {"target", | |
1191 | OptionTypeInfo::AsCustomSharedPtr<SystemClock>( | |
1192 | 0, OptionVerificationType::kByName, OptionTypeFlags::kDontSerialize)}, | |
1193 | #endif // ROCKSDB_LITE | |
1194 | }; | |
1195 | ||
1196 | } // namespace | |
1197 | SystemClockWrapper::SystemClockWrapper(const std::shared_ptr<SystemClock>& t) | |
1198 | : target_(t) { | |
1199 | RegisterOptions("", &target_, &sc_wrapper_type_info); | |
1200 | } | |
1201 | ||
1202 | Status SystemClockWrapper::PrepareOptions(const ConfigOptions& options) { | |
1203 | if (target_ == nullptr) { | |
1204 | target_ = SystemClock::Default(); | |
1205 | } | |
1206 | return SystemClock::PrepareOptions(options); | |
20effc67 | 1207 | } |
20effc67 | 1208 | |
1e59de90 TL |
1209 | #ifndef ROCKSDB_LITE |
1210 | std::string SystemClockWrapper::SerializeOptions( | |
1211 | const ConfigOptions& config_options, const std::string& header) const { | |
1212 | auto parent = SystemClock::SerializeOptions(config_options, ""); | |
1213 | if (config_options.IsShallow() || target_ == nullptr || | |
1214 | target_->IsInstanceOf(SystemClock::kDefaultName())) { | |
1215 | return parent; | |
1216 | } else { | |
1217 | std::string result = header; | |
1218 | if (!StartsWith(parent, OptionTypeInfo::kIdPropName())) { | |
1219 | result.append(OptionTypeInfo::kIdPropName()).append("="); | |
1220 | } | |
1221 | result.append(parent); | |
1222 | if (!EndsWith(result, config_options.delimiter)) { | |
1223 | result.append(config_options.delimiter); | |
1224 | } | |
1225 | result.append("target=").append(target_->ToString(config_options)); | |
1226 | return result; | |
1227 | } | |
1228 | } | |
1229 | #endif // ROCKSDB_LITE | |
1230 | ||
1231 | #ifndef ROCKSDB_LITE | |
1232 | static int RegisterBuiltinSystemClocks(ObjectLibrary& library, | |
1233 | const std::string& /*arg*/) { | |
1234 | library.AddFactory<SystemClock>( | |
1235 | EmulatedSystemClock::kClassName(), | |
1236 | [](const std::string& /*uri*/, std::unique_ptr<SystemClock>* guard, | |
1237 | std::string* /* errmsg */) { | |
1238 | guard->reset(new EmulatedSystemClock(SystemClock::Default())); | |
1239 | return guard->get(); | |
1240 | }); | |
1241 | size_t num_types; | |
1242 | return static_cast<int>(library.GetFactoryCount(&num_types)); | |
1243 | } | |
1244 | #endif // ROCKSDB_LITE | |
1245 | ||
1246 | Status SystemClock::CreateFromString(const ConfigOptions& config_options, | |
1247 | const std::string& value, | |
1248 | std::shared_ptr<SystemClock>* result) { | |
1249 | auto clock = SystemClock::Default(); | |
1250 | if (clock->IsInstanceOf(value)) { | |
1251 | *result = clock; | |
1252 | return Status::OK(); | |
1253 | } else { | |
1254 | #ifndef ROCKSDB_LITE | |
1255 | static std::once_flag once; | |
1256 | std::call_once(once, [&]() { | |
1257 | RegisterBuiltinSystemClocks(*(ObjectLibrary::Default().get()), ""); | |
1258 | }); | |
1259 | #endif // ROCKSDB_LITE | |
1260 | return LoadSharedObject<SystemClock>(config_options, value, nullptr, | |
1261 | result); | |
1262 | } | |
1263 | } | |
f67539c2 | 1264 | } // namespace ROCKSDB_NAMESPACE |