Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chrome/browser/chromeos/system_logs/single_log_source.cc

Issue 2940493002: SingleLogSource handles rotation of log files (Closed)
Patch Set: Use constexpr; Rename bool; Simplify logic Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/system_logs/single_log_source.h" 5 #include "chrome/browser/chromeos/system_logs/single_log_source.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/task_scheduler/post_task.h" 9 #include "base/task_scheduler/post_task.h"
10 #include "content/public/browser/browser_thread.h" 10 #include "content/public/browser/browser_thread.h"
11 11
12 namespace system_logs { 12 namespace system_logs {
13 13
14 namespace { 14 namespace {
15 15
16 const char kDefaultSystemLogDirPath[] = "/var/log"; 16 constexpr char kDefaultSystemLogDirPath[] = "/var/log";
17 constexpr int kMaxNumAllowedLogRotationsDuringFileRead = 3;
17 18
18 // Converts a logs source type to the corresponding file path, relative to the 19 // Converts a logs source type to the corresponding file path, relative to the
19 // base system log directory path. In the future, if non-file source types are 20 // base system log directory path. In the future, if non-file source types are
20 // added, this function should return an empty file path. 21 // added, this function should return an empty file path.
21 base::FilePath GetLogFileSourceRelativeFilePath( 22 base::FilePath GetLogFileSourceRelativeFilePath(
22 SingleLogSource::SupportedSource source) { 23 SingleLogSource::SupportedSource source) {
23 switch (source) { 24 switch (source) {
24 case SingleLogSource::SupportedSource::kMessages: 25 case SingleLogSource::SupportedSource::kMessages:
25 return base::FilePath("messages"); 26 return base::FilePath("messages");
26 case SingleLogSource::SupportedSource::kUiLatest: 27 case SingleLogSource::SupportedSource::kUiLatest:
27 return base::FilePath("ui/ui.LATEST"); 28 return base::FilePath("ui/ui.LATEST");
28 } 29 }
29 NOTREACHED(); 30 NOTREACHED();
30 return base::FilePath(); 31 return base::FilePath();
31 } 32 }
32 33
34 // Returns the inode value of file at |path|, or 0 if it doesn't exist or is
35 // otherwise unable to be accessed for file system info.
36 ino_t GetInodeValue(const base::FilePath& path) {
37 struct stat file_stats;
38 if (stat(path.value().c_str(), &file_stats) != 0)
39 return 0;
40 return file_stats.st_ino;
41 }
42
33 // Attempts to store a string |value| in |*response| under |key|. If there is 43 // Attempts to store a string |value| in |*response| under |key|. If there is
34 // already a string in |*response| under |key|, appends |value| to the existing 44 // already a string in |*response| under |key|, appends |value| to the existing
35 // string value. 45 // string value.
36 void AppendToSystemLogsResponse(SystemLogsResponse* response, 46 void AppendToSystemLogsResponse(SystemLogsResponse* response,
37 const std::string& key, 47 const std::string& key,
38 const std::string& value) { 48 const std::string& value) {
39 auto iter = response->find(key); 49 auto iter = response->find(key);
40 if (iter == response->end()) 50 if (iter == response->end())
41 response->emplace(key, value); 51 response->emplace(key, value);
42 else 52 else
43 iter->second += value; 53 iter->second += value;
44 } 54 }
45 55
46 } // namespace 56 } // namespace
47 57
48 SingleLogSource::SingleLogSource(SupportedSource source) 58 SingleLogSource::SingleLogSource(SupportedSource source)
49 : SystemLogsSource(GetLogFileSourceRelativeFilePath(source).value()), 59 : SystemLogsSource(GetLogFileSourceRelativeFilePath(source).value()),
50 log_file_dir_path_(kDefaultSystemLogDirPath), 60 log_file_dir_path_(kDefaultSystemLogDirPath),
51 num_bytes_read_(0), 61 num_bytes_read_(0),
62 file_inode_(0),
52 weak_ptr_factory_(this) {} 63 weak_ptr_factory_(this) {}
53 64
54 SingleLogSource::~SingleLogSource() {} 65 SingleLogSource::~SingleLogSource() {}
55 66
56 void SingleLogSource::Fetch(const SysLogsSourceCallback& callback) { 67 void SingleLogSource::Fetch(const SysLogsSourceCallback& callback) {
57 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 68 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
58 DCHECK(!callback.is_null()); 69 DCHECK(!callback.is_null());
59 70
60 SystemLogsResponse* response = new SystemLogsResponse; 71 SystemLogsResponse* response = new SystemLogsResponse;
61 base::PostTaskWithTraitsAndReply( 72 base::PostTaskWithTraitsAndReply(
62 FROM_HERE, 73 FROM_HERE,
63 base::TaskTraits(base::MayBlock(), base::TaskPriority::BACKGROUND), 74 base::TaskTraits(base::MayBlock(), base::TaskPriority::BACKGROUND),
64 base::Bind(&SingleLogSource::ReadFile, weak_ptr_factory_.GetWeakPtr(), 75 base::Bind(&SingleLogSource::ReadFile, weak_ptr_factory_.GetWeakPtr(),
65 response), 76 kMaxNumAllowedLogRotationsDuringFileRead, response),
66 base::Bind(callback, base::Owned(response))); 77 base::Bind(callback, base::Owned(response)));
67 } 78 }
68 79
69 void SingleLogSource::ReadFile(SystemLogsResponse* result) { 80 base::FilePath SingleLogSource::GetLogFilePath() const {
81 return base::FilePath(log_file_dir_path_).Append(source_name());
82 }
83
84 void SingleLogSource::ReadFile(size_t num_rotations_allowed,
85 SystemLogsResponse* result) {
70 // Attempt to open the file if it was not previously opened. 86 // Attempt to open the file if it was not previously opened.
71 if (!file_.IsValid()) { 87 if (!file_.IsValid()) {
72 file_.Initialize(base::FilePath(log_file_dir_path_).Append(source_name()), 88 file_.Initialize(GetLogFilePath(),
73 base::File::FLAG_OPEN | base::File::FLAG_READ); 89 base::File::FLAG_OPEN | base::File::FLAG_READ);
74 if (!file_.IsValid()) 90 if (!file_.IsValid())
75 return; 91 return;
92
93 file_inode_ = GetInodeValue(GetLogFilePath());
76 } 94 }
77 95
78 // Check for file size reset. 96 // Check for file size reset.
79 const size_t length = file_.GetLength(); 97 const size_t length = file_.GetLength();
80 if (length < num_bytes_read_) { 98 if (length < num_bytes_read_) {
81 num_bytes_read_ = 0; 99 num_bytes_read_ = 0;
82 file_.Seek(base::File::FROM_BEGIN, 0); 100 file_.Seek(base::File::FROM_BEGIN, 0);
83 } 101 }
84 102
85 // Read from file until end. 103 // Read from file until end.
86 const size_t size_to_read = length - num_bytes_read_; 104 const size_t size_to_read = length - num_bytes_read_;
87 std::string result_string; 105 std::string result_string;
88 result_string.resize(size_to_read); 106 result_string.resize(size_to_read);
89 size_t size_read = file_.ReadAtCurrentPos(&result_string[0], size_to_read); 107 size_t size_read = file_.ReadAtCurrentPos(&result_string[0], size_to_read);
90 result_string.resize(size_read); 108 result_string.resize(size_read);
91 109
92 // The reader may only read complete lines. 110 const bool file_was_rotated = file_inode_ != GetInodeValue(GetLogFilePath());
93 if (result_string.empty() || result_string.back() != '\n') { 111 const bool should_handle_file_rotation =
112 file_was_rotated && num_rotations_allowed > 0;
113
114 // The reader may only read complete lines. The exception is when there is a
115 // rotation, in which case all the remaining contents of the old log file
116 // should be read before moving on to read the new log file.
117 if ((result_string.empty() || result_string.back() != '\n') &&
118 !should_handle_file_rotation) {
94 // If an incomplete line was read, return only the part that includes whole 119 // If an incomplete line was read, return only the part that includes whole
95 // lines. 120 // lines.
96 size_t last_newline_pos = result_string.find_last_of('\n'); 121 size_t last_newline_pos = result_string.find_last_of('\n');
97 if (last_newline_pos == std::string::npos) { 122 if (last_newline_pos == std::string::npos) {
98 file_.Seek(base::File::FROM_CURRENT, -size_read); 123 file_.Seek(base::File::FROM_CURRENT, -size_read);
99 AppendToSystemLogsResponse(result, source_name(), ""); 124 AppendToSystemLogsResponse(result, source_name(), "");
100 return; 125 return;
101 } 126 }
102 // The part of the string that will be returned includes the newline itself. 127 // The part of the string that will be returned includes the newline itself.
103 size_t adjusted_size_read = last_newline_pos + 1; 128 size_t adjusted_size_read = last_newline_pos + 1;
104 file_.Seek(base::File::FROM_CURRENT, -size_read + adjusted_size_read); 129 file_.Seek(base::File::FROM_CURRENT, -size_read + adjusted_size_read);
105 result_string.resize(adjusted_size_read); 130 result_string.resize(adjusted_size_read);
106 131
107 // Update |size_read| to reflect that the read was only up to the last 132 // Update |size_read| to reflect that the read was only up to the last
108 // newline. 133 // newline.
109 size_read = adjusted_size_read; 134 size_read = adjusted_size_read;
110 } 135 }
111 136
112 num_bytes_read_ += size_read; 137 num_bytes_read_ += size_read;
113 138
114 // Pass it back to the callback. 139 // Pass it back to the callback.
115 AppendToSystemLogsResponse(result, source_name(), 140 AppendToSystemLogsResponse(result, source_name(),
116 anonymizer_.Anonymize(result_string)); 141 anonymizer_.Anonymize(result_string));
142
143 // If the file was rotated, close the file handle and call this function
144 // again, to read from the new file.
145 if (should_handle_file_rotation) {
146 file_.Close();
147 num_bytes_read_ = 0;
148 file_inode_ = 0;
149 ReadFile(num_rotations_allowed - 1, result);
150 }
117 } 151 }
118 152
119 } // namespace system_logs 153 } // namespace system_logs
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698