blob: 5a14aa864e4fd11eadf73befe67ead2701fd9e12 [file] [log] [blame]
Aron Virginas-Tardfa14772019-09-24 18:24:47 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// 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{
46 m_IncomingDumpFileStream.close();
47 m_OutgoingDumpFileStream.close();
48 m_Connection->Close();
49}
50
51bool ProfilingConnectionDumpToFileDecorator::WritePacket(const unsigned char* buffer, uint32_t length)
52{
53 bool success = true;
Keith Davisb10e0812019-10-17 09:52:50 +010054 if (!m_Options.m_OutgoingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010055 {
Matteo Martincigh67ef2a52019-10-10 13:29:02 +010056 success &= DumpOutgoingToFile(buffer, length);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010057 }
58 success &= m_Connection->WritePacket(buffer, length);
59 return success;
60}
61
62Packet ProfilingConnectionDumpToFileDecorator::ReadPacket(uint32_t timeout)
63{
64 Packet packet = m_Connection->ReadPacket(timeout);
Keith Davisb10e0812019-10-17 09:52:50 +010065 if (!m_Options.m_IncomingCaptureFile.empty())
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010066 {
67 DumpIncomingToFile(packet);
68 }
69 return packet;
70}
71
72bool ProfilingConnectionDumpToFileDecorator::OpenIncomingDumpFile()
73{
Keith Davisb10e0812019-10-17 09:52:50 +010074 m_IncomingDumpFileStream.open(m_Options.m_IncomingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010075 return m_IncomingDumpFileStream.is_open();
76}
77
78bool ProfilingConnectionDumpToFileDecorator::OpenOutgoingDumpFile()
79{
Keith Davisb10e0812019-10-17 09:52:50 +010080 m_OutgoingDumpFileStream.open(m_Options.m_OutgoingCaptureFile, std::ios::out | std::ios::binary);
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010081 return m_OutgoingDumpFileStream.is_open();
82}
83
84
85/// Dumps incoming data into the file specified by m_Settings.m_IncomingDumpFileName.
86/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
87/// i.e. the method will not throw an exception if it encounters an error while trying
88/// to write the data into the specified file.
89/// @param packet data packet to write
90/// @return nothing
91void ProfilingConnectionDumpToFileDecorator::DumpIncomingToFile(const Packet& packet)
92{
93 bool success = true;
94 if (!m_IncomingDumpFileStream.is_open())
95 {
96 // attempt to open dump file
97 success &= OpenIncomingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +010098 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +010099 {
Keith Davisb10e0812019-10-17 09:52:50 +0100100 Fail("Failed to open \"" + m_Options.m_IncomingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100101 }
102 }
103
104 // attempt to write binary data from packet
Aron Virginas-Taraab82c52019-09-30 14:21:26 +0100105 const unsigned int header = packet.GetHeader();
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100106 const unsigned int packetLength = packet.GetLength();
107
108 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&header), sizeof header);
109 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(&packetLength), sizeof packetLength);
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100110 m_IncomingDumpFileStream.write(reinterpret_cast<const char*>(packet.GetData()),
111 boost::numeric_cast<std::streamsize>(packetLength));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100112
113 success &= m_IncomingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100114 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100115 {
116 Fail("Error writing incoming packet of " + std::to_string(packetLength) + " bytes");
117 }
118}
119
120/// Dumps outgoing data into the file specified by m_Settings.m_OutgoingDumpFileName.
121/// If m_IgnoreFileErrors is set to true in m_Settings, write errors will be ignored,
122/// i.e. the method will not throw an exception if it encounters an error while trying
123/// to write the data into the specified file. However, the return value will still
124/// signal if the write has not been completed succesfully.
125/// @param buffer pointer to data to write
126/// @param length number of bytes to write
127/// @return true if write successful, false otherwise
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100128bool ProfilingConnectionDumpToFileDecorator::DumpOutgoingToFile(const unsigned char* buffer, uint32_t length)
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100129{
130 bool success = true;
131 if (!m_OutgoingDumpFileStream.is_open())
132 {
133 // attempt to open dump file
134 success &= OpenOutgoingDumpFile();
Keith Davisb10e0812019-10-17 09:52:50 +0100135 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100136 {
Keith Davisb10e0812019-10-17 09:52:50 +0100137 Fail("Failed to open \"" + m_Options.m_OutgoingCaptureFile + "\" for writing");
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100138 }
139 }
140
141 // attempt to write binary data
Matteo Martincigh67ef2a52019-10-10 13:29:02 +0100142 m_OutgoingDumpFileStream.write(reinterpret_cast<const char*>(buffer),
143 boost::numeric_cast<std::streamsize>(length));
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100144 success &= m_OutgoingDumpFileStream.good();
Keith Davisb10e0812019-10-17 09:52:50 +0100145 if (!(success || m_IgnoreFileErrors))
Aron Virginas-Tardfa14772019-09-24 18:24:47 +0100146 {
147 Fail("Error writing outgoing packet of " + std::to_string(length) + " bytes");
148 }
149
150 return success;
151}
152
153void ProfilingConnectionDumpToFileDecorator::Fail(const std::string& errorMessage)
154{
155 Close();
156 throw RuntimeException(errorMessage);
157}
158
159} // namespace profiling
160
161} // namespace armnn