Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <fcntl.h> | |
| 6 #include <stdio.h> | |
| 7 #include <stdlib.h> | |
| 8 #include <sys/file.h> | |
| 9 #include <sys/stat.h> | |
| 10 #include <unistd.h> | |
| 11 | |
| 12 #include <list> | |
| 13 #include <memory> | |
| 14 | |
| 15 #include "base/file_util.h" | |
| 16 #include "base/files/file_path.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/memory/scoped_vector.h" | |
| 19 #include "base/metrics/chromeos_metrics.h" | |
| 20 #include "base/metrics/crash_sample.h" | |
| 21 #include "base/metrics/histogram_sample.h" | |
| 22 #include "base/metrics/linearhistogram_sample.h" | |
| 23 #include "base/metrics/metric_sample.h" | |
| 24 #include "base/metrics/sparsehistogram_sample.h" | |
| 25 #include "base/metrics/useraction_sample.h" | |
| 26 | |
| 27 namespace base { | |
| 28 MetricSample* ChromeOSMetrics::ReadSample(int32 message_size, uint8* buffer) { | |
|
achaulk
2014/04/07 22:16:00
You're doing an awful lot of reinterpret_casts in
| |
| 29 // The buffer should now contain a pair of null-terminated strings. | |
| 30 uint8* p = reinterpret_cast<uint8*>(memchr(buffer, '\0', message_size)); | |
| 31 uint8* q = NULL; | |
| 32 if (p != NULL) { | |
| 33 q = reinterpret_cast<uint8*>( | |
| 34 memchr(p + 1, '\0', message_size - (p + 1 - buffer))); | |
| 35 } | |
| 36 if (q == NULL) { | |
| 37 DLOG(ERROR) << "bad name-value pair for metrics"; | |
| 38 return NULL; | |
| 39 } | |
| 40 char* name = reinterpret_cast<char*>(buffer); | |
| 41 char* value = reinterpret_cast<char*>(p + 1); | |
| 42 if (strcmp(name, "crash") == 0) { | |
| 43 return CrashSample::ReadCrash(value); | |
| 44 } else if (strcmp(name, "histogram") == 0) { | |
| 45 return HistogramSample::ReadHistogram(value); | |
| 46 } else if (strcmp(name, "linearhistogram") == 0) { | |
| 47 return LinearHistogramSample::ReadLinearHistogram(value); | |
| 48 } else if (strcmp(name, "sparsehistogram") == 0) { | |
| 49 return SparseHistogramSample::ReadSparseHistogram(value); | |
| 50 } else if (strcmp(name, "useraction") == 0) { | |
| 51 return new UserActionSample(value); | |
| 52 } else { | |
| 53 DLOG(ERROR) << "invalid event type: " << name << value << message_size; | |
| 54 } | |
| 55 return NULL; | |
| 56 } | |
| 57 | |
| 58 int32_t ChromeOSMetrics::FormatSample(int32_t buffer_size, char* buffer, | |
|
achaulk
2014/04/07 22:16:00
This doesn't seem very useful since it just calls
| |
| 59 const char* format, ...) { | |
| 60 int32_t message_length; | |
| 61 | |
| 62 // Format the non-LENGTH contents in the buffer by leaving space for | |
| 63 // LENGTH at the start of the buffer. | |
| 64 va_list args; | |
| 65 va_start(args, format); | |
| 66 message_length = vsnprintf(buffer, buffer_size, | |
| 67 format, args); | |
| 68 va_end(args); | |
| 69 | |
| 70 if (message_length < 0) { | |
|
achaulk
2014/04/07 22:16:00
I don't think negative values are possible with th
| |
| 71 return -1; | |
| 72 } | |
| 73 | |
| 74 // +1 to account for the trailing \0. | |
| 75 message_length += 1; | |
| 76 if (message_length > buffer_size) { | |
| 77 return -1; | |
| 78 } | |
| 79 | |
| 80 return message_length; | |
| 81 } | |
| 82 | |
| 83 int32_t ChromeOSMetrics::WriteChromeMessage(MetricSample* sample, | |
| 84 int32_t buffer_size, char* buffer) { | |
| 85 int32_t message_length; | |
| 86 size_t len_size = sizeof(message_length); | |
| 87 | |
| 88 // Format the non-LENGTH contents in the buffer by leaving space for | |
| 89 // LENGTH at the start of the buffer. | |
| 90 message_length = sample->Write(buffer_size-len_size, &buffer[len_size]); | |
|
achaulk
2014/04/07 22:16:00
Should have the write functions return a std::stri
| |
| 91 | |
| 92 if (message_length < 0) { | |
| 93 return -1; | |
| 94 } | |
| 95 | |
| 96 // +1 to account for the trailing \0. | |
| 97 message_length += len_size; | |
| 98 if (message_length > buffer_size) { | |
| 99 return -1; | |
| 100 } | |
| 101 | |
| 102 // Prepend LENGTH to the message. | |
| 103 memcpy(buffer, &message_length, len_size); | |
| 104 return message_length; | |
| 105 } | |
| 106 | |
| 107 bool ChromeOSMetrics::WriteMetricToFile(MetricSample* sample, | |
| 108 const std::string& filename) { | |
| 109 File file = File(FilePath(filename), File::FLAG_OPEN_ALWAYS | |
| 110 | File::FLAG_APPEND); | |
| 111 File::Error err = file.Lock(); | |
| 112 if (err != File::FILE_OK) { | |
| 113 DLOG(ERROR) << "could not lock the file"; | |
| 114 return false; | |
| 115 } | |
| 116 | |
| 117 char buffer[kMessageMaxLength]; | |
| 118 int32_t length = | |
| 119 ChromeOSMetrics::WriteChromeMessage(sample, kMessageMaxLength, buffer); | |
| 120 file.WriteAtCurrentPos(buffer, length); | |
| 121 | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 void ChromeOSMetrics::ReadMetricsFromFile(const std::string& filename, | |
| 126 ScopedVector<MetricSample>* metrics) { | |
| 127 File file = File(FilePath(filename), File::FLAG_OPEN | | |
| 128 File::FLAG_READ | File::FLAG_WRITE); | |
|
achaulk
2014/04/07 22:16:00
Why have write here? If you want to truncate, woul
bsimonnet
2014/04/08 23:00:09
The way it works it that the reading and writing w
| |
| 129 File::Error err = file.Lock(); | |
| 130 if (err != File::FILE_OK) { | |
| 131 DLOG(ERROR) << "could not lock the file"; | |
| 132 return; | |
| 133 } | |
| 134 for (;;) { | |
| 135 int32 message_length; | |
| 136 int read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&message_length), | |
|
achaulk
2014/04/07 22:16:00
Possible endian issues? Do these files ever leave
bsimonnet
2014/04/08 23:00:09
This file will always stay on the device. It is on
| |
| 137 sizeof(message_length)); | |
| 138 if (read != sizeof(message_length)) { | |
| 139 break; | |
| 140 } | |
| 141 message_length -= sizeof(message_length); | |
| 142 char serialized_sample[message_length]; | |
|
achaulk
2014/04/07 22:16:00
I think we are avoiding this GCC extension
| |
| 143 read = file.ReadAtCurrentPos(serialized_sample, message_length); | |
| 144 if (read != message_length) { | |
| 145 DLOG(ERROR) << "could not read message" << read; | |
| 146 break; | |
| 147 } | |
| 148 metrics->push_back(ReadSample(message_length, | |
| 149 reinterpret_cast<uint8*>(serialized_sample))); | |
| 150 } | |
| 151 file.SetLength(0); | |
| 152 } | |
| 153 } // namespace base | |
| OLD | NEW |