1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef HIPERF_REPORT_PROTOBUF_FILE
17#define HIPERF_REPORT_PROTOBUF_FILE
18
19#include <fstream>
20#include <stdint.h>
21#include <linux/perf_event.h>
22
23#include "google/protobuf/io/coded_stream.h"
24#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
25
26#include "debug_logger.h"
27#include "perf_event_record.h"
28#include "report_sample.pb.h"
29#include "symbols_file.h"
30#include "utilities.h"
31
32namespace Proto = OHOS::Developtools::Hiperf::Proto;
33namespace OHOS {
34namespace Developtools {
35namespace HiPerf {
36static const char FILE_MAGIC[] = "HIPERF_PB_";
37static const uint16_t FILE_VERSION = 1u;
38using ProtobufReadBack = std::function<void(Proto::HiperfRecord &record)>;
39
40class ReportProtobufFileWriter : public google::protobuf::io::CopyingOutputStream {
41public:
42    bool Create(std::string fileName);
43
44    bool ProcessRecord(const PerfEventRecord &record);
45    bool ProcessSampleRecord(const PerfRecordSample &recordSample, uint32_t configIndex,
46                             const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles);
47    bool ProcessSymbolsFiles(const std::vector<std::unique_ptr<SymbolsFile>> &symbolsFiles);
48    bool ProcessReportInfo(const std::vector<std::string> &configNames,
49                           const std::string &workloadCmd);
50
51    ~ReportProtobufFileWriter();
52    void Close();
53
54private:
55    std::unique_ptr<google::protobuf::io::CopyingOutputStreamAdaptor> protpbufOutputStream_;
56    std::unique_ptr<google::protobuf::io::CodedOutputStream> protpbufCodedOutputStream_;
57    std::string fileName_;
58    std::unique_ptr<std::ofstream> protobufFileStream_ = std::make_unique<std::ofstream>();
59
60    uint64_t recordCount_ = 0;
61    uint64_t recordLost_ = 0;
62
63    bool IsOpen();
64    bool Write(const void *buffer, int size) override;
65    virtual bool ProcessRecord(const PerfRecordComm &recordComm);
66    virtual bool ProcessRecord(const PerfRecordLost &recordLost);
67    void BeforeClose();
68
69    FRIEND_TEST(ReportProtobufFileTest, Close);
70    FRIEND_TEST(ReportProtobufFileTest, ProcessRecord);
71    FRIEND_TEST(ReportProtobufFileTest, ProcessRecordPerfRecordLost);
72    FRIEND_TEST(ReportProtobufFileTest, ProcessRecordPerfRecordComm);
73    FRIEND_TEST(ReportProtobufFileTest, BeforeClose);
74    FRIEND_TEST(ReportProtobufFileTest, ProcessSymbolsFiles);
75};
76
77class ReportProtobufFileReader : public google::protobuf::io::CopyingInputStream {
78public:
79    bool Dump(std::string fileName, ProtobufReadBack readBack = nullptr);
80
81private:
82    std::unique_ptr<google::protobuf::io::CopyingInputStreamAdaptor> protpbufInputStream_;
83    std::unique_ptr<google::protobuf::io::CodedInputStream> protpbufCodedInputStream_;
84    std::string fileName_;
85    std::unique_ptr<std::ifstream> protobufFileStream_ = std::make_unique<std::ifstream>();
86
87    bool IsOpen();
88    bool CheckFileMagic();
89    int Read(void *buffer, int size) override;
90    bool Dump(const Proto::HiperfRecord &record, int indent = 0);
91    bool Dump(const Proto::CallStackSample &message, int indent = 0);
92    bool Dump(const Proto::SampleStatistic &message, int indent = 0);
93    bool Dump(const Proto::SymbolTableFile &message, int indent = 0);
94    bool Dump(const Proto::VirtualThreadInfo &message, int indent = 0);
95    bool Dump(const Proto::ReportInfo &message, int indent = 0);
96};
97} // namespace HiPerf
98} // namespace Developtools
99} // namespace OHOS
100#endif // HIPERF_REPORT_PROTOBUF_FILE
101