]>
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> | |
f67539c2 TL |
13 | #include "env/composite_env_wrapper.h" |
14 | #include "logging/env_logger.h" | |
15 | #include "memory/arena.h" | |
7c673cae FG |
16 | #include "options/db_options.h" |
17 | #include "port/port.h" | |
18 | #include "port/sys_time.h" | |
19 | #include "rocksdb/options.h" | |
f67539c2 | 20 | #include "rocksdb/utilities/object_registry.h" |
7c673cae FG |
21 | #include "util/autovector.h" |
22 | ||
f67539c2 | 23 | namespace ROCKSDB_NAMESPACE { |
7c673cae FG |
24 | |
25 | Env::~Env() { | |
26 | } | |
27 | ||
f67539c2 TL |
28 | Status Env::NewLogger(const std::string& fname, |
29 | std::shared_ptr<Logger>* result) { | |
30 | return NewEnvLogger(fname, this, result); | |
31 | } | |
32 | ||
33 | Status Env::LoadEnv(const std::string& value, Env** result) { | |
34 | Env* env = *result; | |
35 | Status s; | |
36 | #ifndef ROCKSDB_LITE | |
37 | s = ObjectRegistry::NewInstance()->NewStaticObject<Env>(value, &env); | |
38 | #else | |
39 | s = Status::NotSupported("Cannot load environment in LITE mode: ", value); | |
40 | #endif | |
41 | if (s.ok()) { | |
42 | *result = env; | |
43 | } | |
44 | return s; | |
45 | } | |
46 | ||
47 | Status Env::LoadEnv(const std::string& value, Env** result, | |
48 | std::shared_ptr<Env>* guard) { | |
49 | assert(result); | |
50 | Status s; | |
51 | #ifndef ROCKSDB_LITE | |
52 | Env* env = nullptr; | |
53 | std::unique_ptr<Env> uniq_guard; | |
54 | std::string err_msg; | |
55 | assert(guard != nullptr); | |
56 | env = ObjectRegistry::NewInstance()->NewObject<Env>(value, &uniq_guard, | |
57 | &err_msg); | |
58 | if (!env) { | |
59 | s = Status::NotFound(std::string("Cannot load ") + Env::Type() + ": " + | |
60 | value); | |
61 | env = Env::Default(); | |
62 | } | |
63 | if (s.ok() && uniq_guard) { | |
64 | guard->reset(uniq_guard.release()); | |
65 | *result = guard->get(); | |
66 | } else { | |
67 | *result = env; | |
68 | } | |
69 | #else | |
70 | (void)result; | |
71 | (void)guard; | |
72 | s = Status::NotSupported("Cannot load environment in LITE mode: ", value); | |
73 | #endif | |
74 | return s; | |
75 | } | |
76 | ||
11fdf7f2 TL |
77 | std::string Env::PriorityToString(Env::Priority priority) { |
78 | switch (priority) { | |
79 | case Env::Priority::BOTTOM: | |
80 | return "Bottom"; | |
81 | case Env::Priority::LOW: | |
82 | return "Low"; | |
83 | case Env::Priority::HIGH: | |
84 | return "High"; | |
494da23a TL |
85 | case Env::Priority::USER: |
86 | return "User"; | |
11fdf7f2 TL |
87 | case Env::Priority::TOTAL: |
88 | assert(false); | |
89 | } | |
90 | return "Invalid"; | |
91 | } | |
92 | ||
7c673cae FG |
93 | uint64_t Env::GetThreadID() const { |
94 | std::hash<std::thread::id> hasher; | |
95 | return hasher(std::this_thread::get_id()); | |
96 | } | |
97 | ||
98 | Status Env::ReuseWritableFile(const std::string& fname, | |
99 | const std::string& old_fname, | |
494da23a | 100 | std::unique_ptr<WritableFile>* result, |
7c673cae FG |
101 | const EnvOptions& options) { |
102 | Status s = RenameFile(old_fname, fname); | |
103 | if (!s.ok()) { | |
104 | return s; | |
105 | } | |
106 | return NewWritableFile(fname, result, options); | |
107 | } | |
108 | ||
109 | Status Env::GetChildrenFileAttributes(const std::string& dir, | |
110 | std::vector<FileAttributes>* result) { | |
111 | assert(result != nullptr); | |
112 | std::vector<std::string> child_fnames; | |
113 | Status s = GetChildren(dir, &child_fnames); | |
114 | if (!s.ok()) { | |
115 | return s; | |
116 | } | |
117 | result->resize(child_fnames.size()); | |
118 | size_t result_size = 0; | |
119 | for (size_t i = 0; i < child_fnames.size(); ++i) { | |
120 | const std::string path = dir + "/" + child_fnames[i]; | |
121 | if (!(s = GetFileSize(path, &(*result)[result_size].size_bytes)).ok()) { | |
122 | if (FileExists(path).IsNotFound()) { | |
123 | // The file may have been deleted since we listed the directory | |
124 | continue; | |
125 | } | |
126 | return s; | |
127 | } | |
128 | (*result)[result_size].name = std::move(child_fnames[i]); | |
129 | result_size++; | |
130 | } | |
131 | result->resize(result_size); | |
132 | return Status::OK(); | |
133 | } | |
134 | ||
135 | SequentialFile::~SequentialFile() { | |
136 | } | |
137 | ||
138 | RandomAccessFile::~RandomAccessFile() { | |
139 | } | |
140 | ||
141 | WritableFile::~WritableFile() { | |
142 | } | |
143 | ||
11fdf7f2 TL |
144 | MemoryMappedFileBuffer::~MemoryMappedFileBuffer() {} |
145 | ||
146 | Logger::~Logger() {} | |
147 | ||
148 | Status Logger::Close() { | |
149 | if (!closed_) { | |
150 | closed_ = true; | |
151 | return CloseImpl(); | |
152 | } else { | |
153 | return Status::OK(); | |
154 | } | |
7c673cae FG |
155 | } |
156 | ||
11fdf7f2 TL |
157 | Status Logger::CloseImpl() { return Status::NotSupported(); } |
158 | ||
7c673cae FG |
159 | FileLock::~FileLock() { |
160 | } | |
161 | ||
162 | void LogFlush(Logger *info_log) { | |
163 | if (info_log) { | |
164 | info_log->Flush(); | |
165 | } | |
166 | } | |
167 | ||
11fdf7f2 | 168 | static void Logv(Logger *info_log, const char* format, va_list ap) { |
7c673cae | 169 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL) { |
7c673cae | 170 | info_log->Logv(InfoLogLevel::INFO_LEVEL, format, ap); |
7c673cae FG |
171 | } |
172 | } | |
173 | ||
11fdf7f2 TL |
174 | void Log(Logger* info_log, const char* format, ...) { |
175 | va_list ap; | |
176 | va_start(ap, format); | |
177 | Logv(info_log, format, ap); | |
178 | va_end(ap); | |
179 | } | |
180 | ||
7c673cae FG |
181 | void Logger::Logv(const InfoLogLevel log_level, const char* format, va_list ap) { |
182 | static const char* kInfoLogLevelNames[5] = { "DEBUG", "INFO", "WARN", | |
183 | "ERROR", "FATAL" }; | |
184 | if (log_level < log_level_) { | |
185 | return; | |
186 | } | |
187 | ||
188 | if (log_level == InfoLogLevel::INFO_LEVEL) { | |
189 | // Doesn't print log level if it is INFO level. | |
190 | // This is to avoid unexpected performance regression after we add | |
191 | // the feature of log level. All the logs before we add the feature | |
192 | // are INFO level. We don't want to add extra costs to those existing | |
193 | // logging. | |
194 | Logv(format, ap); | |
494da23a TL |
195 | } else if (log_level == InfoLogLevel::HEADER_LEVEL) { |
196 | LogHeader(format, ap); | |
7c673cae FG |
197 | } else { |
198 | char new_format[500]; | |
199 | snprintf(new_format, sizeof(new_format) - 1, "[%s] %s", | |
200 | kInfoLogLevelNames[log_level], format); | |
201 | Logv(new_format, ap); | |
202 | } | |
203 | } | |
204 | ||
11fdf7f2 | 205 | static void Logv(const InfoLogLevel log_level, Logger *info_log, const char *format, va_list ap) { |
7c673cae | 206 | if (info_log && info_log->GetInfoLogLevel() <= log_level) { |
7c673cae FG |
207 | if (log_level == InfoLogLevel::HEADER_LEVEL) { |
208 | info_log->LogHeader(format, ap); | |
209 | } else { | |
210 | info_log->Logv(log_level, format, ap); | |
211 | } | |
7c673cae FG |
212 | } |
213 | } | |
214 | ||
11fdf7f2 TL |
215 | void Log(const InfoLogLevel log_level, Logger* info_log, const char* format, |
216 | ...) { | |
217 | va_list ap; | |
218 | va_start(ap, format); | |
219 | Logv(log_level, info_log, format, ap); | |
220 | va_end(ap); | |
221 | } | |
222 | ||
223 | static void Headerv(Logger *info_log, const char *format, va_list ap) { | |
7c673cae | 224 | if (info_log) { |
7c673cae | 225 | info_log->LogHeader(format, ap); |
7c673cae FG |
226 | } |
227 | } | |
228 | ||
11fdf7f2 TL |
229 | void Header(Logger* info_log, const char* format, ...) { |
230 | va_list ap; | |
231 | va_start(ap, format); | |
232 | Headerv(info_log, format, ap); | |
233 | va_end(ap); | |
234 | } | |
235 | ||
236 | static void Debugv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 237 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::DEBUG_LEVEL) { |
7c673cae | 238 | info_log->Logv(InfoLogLevel::DEBUG_LEVEL, format, ap); |
7c673cae FG |
239 | } |
240 | } | |
241 | ||
11fdf7f2 TL |
242 | void Debug(Logger* info_log, const char* format, ...) { |
243 | va_list ap; | |
244 | va_start(ap, format); | |
245 | Debugv(info_log, format, ap); | |
246 | va_end(ap); | |
247 | } | |
248 | ||
249 | static void Infov(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 250 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::INFO_LEVEL) { |
7c673cae | 251 | info_log->Logv(InfoLogLevel::INFO_LEVEL, format, ap); |
7c673cae FG |
252 | } |
253 | } | |
254 | ||
11fdf7f2 TL |
255 | void Info(Logger* info_log, const char* format, ...) { |
256 | va_list ap; | |
257 | va_start(ap, format); | |
258 | Infov(info_log, format, ap); | |
259 | va_end(ap); | |
260 | } | |
261 | ||
262 | static void Warnv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 263 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::WARN_LEVEL) { |
7c673cae | 264 | info_log->Logv(InfoLogLevel::WARN_LEVEL, format, ap); |
7c673cae FG |
265 | } |
266 | } | |
11fdf7f2 TL |
267 | |
268 | void Warn(Logger* info_log, const char* format, ...) { | |
269 | va_list ap; | |
270 | va_start(ap, format); | |
271 | Warnv(info_log, format, ap); | |
272 | va_end(ap); | |
273 | } | |
274 | ||
275 | static void Errorv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 276 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::ERROR_LEVEL) { |
7c673cae | 277 | info_log->Logv(InfoLogLevel::ERROR_LEVEL, format, ap); |
7c673cae FG |
278 | } |
279 | } | |
11fdf7f2 TL |
280 | |
281 | void Error(Logger* info_log, const char* format, ...) { | |
282 | va_list ap; | |
283 | va_start(ap, format); | |
284 | Errorv(info_log, format, ap); | |
285 | va_end(ap); | |
286 | } | |
287 | ||
288 | static void Fatalv(Logger* info_log, const char* format, va_list ap) { | |
7c673cae | 289 | if (info_log && info_log->GetInfoLogLevel() <= InfoLogLevel::FATAL_LEVEL) { |
7c673cae | 290 | info_log->Logv(InfoLogLevel::FATAL_LEVEL, format, ap); |
7c673cae FG |
291 | } |
292 | } | |
293 | ||
11fdf7f2 TL |
294 | void Fatal(Logger* info_log, const char* format, ...) { |
295 | va_list ap; | |
296 | va_start(ap, format); | |
297 | Fatalv(info_log, format, ap); | |
298 | va_end(ap); | |
299 | } | |
300 | ||
494da23a | 301 | void LogFlush(const std::shared_ptr<Logger>& info_log) { |
11fdf7f2 | 302 | LogFlush(info_log.get()); |
7c673cae FG |
303 | } |
304 | ||
494da23a | 305 | void Log(const InfoLogLevel log_level, const std::shared_ptr<Logger>& info_log, |
7c673cae | 306 | const char* format, ...) { |
11fdf7f2 TL |
307 | va_list ap; |
308 | va_start(ap, format); | |
309 | Logv(log_level, info_log.get(), format, ap); | |
310 | va_end(ap); | |
7c673cae FG |
311 | } |
312 | ||
494da23a | 313 | void Header(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
314 | va_list ap; |
315 | va_start(ap, format); | |
316 | Headerv(info_log.get(), format, ap); | |
317 | va_end(ap); | |
7c673cae FG |
318 | } |
319 | ||
494da23a | 320 | void Debug(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
321 | va_list ap; |
322 | va_start(ap, format); | |
323 | Debugv(info_log.get(), format, ap); | |
324 | va_end(ap); | |
7c673cae FG |
325 | } |
326 | ||
494da23a | 327 | void Info(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
328 | va_list ap; |
329 | va_start(ap, format); | |
330 | Infov(info_log.get(), format, ap); | |
331 | va_end(ap); | |
7c673cae FG |
332 | } |
333 | ||
494da23a | 334 | void Warn(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
335 | va_list ap; |
336 | va_start(ap, format); | |
337 | Warnv(info_log.get(), format, ap); | |
338 | va_end(ap); | |
7c673cae FG |
339 | } |
340 | ||
494da23a | 341 | void Error(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
342 | va_list ap; |
343 | va_start(ap, format); | |
344 | Errorv(info_log.get(), format, ap); | |
345 | va_end(ap); | |
7c673cae FG |
346 | } |
347 | ||
494da23a | 348 | void Fatal(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
349 | va_list ap; |
350 | va_start(ap, format); | |
351 | Fatalv(info_log.get(), format, ap); | |
352 | va_end(ap); | |
7c673cae FG |
353 | } |
354 | ||
494da23a | 355 | void Log(const std::shared_ptr<Logger>& info_log, const char* format, ...) { |
11fdf7f2 TL |
356 | va_list ap; |
357 | va_start(ap, format); | |
358 | Logv(info_log.get(), format, ap); | |
359 | va_end(ap); | |
7c673cae FG |
360 | } |
361 | ||
362 | Status WriteStringToFile(Env* env, const Slice& data, const std::string& fname, | |
363 | bool should_sync) { | |
494da23a | 364 | std::unique_ptr<WritableFile> file; |
7c673cae FG |
365 | EnvOptions soptions; |
366 | Status s = env->NewWritableFile(fname, &file, soptions); | |
367 | if (!s.ok()) { | |
368 | return s; | |
369 | } | |
370 | s = file->Append(data); | |
371 | if (s.ok() && should_sync) { | |
372 | s = file->Sync(); | |
373 | } | |
374 | if (!s.ok()) { | |
375 | env->DeleteFile(fname); | |
376 | } | |
377 | return s; | |
378 | } | |
379 | ||
380 | Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { | |
f67539c2 TL |
381 | LegacyFileSystemWrapper lfsw(env); |
382 | return ReadFileToString(&lfsw, fname, data); | |
7c673cae FG |
383 | } |
384 | ||
385 | EnvWrapper::~EnvWrapper() { | |
386 | } | |
387 | ||
388 | namespace { // anonymous namespace | |
389 | ||
390 | void AssignEnvOptions(EnvOptions* env_options, const DBOptions& options) { | |
391 | env_options->use_mmap_reads = options.allow_mmap_reads; | |
392 | env_options->use_mmap_writes = options.allow_mmap_writes; | |
393 | env_options->use_direct_reads = options.use_direct_reads; | |
394 | env_options->set_fd_cloexec = options.is_fd_close_on_exec; | |
395 | env_options->bytes_per_sync = options.bytes_per_sync; | |
396 | env_options->compaction_readahead_size = options.compaction_readahead_size; | |
397 | env_options->random_access_max_buffer_size = | |
398 | options.random_access_max_buffer_size; | |
399 | env_options->rate_limiter = options.rate_limiter.get(); | |
400 | env_options->writable_file_max_buffer_size = | |
401 | options.writable_file_max_buffer_size; | |
402 | env_options->allow_fallocate = options.allow_fallocate; | |
f67539c2 TL |
403 | env_options->strict_bytes_per_sync = options.strict_bytes_per_sync; |
404 | options.env->SanitizeEnvOptions(env_options); | |
7c673cae FG |
405 | } |
406 | ||
407 | } | |
408 | ||
409 | EnvOptions Env::OptimizeForLogWrite(const EnvOptions& env_options, | |
410 | const DBOptions& db_options) const { | |
411 | EnvOptions optimized_env_options(env_options); | |
412 | optimized_env_options.bytes_per_sync = db_options.wal_bytes_per_sync; | |
11fdf7f2 TL |
413 | optimized_env_options.writable_file_max_buffer_size = |
414 | db_options.writable_file_max_buffer_size; | |
7c673cae FG |
415 | return optimized_env_options; |
416 | } | |
417 | ||
418 | EnvOptions Env::OptimizeForManifestWrite(const EnvOptions& env_options) const { | |
419 | return env_options; | |
420 | } | |
421 | ||
11fdf7f2 TL |
422 | EnvOptions Env::OptimizeForLogRead(const EnvOptions& env_options) const { |
423 | EnvOptions optimized_env_options(env_options); | |
424 | optimized_env_options.use_direct_reads = false; | |
425 | return optimized_env_options; | |
426 | } | |
427 | ||
428 | EnvOptions Env::OptimizeForManifestRead(const EnvOptions& env_options) const { | |
429 | EnvOptions optimized_env_options(env_options); | |
430 | optimized_env_options.use_direct_reads = false; | |
431 | return optimized_env_options; | |
432 | } | |
433 | ||
7c673cae FG |
434 | EnvOptions Env::OptimizeForCompactionTableWrite( |
435 | const EnvOptions& env_options, const ImmutableDBOptions& db_options) const { | |
436 | EnvOptions optimized_env_options(env_options); | |
437 | optimized_env_options.use_direct_writes = | |
438 | db_options.use_direct_io_for_flush_and_compaction; | |
439 | return optimized_env_options; | |
440 | } | |
441 | ||
442 | EnvOptions Env::OptimizeForCompactionTableRead( | |
443 | const EnvOptions& env_options, const ImmutableDBOptions& db_options) const { | |
444 | EnvOptions optimized_env_options(env_options); | |
11fdf7f2 | 445 | optimized_env_options.use_direct_reads = db_options.use_direct_reads; |
7c673cae FG |
446 | return optimized_env_options; |
447 | } | |
448 | ||
449 | EnvOptions::EnvOptions(const DBOptions& options) { | |
450 | AssignEnvOptions(this, options); | |
451 | } | |
452 | ||
453 | EnvOptions::EnvOptions() { | |
454 | DBOptions options; | |
455 | AssignEnvOptions(this, options); | |
456 | } | |
457 | ||
f67539c2 TL |
458 | Status NewEnvLogger(const std::string& fname, Env* env, |
459 | std::shared_ptr<Logger>* result) { | |
460 | EnvOptions options; | |
461 | // TODO: Tune the buffer size. | |
462 | options.writable_file_max_buffer_size = 1024 * 1024; | |
463 | std::unique_ptr<WritableFile> writable_file; | |
464 | const auto status = env->NewWritableFile(fname, &writable_file, options); | |
465 | if (!status.ok()) { | |
466 | return status; | |
467 | } | |
468 | ||
469 | *result = std::make_shared<EnvLogger>( | |
470 | NewLegacyWritableFileWrapper(std::move(writable_file)), fname, options, | |
471 | env); | |
472 | return Status::OK(); | |
473 | } | |
7c673cae | 474 | |
f67539c2 | 475 | } // namespace ROCKSDB_NAMESPACE |