blob: 57685661786c725a9ddb7bb7aa1f95bc695b75fb [file] [log] [blame]
Aron Virginas-Tardfa14772019-09-24 18:24:47 +01001//
Jim Flynnbbfe6032020-07-20 16:57:44 +01002// Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tardfa14772019-09-24 18:24:47 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "ProfilingConnectionDumpToFileDecorator.hpp"
7
8#include <armnn/Exceptions.hpp>
9
10#include <fstream>
11
Aron Virginas-Taraab82c52019-09-30 14:21:26 +010012#include <boost/numeric/conversion/cast.hpp>
13
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010014namespace armnn
15{
16
17namespace profiling
18{
19
20ProfilingConnectionDumpToFileDecorator::ProfilingConnectionDumpToFileDecorator(
21 std::unique_ptr<IProfilingConnection> connection,
Keith Davisb10e0812019-10-17 09:52:50 +010022 const Runtime::CreationOptions::ExternalProfilingOptions& options,
23 bool ignoreFailures)
24 : m_Connection(std::move(connection))
25 , m_Options(options)
26 , m_IgnoreFileErrors(ignoreFailures)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010027{
28 if (!m_Connection)
29 {
30 throw InvalidArgumentException("Connection cannot be nullptr");
31 }
32}
33
34ProfilingConnectionDumpToFileDecorator::~ProfilingConnectionDumpToFileDecorator()
35{
36 Close();
37}
38
Matteo Martincigh54fb9572019-10-02 12:50:57 +010039bool ProfilingConnectionDumpToFileDecorator::IsOpen() const
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010040{
41 return m_Connection->IsOpen();
42}
43
44void ProfilingConnectionDumpToFileDecorator::Close()
45{
Keith Davis3201eea2019-10-24 17:30:41 +010046 m_IncomingDumpFileStream.flush();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010047 m_IncomingDumpFileStream.close();
Keith Davis3201eea2019-10-24 17:30:41 +010048 m_OutgoingDumpFileStream.flush();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010049 m_OutgoingDumpFileStream.close();
50 m_Connection->Close();
51}
52
53bool ProfilingConnectionDumpToFileDecorator::WritePacket(const unsigned char* buffer, uint32_t length)
54{
55 bool success = true;
Keith Davisb10e0812019-10-17 09:52:50 +010056 if (!m_Options.m_OutgoingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010057 {
Matteo Martincigh67ef2a52019-10-10 13:29:02 +010058 success &= DumpOutgoingToFile(buffer, length);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010059 }
60 success &= m_Connection->WritePacket(buffer, length);
61 return success;
62}
63
Jim Flynnbbfe6032020-07-20 16:57:44 +010064arm::pipe::Packet ProfilingConnectionDumpToFileDecorator::ReadPacket(uint32_t timeout)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010065{
Jim Flynnbbfe6032020-07-20 16:57:44 +010066 arm::pipe::Packet packet = m_Connection->ReadPacket(timeout);
Keith Davisb10e0812019-10-17 09:52:50 +010067 if (!m_Options.m_IncomingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010068 {
69 DumpIncomingToFile(packet);
70 }
71 return packet;
72}
73
74bool ProfilingConnectionDumpToFileDecorator::OpenIncomingDumpFile()
75{
Keith Davisb10e0812019-10-17 09:52:50 +010076 m_IncomingDumpFileStream.open(m_Options.m_IncomingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010077 return m_IncomingDumpFileStream.is_open();
78}
79
80bool ProfilingConnectionDumpToFileDecorator::OpenOutgoingDumpFile()
81{
Keith Davisb10e0812019-10-17 09:52:50 +010082 m_OutgoingDumpFileStream.open(m_Options.m_OutgoingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010083 return m_OutgoingDumpFileStream.is_open();
84}
85
86
87/// Dumps incoming data into the file specified by m_Settings.m_IncomingDumpFileName.
88/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
89/// i.e. the method will not throw an exception if it encounters an error while trying
90/// to write the data into the specified file.
91/// @param packet data packet to write
92/// @return nothing
Jim Flynnbbfe6032020-07-20 16:57:44 +010093void ProfilingConnectionDumpToFileDecorator::DumpIncomingToFile(const arm::pipe::Packet& packet)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010094{
95 bool success = true;
96 if (!m_IncomingDumpFileStream.is_open())
97 {
98 // attempt to open dump file
99 success &= OpenIncomingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +0100100 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100101 {
Keith Davisb10e0812019-10-17 09:52:50 +0100102 Fail("Failed to open \"" + m_Options.m_IncomingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100103 }
104 }
105
106 // attempt to write binary data from packet
Aron Virginas-Taraab82c52019-09-30 14:21:26 +0100107 const unsigned int header = packet.GetHeader();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100108 const unsigned int packetLength = packet.GetLength();
109
110 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&header), sizeof header);
111 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&packetLength), sizeof packetLength);
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100112 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(packet.GetData()),
113 boost::numeric_cast<std::streamsize>(packetLength));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100114
115 success &= m_IncomingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100116 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100117 {
118 Fail("Error writing incoming packet of " + std::to_string(packetLength) + " bytes");
119 }
120}
121
122/// Dumps outgoing data into the file specified by m_Settings.m_OutgoingDumpFileName.
123/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
124/// i.e. the method will not throw an exception if it encounters an error while trying
125/// to write the data into the specified file. However, the return value will still
126/// signal if the write has not been completed succesfully.
127/// @param buffer pointer to data to write
128/// @param length number of bytes to write
129/// @return true if write successful, false otherwise
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100130bool ProfilingConnectionDumpToFileDecorator::DumpOutgoingToFile(const unsigned char* buffer, uint32_t length)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100131{
132 bool success = true;
133 if (!m_OutgoingDumpFileStream.is_open())
134 {
135 // attempt to open dump file
136 success &= OpenOutgoingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +0100137 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100138 {
Keith Davisb10e0812019-10-17 09:52:50 +0100139 Fail("Failed to open \"" + m_Options.m_OutgoingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100140 }
141 }
142
143 // attempt to write binary data
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100144 m_OutgoingDumpFileStream.write(reinterpret_cast<const char*>(buffer),
145 boost::numeric_cast<std::streamsize>(length));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100146 success &= m_OutgoingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100147 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100148 {
149 Fail("Error writing outgoing packet of " + std::to_string(length) + " bytes");
150 }
151
152 return success;
153}
154
155void ProfilingConnectionDumpToFileDecorator::Fail(const std::string& errorMessage)
156{
157 Close();
158 throw RuntimeException(errorMessage);
159}
160
161} // namespace profiling
162
163} // namespace armnn