1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
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.
10 #include "rocksdb/env.h"
13 #include "options/db_options.h"
14 #include "port/port.h"
15 #include "port/sys_time.h"
16 #include "rocksdb/options.h"
17 #include "util/arena.h"
18 #include "util/autovector.h"
25 std::string
Env::PriorityToString(Env::Priority priority
) {
27 case Env::Priority::BOTTOM
:
29 case Env::Priority::LOW
:
31 case Env::Priority::HIGH
:
33 case Env::Priority::TOTAL
:
39 uint64_t Env::GetThreadID() const {
40 std::hash
<std::thread::id
> hasher
;
41 return hasher(std::this_thread::get_id());
44 Status
Env::ReuseWritableFile(const std::string
& fname
,
45 const std::string
& old_fname
,
46 unique_ptr
<WritableFile
>* result
,
47 const EnvOptions
& options
) {
48 Status s
= RenameFile(old_fname
, fname
);
52 return NewWritableFile(fname
, result
, options
);
55 Status
Env::GetChildrenFileAttributes(const std::string
& dir
,
56 std::vector
<FileAttributes
>* result
) {
57 assert(result
!= nullptr);
58 std::vector
<std::string
> child_fnames
;
59 Status s
= GetChildren(dir
, &child_fnames
);
63 result
->resize(child_fnames
.size());
64 size_t result_size
= 0;
65 for (size_t i
= 0; i
< child_fnames
.size(); ++i
) {
66 const std::string path
= dir
+ "/" + child_fnames
[i
];
67 if (!(s
= GetFileSize(path
, &(*result
)[result_size
].size_bytes
)).ok()) {
68 if (FileExists(path
).IsNotFound()) {
69 // The file may have been deleted since we listed the directory
74 (*result
)[result_size
].name
= std::move(child_fnames
[i
]);
77 result
->resize(result_size
);
81 SequentialFile::~SequentialFile() {
84 RandomAccessFile::~RandomAccessFile() {
87 WritableFile::~WritableFile() {
90 MemoryMappedFileBuffer::~MemoryMappedFileBuffer() {}
94 Status
Logger::Close() {
103 Status
Logger::CloseImpl() { return Status::NotSupported(); }
105 FileLock::~FileLock() {
108 void LogFlush(Logger
*info_log
) {
114 static void Logv(Logger
*info_log
, const char* format
, va_list ap
) {
115 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL
) {
116 info_log
->Logv(InfoLogLevel::INFO_LEVEL
, format
, ap
);
120 void Log(Logger
* info_log
, const char* format
, ...) {
122 va_start(ap
, format
);
123 Logv(info_log
, format
, ap
);
127 void Logger::Logv(const InfoLogLevel log_level
, const char* format
, va_list ap
) {
128 static const char* kInfoLogLevelNames
[5] = { "DEBUG", "INFO", "WARN",
130 if (log_level
< log_level_
) {
134 if (log_level
== InfoLogLevel::INFO_LEVEL
) {
135 // Doesn't print log level if it is INFO level.
136 // This is to avoid unexpected performance regression after we add
137 // the feature of log level. All the logs before we add the feature
138 // are INFO level. We don't want to add extra costs to those existing
142 char new_format
[500];
143 snprintf(new_format
, sizeof(new_format
) - 1, "[%s] %s",
144 kInfoLogLevelNames
[log_level
], format
);
145 Logv(new_format
, ap
);
149 static void Logv(const InfoLogLevel log_level
, Logger
*info_log
, const char *format
, va_list ap
) {
150 if (info_log
&& info_log
->GetInfoLogLevel() <= log_level
) {
151 if (log_level
== InfoLogLevel::HEADER_LEVEL
) {
152 info_log
->LogHeader(format
, ap
);
154 info_log
->Logv(log_level
, format
, ap
);
159 void Log(const InfoLogLevel log_level
, Logger
* info_log
, const char* format
,
162 va_start(ap
, format
);
163 Logv(log_level
, info_log
, format
, ap
);
167 static void Headerv(Logger
*info_log
, const char *format
, va_list ap
) {
169 info_log
->LogHeader(format
, ap
);
173 void Header(Logger
* info_log
, const char* format
, ...) {
175 va_start(ap
, format
);
176 Headerv(info_log
, format
, ap
);
180 static void Debugv(Logger
* info_log
, const char* format
, va_list ap
) {
181 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::DEBUG_LEVEL
) {
182 info_log
->Logv(InfoLogLevel::DEBUG_LEVEL
, format
, ap
);
186 void Debug(Logger
* info_log
, const char* format
, ...) {
188 va_start(ap
, format
);
189 Debugv(info_log
, format
, ap
);
193 static void Infov(Logger
* info_log
, const char* format
, va_list ap
) {
194 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL
) {
195 info_log
->Logv(InfoLogLevel::INFO_LEVEL
, format
, ap
);
199 void Info(Logger
* info_log
, const char* format
, ...) {
201 va_start(ap
, format
);
202 Infov(info_log
, format
, ap
);
206 static void Warnv(Logger
* info_log
, const char* format
, va_list ap
) {
207 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::WARN_LEVEL
) {
208 info_log
->Logv(InfoLogLevel::WARN_LEVEL
, format
, ap
);
212 void Warn(Logger
* info_log
, const char* format
, ...) {
214 va_start(ap
, format
);
215 Warnv(info_log
, format
, ap
);
219 static void Errorv(Logger
* info_log
, const char* format
, va_list ap
) {
220 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::ERROR_LEVEL
) {
221 info_log
->Logv(InfoLogLevel::ERROR_LEVEL
, format
, ap
);
225 void Error(Logger
* info_log
, const char* format
, ...) {
227 va_start(ap
, format
);
228 Errorv(info_log
, format
, ap
);
232 static void Fatalv(Logger
* info_log
, const char* format
, va_list ap
) {
233 if (info_log
&& info_log
->GetInfoLogLevel() <= InfoLogLevel::FATAL_LEVEL
) {
234 info_log
->Logv(InfoLogLevel::FATAL_LEVEL
, format
, ap
);
238 void Fatal(Logger
* info_log
, const char* format
, ...) {
240 va_start(ap
, format
);
241 Fatalv(info_log
, format
, ap
);
245 void LogFlush(const shared_ptr
<Logger
>& info_log
) {
246 LogFlush(info_log
.get());
249 void Log(const InfoLogLevel log_level
, const shared_ptr
<Logger
>& info_log
,
250 const char* format
, ...) {
252 va_start(ap
, format
);
253 Logv(log_level
, info_log
.get(), format
, ap
);
257 void Header(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
259 va_start(ap
, format
);
260 Headerv(info_log
.get(), format
, ap
);
264 void Debug(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
266 va_start(ap
, format
);
267 Debugv(info_log
.get(), format
, ap
);
271 void Info(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
273 va_start(ap
, format
);
274 Infov(info_log
.get(), format
, ap
);
278 void Warn(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
280 va_start(ap
, format
);
281 Warnv(info_log
.get(), format
, ap
);
285 void Error(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
287 va_start(ap
, format
);
288 Errorv(info_log
.get(), format
, ap
);
292 void Fatal(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
294 va_start(ap
, format
);
295 Fatalv(info_log
.get(), format
, ap
);
299 void Log(const shared_ptr
<Logger
>& info_log
, const char* format
, ...) {
301 va_start(ap
, format
);
302 Logv(info_log
.get(), format
, ap
);
306 Status
WriteStringToFile(Env
* env
, const Slice
& data
, const std::string
& fname
,
308 unique_ptr
<WritableFile
> file
;
310 Status s
= env
->NewWritableFile(fname
, &file
, soptions
);
314 s
= file
->Append(data
);
315 if (s
.ok() && should_sync
) {
319 env
->DeleteFile(fname
);
324 Status
ReadFileToString(Env
* env
, const std::string
& fname
, std::string
* data
) {
327 unique_ptr
<SequentialFile
> file
;
328 Status s
= env
->NewSequentialFile(fname
, &file
, soptions
);
332 static const int kBufferSize
= 8192;
333 char* space
= new char[kBufferSize
];
336 s
= file
->Read(kBufferSize
, &fragment
, space
);
340 data
->append(fragment
.data(), fragment
.size());
341 if (fragment
.empty()) {
349 EnvWrapper::~EnvWrapper() {
352 namespace { // anonymous namespace
354 void AssignEnvOptions(EnvOptions
* env_options
, const DBOptions
& options
) {
355 env_options
->use_mmap_reads
= options
.allow_mmap_reads
;
356 env_options
->use_mmap_writes
= options
.allow_mmap_writes
;
357 env_options
->use_direct_reads
= options
.use_direct_reads
;
358 env_options
->set_fd_cloexec
= options
.is_fd_close_on_exec
;
359 env_options
->bytes_per_sync
= options
.bytes_per_sync
;
360 env_options
->compaction_readahead_size
= options
.compaction_readahead_size
;
361 env_options
->random_access_max_buffer_size
=
362 options
.random_access_max_buffer_size
;
363 env_options
->rate_limiter
= options
.rate_limiter
.get();
364 env_options
->writable_file_max_buffer_size
=
365 options
.writable_file_max_buffer_size
;
366 env_options
->allow_fallocate
= options
.allow_fallocate
;
371 EnvOptions
Env::OptimizeForLogWrite(const EnvOptions
& env_options
,
372 const DBOptions
& db_options
) const {
373 EnvOptions
optimized_env_options(env_options
);
374 optimized_env_options
.bytes_per_sync
= db_options
.wal_bytes_per_sync
;
375 optimized_env_options
.writable_file_max_buffer_size
=
376 db_options
.writable_file_max_buffer_size
;
377 return optimized_env_options
;
380 EnvOptions
Env::OptimizeForManifestWrite(const EnvOptions
& env_options
) const {
384 EnvOptions
Env::OptimizeForLogRead(const EnvOptions
& env_options
) const {
385 EnvOptions
optimized_env_options(env_options
);
386 optimized_env_options
.use_direct_reads
= false;
387 return optimized_env_options
;
390 EnvOptions
Env::OptimizeForManifestRead(const EnvOptions
& env_options
) const {
391 EnvOptions
optimized_env_options(env_options
);
392 optimized_env_options
.use_direct_reads
= false;
393 return optimized_env_options
;
396 EnvOptions
Env::OptimizeForCompactionTableWrite(
397 const EnvOptions
& env_options
, const ImmutableDBOptions
& db_options
) const {
398 EnvOptions
optimized_env_options(env_options
);
399 optimized_env_options
.use_direct_writes
=
400 db_options
.use_direct_io_for_flush_and_compaction
;
401 return optimized_env_options
;
404 EnvOptions
Env::OptimizeForCompactionTableRead(
405 const EnvOptions
& env_options
, const ImmutableDBOptions
& db_options
) const {
406 EnvOptions
optimized_env_options(env_options
);
407 optimized_env_options
.use_direct_reads
= db_options
.use_direct_reads
;
408 return optimized_env_options
;
411 EnvOptions::EnvOptions(const DBOptions
& options
) {
412 AssignEnvOptions(this, options
);
415 EnvOptions::EnvOptions() {
417 AssignEnvOptions(this, options
);
421 } // namespace rocksdb