]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/env/env.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / env / env.cc
CommitLineData
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 30namespace ROCKSDB_NAMESPACE {
1e59de90
TL
31namespace {
32#ifndef ROCKSDB_LITE
33static 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
53static 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
62class 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
111class 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
142class 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
201class 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
241class 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
344class 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
365class 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
622Env::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
627Env::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
632Env::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
636Env::~Env() {}
637
f67539c2
TL
638Status Env::NewLogger(const std::string& fname,
639 std::shared_ptr<Logger>* result) {
640 return NewEnvLogger(fname, this, result);
641}
642
643Status Env::LoadEnv(const std::string& value, Env** result) {
1e59de90
TL
644 return CreateFromString(ConfigOptions(), value, result);
645}
646
647Status 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
664Status 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
669Status 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
711Status 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
735std::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
751uint64_t Env::GetThreadID() const {
752 std::hash<std::thread::id> hasher;
753 return hasher(std::this_thread::get_id());
754}
755
756Status 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
767Status 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 793Status 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
803std::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 843SequentialFile::~SequentialFile() {}
7c673cae 844
1e59de90
TL
845RandomAccessFile::~RandomAccessFile() {}
846
847WritableFile::~WritableFile() {}
7c673cae 848
11fdf7f2
TL
849MemoryMappedFileBuffer::~MemoryMappedFileBuffer() {}
850
851Logger::~Logger() {}
852
853Status Logger::Close() {
854 if (!closed_) {
855 closed_ = true;
856 return CloseImpl();
857 } else {
858 return Status::OK();
859 }
7c673cae
FG
860}
861
11fdf7f2
TL
862Status Logger::CloseImpl() { return Status::NotSupported(); }
863
1e59de90 864FileLock::~FileLock() {}
7c673cae 865
1e59de90 866void LogFlush(Logger* info_log) {
7c673cae
FG
867 if (info_log) {
868 info_log->Flush();
869 }
870}
871
1e59de90 872static 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
878void 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
885void 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
918static 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
929void 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 937static 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
943void 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
950static 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
956void 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
963static 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
969void 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
976static 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
982void 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
989static 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
995void 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
1002static 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
1008void 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 1015void LogFlush(const std::shared_ptr<Logger>& info_log) {
11fdf7f2 1016 LogFlush(info_log.get());
7c673cae
FG
1017}
1018
494da23a 1019void 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 1027void 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 1034void 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 1041void 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 1048void 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 1055void 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 1062void 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 1069void 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
1076Status 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
1082Status 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
1087namespace { // anonymous namespace
1088
1089void 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
1108EnvOptions 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
1117EnvOptions Env::OptimizeForManifestWrite(const EnvOptions& env_options) const {
1118 return env_options;
1119}
1120
11fdf7f2
TL
1121EnvOptions 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
1127EnvOptions 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
1133EnvOptions 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
1141EnvOptions 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
1147EnvOptions 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
1154EnvOptions::EnvOptions(const DBOptions& options) {
1155 AssignEnvOptions(this, options);
1156}
1157
1158EnvOptions::EnvOptions() {
1159 DBOptions options;
1160 AssignEnvOptions(this, options);
1161}
1162
f67539c2
TL
1163Status 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
1180const std::shared_ptr<FileSystem>& Env::GetFileSystem() const {
1181 return file_system_;
1182}
1183
1e59de90
TL
1184const std::shared_ptr<SystemClock>& Env::GetSystemClock() const {
1185 return system_clock_;
1186}
1187namespace {
1188static 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
1197SystemClockWrapper::SystemClockWrapper(const std::shared_ptr<SystemClock>& t)
1198 : target_(t) {
1199 RegisterOptions("", &target_, &sc_wrapper_type_info);
1200}
1201
1202Status 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
1210std::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
1232static 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
1246Status 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