Home | History | Annotate | Download | only in quipper
      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.
     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|.
     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|.
     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 
    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