• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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