From 878d9e6dde8918fd19fdfbc3de4d220c3eb3dc8a Mon Sep 17 00:00:00 2001 From: EricLiu2000 Date: Fri, 21 Jun 2019 16:14:52 -0400 Subject: [PATCH] Implemented threaded error handling in errormanager and fixed compile error --- api/icsneocpp/errormanager.cpp | 12 ++++++- communication/packet/ethernetpacket.cpp | 2 +- include/icsneo/api/errormanager.h | 46 +++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/api/icsneocpp/errormanager.cpp b/api/icsneocpp/errormanager.cpp index b2987a8..2745ccb 100644 --- a/api/icsneocpp/errormanager.cpp +++ b/api/icsneocpp/errormanager.cpp @@ -48,6 +48,16 @@ bool ErrorManager::getLastError(APIError& errorOutput, ErrorFilter filter) { return false; } +bool ErrorManager::getLastError(APIError& errorOutput, std::thread::id id) { + auto iter = lastUserErrors.find(id); + if(iter == lastUserErrors.end()) { + return false; + } else { + errorOutput = iter->second; + return true; + } +} + void ErrorManager::discard(ErrorFilter filter) { std::lock_guard lk(mutex); errors.remove_if([&filter](const APIError& error) { @@ -69,7 +79,7 @@ size_t ErrorManager::count_internal(ErrorFilter filter) const { */ bool ErrorManager::enforceLimit() { // Remove all TooManyErrors before checking - errors.remove_if([](icsneo::APIError err){ return err.getType == icsneo::APIError::TooManyErrors; }); + errors.remove_if([](icsneo::APIError err){ return err.getType() == icsneo::APIError::TooManyErrors; }); // We are not overflowing if(errors.size() < errorLimit) diff --git a/communication/packet/ethernetpacket.cpp b/communication/packet/ethernetpacket.cpp index 2571606..0061315 100644 --- a/communication/packet/ethernetpacket.cpp +++ b/communication/packet/ethernetpacket.cpp @@ -53,7 +53,7 @@ std::shared_ptr HardwareEthernetPacket::DecodeToMessage(const s return messagePtr; } -bool HardwareEthernetPacket::EncodeFromMessage(const EthernetMessage& message, std::vector& bytestream, const device_errorhandler_t& err) { +bool HardwareEthernetPacket::EncodeFromMessage(const EthernetMessage& message, std::vector& bytestream, const device_errorhandler_t&) { const size_t unpaddedSize = message.data.size(); size_t paddedSize = unpaddedSize; diff --git a/include/icsneo/api/errormanager.h b/include/icsneo/api/errormanager.h index f23524c..a30acaa 100644 --- a/include/icsneo/api/errormanager.h +++ b/include/icsneo/api/errormanager.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "icsneo/api/error.h" namespace icsneo { @@ -29,20 +31,42 @@ public: void get(std::vector& outErrors, ErrorFilter filter, size_t max = 0) { get(outErrors, max, filter); } void get(std::vector& outErrors, size_t max = 0, ErrorFilter filter = ErrorFilter()); bool getLastError(APIError& outErrors, ErrorFilter filter = ErrorFilter()); + bool getLastError(APIError& errorOutput, std::thread::id id); void add(APIError error) { std::lock_guard lk(mutex); add_internal(error); } + void add(APIError error, std::thread::id id) { + std::lock_guard lk(mutex); + if(id == std::thread::id()) + add_internal(error); + else + add_internal_threaded(error, id); + } void add(APIError::ErrorType type) { std::lock_guard lk(mutex); add_internal(APIError::APIError(type)); } + void add(APIError::ErrorType type, std::thread::id id) { + std::lock_guard lk(mutex); + if(id == std::thread::id()) + add_internal(APIError::APIError(type)); + else + add_internal_threaded(APIError::APIError(type), id); + + } void add(APIError::ErrorType type, const Device* forDevice) { std::lock_guard lk(mutex); add_internal(APIError::APIError(type, forDevice)); } - + void add(APIError::ErrorType type, const Device* forDevice, std::thread::id id) { + std::lock_guard lk(mutex); + if(id == std::thread::id()) + add_internal(APIError::APIError(type, forDevice)); + else + add_internal_threaded(APIError::APIError(type, forDevice), id); + } void discard(ErrorFilter filter = ErrorFilter()); @@ -70,12 +94,28 @@ private: // Stores all errors std::list errors; + std::unordered_map lastUserErrors; size_t errorLimit = 10000; size_t count_internal(ErrorFilter filter = ErrorFilter()) const; - // If errors is not full, add the error at the end - // Otherwise, remove the least significant errors, push the error to the back and push a APIError::TooManyErrors to the back (in that order) + /** + * Places a {id, error} pair into the lastUserErrors + * If the key id already exists in the map, replace the error of that pair with the new one + */ + void add_internal_threaded(APIError error, std::thread::id id) { + auto iter = lastUserErrors.find(id); + if(iter == lastUserErrors.end()) { + lastUserErrors.insert(std::make_pair(id, error)); + } else { + iter->second = error; + } + } + + /** + * If errors is not full, add the error at the end + * Otherwise, remove the least significant errors, push the error to the back and push a APIError::TooManyErrors to the back (in that order) + */ void add_internal(APIError error) { // Ensure the error list is at most exactly full (size of errorLimit - 1, leaving room for a potential APIError::TooManyErrors) enforceLimit();