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