1 // Copyright (c) 2013 The Chromium OS 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 "conversion_utils.h"
6
7 #include <stdlib.h>
8 #include <unistd.h>
9
10 #include <string>
11 #include <vector>
12
13 #include "base/logging.h"
14
15 #include "compat/proto.h"
16 #include "compat/string.h"
17 #include "file_utils.h"
18 #include "perf_parser.h"
19 #include "perf_protobuf_io.h"
20 #include "perf_reader.h"
21
22 namespace quipper {
23
24 namespace {
25
26 // Parse options from the format strings, set the options, and return the base
27 // format. Returns the empty string if options are not recognized.
ParseFormatOptions(string format,PerfParserOptions * options)28 string ParseFormatOptions(string format, PerfParserOptions* options) {
29 auto dot = format.find('.');
30 if (dot != string::npos) {
31 string opt = format.substr(dot + 1);
32 format = format.substr(0, dot);
33 if (opt == "remap") {
34 options->do_remap = true;
35 } else if (opt == "discard") {
36 options->discard_unused_events = true;
37 } else if (opt == "remap.discard") {
38 options->do_remap = true;
39 options->discard_unused_events = true;
40 } else {
41 LOG(ERROR) << "Unknown option: " << opt;
42 return "";
43 }
44 }
45 return format;
46 }
47
48 // ReadInput reads the input and stores it within |reader|.
ReadInput(const FormatAndFile & input,PerfReader * reader,PerfParserOptions * options)49 bool ReadInput(const FormatAndFile& input, PerfReader* reader,
50 PerfParserOptions* options) {
51 LOG(INFO) << "Reading input.";
52
53 string format = ParseFormatOptions(input.format, options);
54 if (format == kPerfFormat) {
55 return reader->ReadFile(input.filename);
56 }
57
58 if (format == kProtoTextFormat) {
59 PerfDataProto perf_data_proto;
60 std::vector<char> data;
61 if (!FileToBuffer(input.filename, &data)) return false;
62 string text(data.begin(), data.end());
63 if (!TextFormat::ParseFromString(text, &perf_data_proto)) return false;
64
65 return reader->Deserialize(perf_data_proto);
66 }
67
68 LOG(ERROR) << "Unimplemented read format: " << input.format;
69 return false;
70 }
71
72 // WriteOutput reads from |reader| and writes the output to the file
73 // within |output|.
WriteOutput(const FormatAndFile & output,const PerfParserOptions & options,PerfReader * reader)74 bool WriteOutput(const FormatAndFile& output, const PerfParserOptions& options,
75 PerfReader* reader) {
76 LOG(INFO) << "Writing output.";
77
78 // Apply use PerfParser to modify data in reader, applying hacks all hacks,
79 // regardless of output format.
80 PerfParser parser(reader, options);
81 if (!parser.ParseRawEvents()) return false;
82
83 string output_string;
84 if (output.format == kPerfFormat) {
85 return reader->WriteFile(output.filename);
86 }
87
88 if (output.format == kProtoTextFormat) {
89 PerfDataProto perf_data_proto;
90 reader->Serialize(&perf_data_proto);
91
92 // Serialize the parser stats as well.
93 PerfSerializer::SerializeParserStats(parser.stats(), &perf_data_proto);
94
95 // Reset the timestamp field since it causes reproducability issues when
96 // testing.
97 perf_data_proto.set_timestamp_sec(0);
98 if (!TextFormat::PrintToString(perf_data_proto, &output_string))
99 return false;
100 std::vector<char> data(output_string.begin(), output_string.end());
101 return BufferToFile(output.filename, data);
102 }
103
104 LOG(ERROR) << "Unimplemented write format: " << output.format;
105 return false;
106 }
107
108 } // namespace
109
110 // Format string for perf.data.
111 const char kPerfFormat[] = "perf";
112
113 // Format string for protobuf text format.
114 const char kProtoTextFormat[] = "text";
115
ConvertFile(const FormatAndFile & input,const FormatAndFile & output)116 bool ConvertFile(const FormatAndFile& input, const FormatAndFile& output) {
117 PerfReader reader;
118 PerfParserOptions options;
119 if (!ReadInput(input, &reader, &options)) return false;
120 if (!WriteOutput(output, options, &reader)) return false;
121 return true;
122 }
123
124 } // namespace quipper
125