/src/rocksdb/logging/auto_roll_logger.h
Line | Count | Source |
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). |
5 | | // |
6 | | // Logger implementation that can be shared by all environments |
7 | | // where enough posix functionality is available. |
8 | | |
9 | | #pragma once |
10 | | #include <list> |
11 | | #include <queue> |
12 | | #include <string> |
13 | | |
14 | | #include "file/filename.h" |
15 | | #include "port/port.h" |
16 | | #include "port/util_logger.h" |
17 | | #include "test_util/sync_point.h" |
18 | | #include "util/mutexlock.h" |
19 | | |
20 | | namespace ROCKSDB_NAMESPACE { |
21 | | class FileSystem; |
22 | | class SystemClock; |
23 | | |
24 | | // Rolls the log file by size and/or time |
25 | | class AutoRollLogger : public Logger { |
26 | | public: |
27 | | AutoRollLogger(const std::shared_ptr<FileSystem>& fs, |
28 | | const std::shared_ptr<SystemClock>& clock, |
29 | | const std::string& dbname, const std::string& db_log_dir, |
30 | | size_t log_max_size, size_t log_file_time_to_roll, |
31 | | size_t keep_log_file_num, |
32 | | const InfoLogLevel log_level = InfoLogLevel::INFO_LEVEL); |
33 | | |
34 | | using Logger::Logv; |
35 | | void Logv(const char* format, va_list ap) override; |
36 | | |
37 | | // Write a header entry to the log. All header information will be written |
38 | | // again every time the log rolls over. |
39 | | void LogHeader(const char* format, va_list ap) override; |
40 | | |
41 | | // check if the logger has encountered any problem. |
42 | 0 | Status GetStatus() { return status_; } |
43 | | |
44 | 0 | size_t GetLogFileSize() const override { |
45 | 0 | std::shared_ptr<Logger> logger; |
46 | 0 | { |
47 | 0 | MutexLock l(&mutex_); |
48 | 0 | if (!logger_) { |
49 | 0 | return 0; |
50 | 0 | } |
51 | | // pin down the current logger_ instance before releasing the mutex. |
52 | 0 | logger = logger_; |
53 | 0 | } |
54 | 0 | return logger->GetLogFileSize(); |
55 | 0 | } |
56 | | |
57 | 0 | void Flush() override { |
58 | 0 | std::shared_ptr<Logger> logger; |
59 | 0 | { |
60 | 0 | MutexLock l(&mutex_); |
61 | | // pin down the current logger_ instance before releasing the mutex. |
62 | 0 | logger = logger_; |
63 | 0 | } |
64 | 0 | TEST_SYNC_POINT("AutoRollLogger::Flush:PinnedLogger"); |
65 | 0 | if (logger) { |
66 | 0 | logger->Flush(); |
67 | 0 | } |
68 | 0 | } |
69 | | |
70 | 0 | virtual ~AutoRollLogger() { |
71 | 0 | if (logger_ && !closed_) { |
72 | 0 | logger_->Close().PermitUncheckedError(); |
73 | 0 | } |
74 | 0 | status_.PermitUncheckedError(); |
75 | 0 | } |
76 | | |
77 | | using Logger::GetInfoLogLevel; |
78 | 0 | InfoLogLevel GetInfoLogLevel() const override { |
79 | 0 | MutexLock l(&mutex_); |
80 | 0 | if (!logger_) { |
81 | 0 | return Logger::GetInfoLogLevel(); |
82 | 0 | } |
83 | 0 | return logger_->GetInfoLogLevel(); |
84 | 0 | } |
85 | | |
86 | | using Logger::SetInfoLogLevel; |
87 | 0 | void SetInfoLogLevel(const InfoLogLevel log_level) override { |
88 | 0 | MutexLock lock(&mutex_); |
89 | 0 | Logger::SetInfoLogLevel(log_level); |
90 | 0 | if (logger_) { |
91 | 0 | logger_->SetInfoLogLevel(log_level); |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | 0 | void SetCallNowMicrosEveryNRecords(uint64_t call_NowMicros_every_N_records) { |
96 | 0 | call_NowMicros_every_N_records_ = call_NowMicros_every_N_records; |
97 | 0 | } |
98 | | |
99 | | // Expose the log file path for testing purpose |
100 | 0 | std::string TEST_log_fname() const { return log_fname_; } |
101 | | |
102 | 0 | uint64_t TEST_ctime() const { return ctime_; } |
103 | | |
104 | 0 | Logger* TEST_inner_logger() const { return logger_.get(); } |
105 | | |
106 | | protected: |
107 | | // Implementation of Close() |
108 | 0 | Status CloseImpl() override { |
109 | 0 | if (logger_) { |
110 | 0 | return logger_->Close(); |
111 | 0 | } else { |
112 | 0 | return Status::OK(); |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | | private: |
117 | | bool LogExpired(); |
118 | | Status ResetLogger(); |
119 | | void RollLogFile(); |
120 | | // Read all names of old log files into old_log_files_ |
121 | | // If there is any error, put the error code in status_ |
122 | | void GetExistingFiles(); |
123 | | // Delete old log files if it excceeds the limit. |
124 | | Status TrimOldLogFiles(); |
125 | | // Log message to logger without rolling |
126 | | void LogInternal(const char* format, ...); |
127 | | // Serialize the va_list to a string |
128 | | std::string ValistToString(const char* format, va_list args) const; |
129 | | // Write the logs marked as headers to the new log file |
130 | | void WriteHeaderInfo(); |
131 | | std::string log_fname_; // Current active info log's file name. |
132 | | std::string dbname_; |
133 | | std::string db_log_dir_; |
134 | | std::string db_absolute_path_; |
135 | | std::shared_ptr<FileSystem> fs_; |
136 | | std::shared_ptr<SystemClock> clock_; |
137 | | std::shared_ptr<Logger> logger_; |
138 | | // current status of the logger |
139 | | Status status_; |
140 | | const size_t kMaxLogFileSize; |
141 | | const size_t kLogFileTimeToRoll; |
142 | | const size_t kKeepLogFileNum; |
143 | | // header information |
144 | | std::list<std::string> headers_; |
145 | | // List of all existing info log files. Used for enforcing number of |
146 | | // info log files. |
147 | | // Full path is stored here. It consumes signifianctly more memory |
148 | | // than only storing file name. Can optimize if it causes a problem. |
149 | | std::queue<std::string> old_log_files_; |
150 | | // to avoid frequent clock->NowMicros() calls, we cached the current time |
151 | | uint64_t cached_now; |
152 | | uint64_t ctime_; |
153 | | uint64_t cached_now_access_count; |
154 | | uint64_t call_NowMicros_every_N_records_; |
155 | | IOOptions io_options_; |
156 | | IODebugContext io_context_; |
157 | | mutable port::Mutex mutex_; |
158 | | }; |
159 | | |
160 | | // Facade to craete logger automatically |
161 | | Status CreateLoggerFromOptions(const std::string& dbname, |
162 | | const DBOptions& options, |
163 | | std::shared_ptr<Logger>* logger); |
164 | | |
165 | | } // namespace ROCKSDB_NAMESPACE |