xref: /aosp_15_r20/external/armnn/profiling/client/src/ProfilingConnectionDumpToFileDecorator.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "ProfilingConnectionDumpToFileDecorator.hpp"
7 
8 #include <common/include/NumericCast.hpp>
9 #include <common/include/ProfilingException.hpp>
10 
11 #include <fstream>
12 
13 namespace arm
14 {
15 
16 namespace pipe
17 {
18 
ProfilingConnectionDumpToFileDecorator(std::unique_ptr<IProfilingConnection> connection,const ProfilingOptions & options,bool ignoreFailures)19 ProfilingConnectionDumpToFileDecorator::ProfilingConnectionDumpToFileDecorator(
20     std::unique_ptr<IProfilingConnection> connection,
21     const ProfilingOptions& options,
22     bool ignoreFailures)
23       : m_Connection(std::move(connection))
24       , m_Options(options)
25       , m_IgnoreFileErrors(ignoreFailures)
26 {
27     if (!m_Connection)
28     {
29         throw arm::pipe::InvalidArgumentException("Connection cannot be nullptr");
30     }
31 }
32 
~ProfilingConnectionDumpToFileDecorator()33 ProfilingConnectionDumpToFileDecorator::~ProfilingConnectionDumpToFileDecorator()
34 {
35     Close();
36 }
37 
IsOpen() const38 bool ProfilingConnectionDumpToFileDecorator::IsOpen() const
39 {
40     return m_Connection->IsOpen();
41 }
42 
Close()43 void ProfilingConnectionDumpToFileDecorator::Close()
44 {
45     m_IncomingDumpFileStream.flush();
46     m_IncomingDumpFileStream.close();
47     m_OutgoingDumpFileStream.flush();
48     m_OutgoingDumpFileStream.close();
49     m_Connection->Close();
50 }
51 
WritePacket(const unsigned char * buffer,uint32_t length)52 bool ProfilingConnectionDumpToFileDecorator::WritePacket(const unsigned char* buffer, uint32_t length)
53 {
54     bool success = true;
55     if (!m_Options.m_OutgoingCaptureFile.empty())
56     {
57         success &= DumpOutgoingToFile(buffer, length);
58     }
59     success &= m_Connection->WritePacket(buffer, length);
60     return success;
61 }
62 
ReadPacket(uint32_t timeout)63 arm::pipe::Packet ProfilingConnectionDumpToFileDecorator::ReadPacket(uint32_t timeout)
64 {
65     arm::pipe::Packet packet = m_Connection->ReadPacket(timeout);
66     if (!m_Options.m_IncomingCaptureFile.empty())
67     {
68         DumpIncomingToFile(packet);
69     }
70     return packet;
71 }
72 
OpenIncomingDumpFile()73 bool ProfilingConnectionDumpToFileDecorator::OpenIncomingDumpFile()
74 {
75     m_IncomingDumpFileStream.open(m_Options.m_IncomingCaptureFile, std::ios::out | std::ios::binary);
76     return m_IncomingDumpFileStream.is_open();
77 }
78 
OpenOutgoingDumpFile()79 bool ProfilingConnectionDumpToFileDecorator::OpenOutgoingDumpFile()
80 {
81     m_OutgoingDumpFileStream.open(m_Options.m_OutgoingCaptureFile, std::ios::out | std::ios::binary);
82     return m_OutgoingDumpFileStream.is_open();
83 }
84 
85 
86 /// Dumps incoming data into the file specified by m_Settings.m_IncomingDumpFileName.
87 /// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
88 /// i.e. the method will not throw an exception if it encounters an error while trying
89 /// to write the data into the specified file.
90 /// @param packet data packet to write
91 /// @return nothing
DumpIncomingToFile(const arm::pipe::Packet & packet)92 void ProfilingConnectionDumpToFileDecorator::DumpIncomingToFile(const arm::pipe::Packet& packet)
93 {
94     bool success = true;
95     if (!m_IncomingDumpFileStream.is_open())
96     {
97         // attempt to open dump file
98         success &= OpenIncomingDumpFile();
99         if (!(success || m_IgnoreFileErrors))
100         {
101             Fail("Failed to open \"" + m_Options.m_IncomingCaptureFile + "\" for writing");
102         }
103     }
104 
105     // attempt to write binary data from packet
106     const unsigned int header       = packet.GetHeader();
107     const unsigned int packetLength = packet.GetLength();
108 
109     m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&header), sizeof header);
110     m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&packetLength), sizeof packetLength);
111     m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(packet.GetData()),
112                                    arm::pipe::numeric_cast<std::streamsize>(packetLength));
113 
114     success &= m_IncomingDumpFileStream.good();
115     if (!(success || m_IgnoreFileErrors))
116     {
117         Fail("Error writing incoming packet of " + std::to_string(packetLength) + " bytes");
118     }
119 }
120 
121 /// Dumps outgoing data into the file specified by m_Settings.m_OutgoingDumpFileName.
122 /// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
123 /// i.e. the method will not throw an exception if it encounters an error while trying
124 /// to write the data into the specified file. However, the return value will still
125 /// signal if the write has not been completed succesfully.
126 /// @param buffer pointer to data to write
127 /// @param length number of bytes to write
128 /// @return true if write successful, false otherwise
DumpOutgoingToFile(const unsigned char * buffer,uint32_t length)129 bool ProfilingConnectionDumpToFileDecorator::DumpOutgoingToFile(const unsigned char* buffer, uint32_t length)
130 {
131     bool success = true;
132     if (!m_OutgoingDumpFileStream.is_open())
133     {
134         // attempt to open dump file
135         success &= OpenOutgoingDumpFile();
136         if (!(success || m_IgnoreFileErrors))
137         {
138             Fail("Failed to open \"" + m_Options.m_OutgoingCaptureFile + "\" for writing");
139         }
140     }
141 
142     // attempt to write binary data
143     m_OutgoingDumpFileStream.write(reinterpret_cast<const char*>(buffer),
144                                    arm::pipe::numeric_cast<std::streamsize>(length));
145     success &= m_OutgoingDumpFileStream.good();
146     if (!(success || m_IgnoreFileErrors))
147     {
148         Fail("Error writing outgoing packet of " + std::to_string(length) + " bytes");
149     }
150 
151     return success;
152 }
153 
Fail(const std::string & errorMessage)154 void ProfilingConnectionDumpToFileDecorator::Fail(const std::string& errorMessage)
155 {
156     Close();
157     throw arm::pipe::ProfilingException(errorMessage);
158 }
159 
160 } // namespace pipe
161 
162 } // namespace arm
163