• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * @file ${filename}
24  *
25  * @brief Event handler interface.  auto-generated file
26  *
27  * DO NOT EDIT
28  *
29  * Generation Command Line:
30  *  ${'\n *    '.join(cmdline)}
31  *
32  ******************************************************************************/
33 // clang-format off
34 #pragma once
35 
36 #include "common/os.h"
37 #include "${event_header}"
38 #include <fstream>
39 #include <sstream>
40 #include <iostream>
41 #include <thread>
42 
43 namespace ArchRast
44 {
45     //////////////////////////////////////////////////////////////////////////
46     /// EventHandlerFile - interface for handling events.
47     //////////////////////////////////////////////////////////////////////////
48     class EventHandlerFile : public EventHandler
49     {
50     public:
EventHandlerFile(uint32_t id)51         EventHandlerFile(uint32_t id) : mBufOffset(0)
52         {
53 #if defined(_WIN32)
54             DWORD pid = GetCurrentProcessId();
55             TCHAR procname[MAX_PATH];
56             GetModuleFileName(NULL, procname, MAX_PATH);
57             const char*       pBaseName = strrchr(procname, '\\');
58             std::stringstream outDir;
59             outDir << KNOB_DEBUG_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;
60             mOutputDir = outDir.str();
61             if (CreateDirectory(mOutputDir.c_str(), NULL))
62             {
63                 std::cout << std::endl
64                           << "ArchRast Dir:       " << mOutputDir << std::endl
65                           << std::endl
66                           << std::flush;
67             }
68 
69             // There could be multiple threads creating thread pools. We
70             // want to make sure they are uniquly identified by adding in
71             // the creator's thread id into the filename.
72             std::stringstream fstr;
73             fstr << outDir.str().c_str() << "\\ar_event" << std::this_thread::get_id();
74             fstr << "_" << id << ".bin" << std::ends;
75             mFilename = fstr.str();
76 #else
77             // There could be multiple threads creating thread pools. We
78             // want to make sure they are uniquly identified by adding in
79             // the creator's thread id into the filename.
80             std::stringstream fstr;
81             fstr << "/tmp/ar_event" << std::this_thread::get_id();
82             fstr << "_" << id << ".bin" << std::ends;
83             mFilename = fstr.str();
84 #endif
85         }
86 
~EventHandlerFile()87         virtual ~EventHandlerFile() { FlushBuffer(); }
88 
89         //////////////////////////////////////////////////////////////////////////
90         /// @brief Flush buffer to file.
FlushBuffer()91         bool FlushBuffer()
92         {
93             if (mBufOffset > 0)
94             {
95                 if (mBufOffset == mHeaderBufOffset)
96                 {
97                     // Nothing to flush. Only header has been generated.
98                     return false;
99                 }
100 
101                 std::ofstream file;
102                 file.open(mFilename, std::ios::out | std::ios::app | std::ios::binary);
103 
104                 if (!file.is_open())
105                 {
106                     SWR_INVALID("ArchRast: Could not open event file!");
107                     return false;
108                 }
109 
110                 file.write((char*)mBuffer, mBufOffset);
111                 file.close();
112 
113                 mBufOffset       = 0;
114                 mHeaderBufOffset = 0; // Reset header offset so its no longer considered.
115             }
116             return true;
117         }
118 
119         //////////////////////////////////////////////////////////////////////////
120         /// @brief Write event and its payload to the memory buffer.
Write(uint32_t eventId,const char * pBlock,uint32_t size)121         void Write(uint32_t eventId, const char* pBlock, uint32_t size)
122         {
123             if ((mBufOffset + size + sizeof(eventId)) > mBufferSize)
124             {
125                 if (!FlushBuffer())
126                 {
127                     // Don't corrupt what's already in the buffer?
128                     /// @todo Maybe add corrupt marker to buffer here in case we can open file in
129                     /// future?
130                     return;
131                 }
132             }
133 
134             memcpy(&mBuffer[mBufOffset], (char*)&eventId, sizeof(eventId));
135             mBufOffset += sizeof(eventId);
136             memcpy(&mBuffer[mBufOffset], pBlock, size);
137             mBufOffset += size;
138         }
139 <%  sorted_groups = sorted(protos['events']['groups']) %>
140 %   for group in sorted_groups:
141 %       for event_key in protos['events']['groups'][group]:
142 <%
143             event = protos['events']['defs'][event_key]
144 %>
145         //////////////////////////////////////////////////////////////////////////
146         /// @brief Handle ${event_key} event
147         virtual void Handle(const ${event['name']}& event)
148         {
149 % if event['num_fields'] == 0:
150             Write(event.eventId, (char*)&event.data, 0);
151 % else:
152             Write(event.eventId, (char*)&event.data, sizeof(event.data));
153 % endif
154         }
155 %       endfor
156 %   endfor
157 
158         //////////////////////////////////////////////////////////////////////////
159         /// @brief Everything written to buffer this point is the header.
160         virtual void MarkHeader()
161         {
162             mHeaderBufOffset = mBufOffset;
163         }
164 
165         std::string mFilename;
166         std::string mOutputDir;
167 
168         static const uint32_t mBufferSize = 1024;
169         uint8_t               mBuffer[mBufferSize];
170         uint32_t mBufOffset{0};
171         uint32_t mHeaderBufOffset{0};
172     };
173 } // namespace ArchRast
174 // clang-format on
175