OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/metrics/serialization/serialization_utils.h" | 5 #include "components/metrics/serialization/serialization_utils.h" |
6 | 6 |
7 #include <sys/file.h> | 7 #include <sys/file.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 | 115 |
116 void SerializationUtils::ReadAndTruncateMetricsFromFile( | 116 void SerializationUtils::ReadAndTruncateMetricsFromFile( |
117 const std::string& filename, | 117 const std::string& filename, |
118 ScopedVector<MetricSample>* metrics) { | 118 ScopedVector<MetricSample>* metrics) { |
119 struct stat stat_buf; | 119 struct stat stat_buf; |
120 int result; | 120 int result; |
121 | 121 |
122 result = stat(filename.c_str(), &stat_buf); | 122 result = stat(filename.c_str(), &stat_buf); |
123 if (result < 0) { | 123 if (result < 0) { |
124 if (errno != ENOENT) | 124 if (errno != ENOENT) |
125 DPLOG(ERROR) << filename << ": bad metrics file stat"; | 125 DPLOG(ERROR) << "bad metrics file stat: " << filename; |
126 | 126 |
127 // Nothing to collect---try later. | 127 // Nothing to collect---try later. |
128 return; | 128 return; |
129 } | 129 } |
130 if (stat_buf.st_size == 0) { | 130 if (stat_buf.st_size == 0) { |
131 // Also nothing to collect. | 131 // Also nothing to collect. |
132 return; | 132 return; |
133 } | 133 } |
134 base::ScopedFD fd(open(filename.c_str(), O_RDWR)); | 134 base::ScopedFD fd(open(filename.c_str(), O_RDWR)); |
135 if (fd.get() < 0) { | 135 if (fd.get() < 0) { |
136 DPLOG(ERROR) << filename << ": cannot open"; | 136 DPLOG(ERROR) << "cannot open: " << filename; |
137 return; | 137 return; |
138 } | 138 } |
139 result = flock(fd.get(), LOCK_EX); | 139 result = flock(fd.get(), LOCK_EX); |
140 if (result < 0) { | 140 if (result < 0) { |
141 DPLOG(ERROR) << filename << ": cannot lock"; | 141 DPLOG(ERROR) << "cannot lock: " << filename; |
142 return; | 142 return; |
143 } | 143 } |
144 | 144 |
145 // This processes all messages in the log. When all messages are | 145 // This processes all messages in the log. When all messages are |
146 // read and processed, or an error occurs, truncate the file to zero size. | 146 // read and processed, or an error occurs, truncate the file to zero size. |
147 for (;;) { | 147 for (;;) { |
148 std::string message; | 148 std::string message; |
149 | 149 |
150 if (!ReadMessage(fd.get(), &message)) | 150 if (!ReadMessage(fd.get(), &message)) |
151 break; | 151 break; |
152 | 152 |
153 scoped_ptr<MetricSample> sample = ParseSample(message); | 153 scoped_ptr<MetricSample> sample = ParseSample(message); |
154 if (sample) | 154 if (sample) |
155 metrics->push_back(sample.release()); | 155 metrics->push_back(sample.release()); |
156 } | 156 } |
157 | 157 |
158 result = ftruncate(fd.get(), 0); | 158 result = ftruncate(fd.get(), 0); |
159 if (result < 0) | 159 if (result < 0) |
160 DPLOG(ERROR) << "truncate metrics log"; | 160 DPLOG(ERROR) << "truncate metrics log: " << filename; |
161 | 161 |
162 result = flock(fd.get(), LOCK_UN); | 162 result = flock(fd.get(), LOCK_UN); |
163 if (result < 0) | 163 if (result < 0) |
164 DPLOG(ERROR) << "unlock metrics log"; | 164 DPLOG(ERROR) << "unlock metrics log: " << filename; |
165 } | 165 } |
166 | 166 |
167 bool SerializationUtils::WriteMetricToFile(const MetricSample& sample, | 167 bool SerializationUtils::WriteMetricToFile(const MetricSample& sample, |
168 const std::string& filename) { | 168 const std::string& filename) { |
169 if (!sample.IsValid()) | 169 if (!sample.IsValid()) |
170 return false; | 170 return false; |
171 | 171 |
172 base::ScopedFD file_descriptor(open(filename.c_str(), | 172 base::ScopedFD file_descriptor(open(filename.c_str(), |
173 O_WRONLY | O_APPEND | O_CREAT, | 173 O_WRONLY | O_APPEND | O_CREAT, |
174 READ_WRITE_ALL_FILE_FLAGS)); | 174 READ_WRITE_ALL_FILE_FLAGS)); |
175 | 175 |
176 if (file_descriptor.get() < 0) { | 176 if (file_descriptor.get() < 0) { |
177 DLOG(ERROR) << "error openning the file"; | 177 DPLOG(ERROR) << "error openning the file: " << filename; |
178 return false; | 178 return false; |
179 } | 179 } |
180 | 180 |
181 fchmod(file_descriptor.get(), READ_WRITE_ALL_FILE_FLAGS); | 181 fchmod(file_descriptor.get(), READ_WRITE_ALL_FILE_FLAGS); |
182 // Grab a lock to avoid chrome truncating the file | 182 // Grab a lock to avoid chrome truncating the file |
183 // underneath us. Keep the file locked as briefly as possible. | 183 // underneath us. Keep the file locked as briefly as possible. |
184 // Freeing file_descriptor will close the file and and remove the lock. | 184 // Freeing file_descriptor will close the file and and remove the lock. |
185 if (HANDLE_EINTR(flock(file_descriptor.get(), LOCK_EX)) < 0) { | 185 if (HANDLE_EINTR(flock(file_descriptor.get(), LOCK_EX)) < 0) { |
186 DLOG(ERROR) << "error locking" << filename << " : " << errno; | 186 DPLOG(ERROR) << "error locking: " << filename; |
187 return false; | 187 return false; |
188 } | 188 } |
189 | 189 |
190 std::string msg = sample.ToString(); | 190 std::string msg = sample.ToString(); |
191 int32 size = msg.length() + sizeof(int32); | 191 int32 size = msg.length() + sizeof(int32); |
192 if (size > kMessageMaxLength) { | 192 if (size > kMessageMaxLength) { |
193 DLOG(ERROR) << "cannot write message: too long"; | 193 DPLOG(ERROR) << "cannot write message: too long: " << filename; |
194 return false; | 194 return false; |
195 } | 195 } |
196 | 196 |
197 // The file containing the metrics samples will only be read by programs on | 197 // The file containing the metrics samples will only be read by programs on |
198 // the same device so we do not check endianness. | 198 // the same device so we do not check endianness. |
199 if (!base::WriteFileDescriptor(file_descriptor.get(), | 199 if (!base::WriteFileDescriptor(file_descriptor.get(), |
200 reinterpret_cast<char*>(&size), | 200 reinterpret_cast<char*>(&size), |
201 sizeof(size))) { | 201 sizeof(size))) { |
202 DPLOG(ERROR) << "error writing message length"; | 202 DPLOG(ERROR) << "error writing message length: " << filename; |
203 return false; | 203 return false; |
204 } | 204 } |
205 | 205 |
206 if (!base::WriteFileDescriptor( | 206 if (!base::WriteFileDescriptor( |
207 file_descriptor.get(), msg.c_str(), msg.size())) { | 207 file_descriptor.get(), msg.c_str(), msg.size())) { |
208 DPLOG(ERROR) << "error writing message"; | 208 DPLOG(ERROR) << "error writing message: " << filename; |
209 return false; | 209 return false; |
210 } | 210 } |
211 | 211 |
212 return true; | 212 return true; |
213 } | 213 } |
214 | 214 |
215 } // namespace metrics | 215 } // namespace metrics |
OLD | NEW |