Commit 32b0e19aaa1fec06d3452228290e944e9e7cd28a
0 parents
Initial commit. dependencies not resolved yet.
Showing
7 changed files
with
403 additions
and
0 deletions
.gitignore
0 → 100644
CMakeLists.txt
0 → 100644
| 1 | +++ a/CMakeLists.txt | ||
| 1 | +cmake_minimum_required(VERSION 3.0) | ||
| 2 | + | ||
| 3 | +# Check to see where cmake is located. | ||
| 4 | +if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) | ||
| 5 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) | ||
| 6 | +elseif( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) | ||
| 7 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) | ||
| 8 | +else() | ||
| 9 | + return() | ||
| 10 | +endif() | ||
| 11 | + | ||
| 12 | +# Check to see if there is versioning information available | ||
| 13 | +if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) | ||
| 14 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) | ||
| 15 | + include(osdevversion) | ||
| 16 | +endif() | ||
| 17 | + | ||
| 18 | +include(projectheader) | ||
| 19 | +project_header(osdev_transqueue) | ||
| 20 | + | ||
| 21 | +add_subdirectory(src) | ||
| 22 | +add_subdirectory(tests) | ||
| 23 | + | ||
| 24 | +# include(packaging) | ||
| 25 | +# package_component() |
README.md
0 → 100644
| 1 | +++ a/README.md |
src/CMakeLists.txt
0 → 100644
| 1 | +++ a/src/CMakeLists.txt | ||
| 1 | +cmake_minimum_required(VERSION 3.0) | ||
| 2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake) | ||
| 3 | +include(projectheader) | ||
| 4 | +project_header(transqueue) | ||
| 5 | + | ||
| 6 | +find_package( Qt5Core REQUIRED ) | ||
| 7 | +find_package( Qt5Sql REQUIRED ) | ||
| 8 | + | ||
| 9 | +include_directories( SYSTEM | ||
| 10 | + ${Qt5Core_INCLUDE_DIRS} | ||
| 11 | + ${CMAKE_CURRENT_SOURCE_DIR}/../datatypes | ||
| 12 | + ${CMAKE_CURRENT_SOURCE_DIR}/../logutils | ||
| 13 | + ${CMAKE_CURRENT_SOURCE_DIR}/../config | ||
| 14 | + ${CMAKE_CURRENT_SOURCE_DIR}/../pugixml | ||
| 15 | +) | ||
| 16 | + | ||
| 17 | +include(compiler) | ||
| 18 | + | ||
| 19 | +set(SRC_LIST | ||
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/transqueue.cpp | ||
| 21 | +) | ||
| 22 | + | ||
| 23 | +include(qtmoc) | ||
| 24 | +create_mocs( SRC_LIST MOC_LIST | ||
| 25 | + ${CMAKE_CURRENT_SOURCE_DIR}/transqueue.h | ||
| 26 | +) | ||
| 27 | + | ||
| 28 | +include(library) | ||
| 29 | +add_libraries( | ||
| 30 | + ${Qt5Core_LIBRARIES} | ||
| 31 | + datatypes | ||
| 32 | + logutils | ||
| 33 | + config | ||
| 34 | + pugixml | ||
| 35 | +) | ||
| 36 | + | ||
| 37 | +include(installation) | ||
| 38 | +install_component() |
src/transqueue.cpp
0 → 100644
| 1 | +++ a/src/transqueue.cpp | ||
| 1 | +/* **************************************************************************** | ||
| 2 | + * Copyright 2019 Open Systems Development BV * | ||
| 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 shall be included in * | ||
| 12 | + * all copies or substantial portions of the Software. * | ||
| 13 | + * * | ||
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | ||
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | ||
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | ||
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | ||
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | ||
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | ||
| 20 | + * DEALINGS IN THE SOFTWARE. * | ||
| 21 | + * ***************************************************************************/ | ||
| 22 | + | ||
| 23 | +#include "transqueue.h" | ||
| 24 | + | ||
| 25 | +#include "dcxmlconfig.h" | ||
| 26 | +#include "log.h" | ||
| 27 | +#include "threadcontext.h" | ||
| 28 | +#include "ormxmlwriter.h" | ||
| 29 | + | ||
| 30 | +#include <QFile> | ||
| 31 | +#include <QDateTime> | ||
| 32 | +#include <QTextStream> | ||
| 33 | + | ||
| 34 | +using namespace osdev::components; | ||
| 35 | + | ||
| 36 | +TransQueue::TransQueue( QObject *_parent ) | ||
| 37 | + : QObject( _parent ) | ||
| 38 | + , m_TTL( DCXmlConfig::Instance().timeToLive() ) | ||
| 39 | + , m_queueTimer() | ||
| 40 | + , m_queueMutex() | ||
| 41 | + , m_queue() | ||
| 42 | +{ | ||
| 43 | + // Connect the timer to the internal timeout-slot. | ||
| 44 | + connect( &m_queueTimer, &QTimer::timeout, this, &TransQueue::slotProcessQueue ); | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +void TransQueue::setTimeOut( int milli_seconds ) | ||
| 48 | +{ | ||
| 49 | + m_queueTimer.setSingleShot( true ); | ||
| 50 | + m_queueTimer.setInterval( milli_seconds ); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +void TransQueue::setTransaction( const QSharedPointer<ORMRelData>& pData ) | ||
| 54 | +{ | ||
| 55 | + QMutexLocker mutLock( &m_queueMutex ); | ||
| 56 | + if( pData ) | ||
| 57 | + { | ||
| 58 | + if( pData->TTL() == -1 ) | ||
| 59 | + { | ||
| 60 | + pData->setTTL( m_TTL ); | ||
| 61 | + m_queue.enqueue( pData ); | ||
| 62 | + } | ||
| 63 | + else if( pData->TTL() == 0 ) | ||
| 64 | + { | ||
| 65 | + if( !this->dumpToDisk( pData ) ) | ||
| 66 | + { | ||
| 67 | + LogError( "[TransQueue::setTransaction]", | ||
| 68 | + QString( "There was a problem dumping the data disk. That is why we dump it to the LogFile : %1" ).arg( pData->asString() ) ); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + } | ||
| 72 | + else if( pData->TTL() > 0 ) | ||
| 73 | + { | ||
| 74 | + pData->decTTL(); | ||
| 75 | + m_queue.enqueue( pData ); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + this->startProcessing(); | ||
| 80 | + } | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +bool TransQueue::processing() const | ||
| 84 | +{ | ||
| 85 | + return m_queueTimer.isActive(); | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +void TransQueue::startProcessing( bool force ) | ||
| 89 | +{ | ||
| 90 | + if( force ) | ||
| 91 | + { | ||
| 92 | + m_queueTimer.stop(); | ||
| 93 | + /* | ||
| 94 | + * The timer will be started after slotProcessQueue is done processing. | ||
| 95 | + * Timer is implemented as a singleshot, preventing timeout() signals | ||
| 96 | + * to pile up due to the processingtime of the slot. | ||
| 97 | + */ | ||
| 98 | + this->slotProcessQueue(); | ||
| 99 | + } | ||
| 100 | + else | ||
| 101 | + { | ||
| 102 | + if( !m_queueTimer.isActive() ) | ||
| 103 | + { | ||
| 104 | + m_queueTimer.start(); | ||
| 105 | + } | ||
| 106 | + else | ||
| 107 | + { | ||
| 108 | + // Do nothing. timeout will trigger... | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +void TransQueue::stopProcessing( bool force ) | ||
| 114 | +{ | ||
| 115 | + if( force && m_queueTimer.isActive() ) | ||
| 116 | + { | ||
| 117 | + m_queueTimer.stop(); | ||
| 118 | + } | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +void TransQueue::slotProcessQueue() | ||
| 122 | +{ | ||
| 123 | + LogDebug( "[TransQueue::slotProcessQueue()]", QString("Starting processing the queue.") ); | ||
| 124 | + if( !m_queue.isEmpty() ) | ||
| 125 | + { | ||
| 126 | + LogDebug( "[TransQueue::slotProcessQueue()]", QString("Number of entries in the queue before : %1").arg( m_queue.size() ) ); | ||
| 127 | + auto pData = m_queue.dequeue(); | ||
| 128 | + ThreadContextScope tcs(pData->traceId()); | ||
| 129 | + emit signalProcessData( pData ); | ||
| 130 | + LogDebug( "[TransQueue::slotProcessQueue()]", QString("Number of entries in the queue after : %1").arg( m_queue.size() ) ); | ||
| 131 | + LogInfo( "[TransQueue::slotProcessQueue()]", QString("TTL Of package : %1").arg( pData->TTL() ) ); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + // Timer is intentionally set as a singleshot. We have to restart it | ||
| 135 | + // every time this slot is called. | ||
| 136 | + if( m_queue.size() > 0 ) | ||
| 137 | + { | ||
| 138 | + LogInfo( "[TransQueue::slotProcessQueue()]", QString( "Number of transactions in Queue : %1" ).arg( m_queue.size() ) ); | ||
| 139 | + m_queueTimer.start(); | ||
| 140 | + } | ||
| 141 | + else | ||
| 142 | + { | ||
| 143 | + LogInfo( "[TransQueue::slotProcessQueue()]", "Transaction Queue is Empty." ); | ||
| 144 | + // Just to be sure..... | ||
| 145 | + m_queueTimer.stop(); | ||
| 146 | + } | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +bool TransQueue::dumpToDisk( const QSharedPointer<ORMRelData>& data ) const | ||
| 150 | +{ | ||
| 151 | + if( data ) | ||
| 152 | + { | ||
| 153 | + QString strLogFile = DCXmlConfig::Instance().transactionPath(); | ||
| 154 | + OrmXmlWriter oWriter( strLogFile.toStdString() ); | ||
| 155 | + if( oWriter.writeToDisk() ) | ||
| 156 | + { | ||
| 157 | + LogWarning( "[TransQueue::dumpToDisk]", | ||
| 158 | + QString( "Datafile failed to save to disk. Content : <ormreldata_%1>%2" ).arg( data->getMainTableContainer()->timeStamp() ).arg( QString( oWriter.asString().c_str() ) ) ); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + } | ||
| 162 | + return false; | ||
| 163 | +} |
src/transqueue.h
0 → 100644
| 1 | +++ a/src/transqueue.h | ||
| 1 | +/* **************************************************************************** | ||
| 2 | + * Copyright 2019 Open Systems Development BV * | ||
| 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 shall be included in * | ||
| 12 | + * all copies or substantial portions of the Software. * | ||
| 13 | + * * | ||
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | ||
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | ||
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | ||
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | ||
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | ||
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | ||
| 20 | + * DEALINGS IN THE SOFTWARE. * | ||
| 21 | + * ***************************************************************************/ | ||
| 22 | + | ||
| 23 | +#ifndef OSDEV_COMPONENTS_TRANSQUEUE_H | ||
| 24 | +#define OSDEV_COMPONENTS_TRANSQUEUE_H | ||
| 25 | + | ||
| 26 | +#include "ormreldata.h" | ||
| 27 | + | ||
| 28 | +#include <QObject> | ||
| 29 | +#include <QQueue> | ||
| 30 | +#include <QTimer> | ||
| 31 | +#include <QMutex> | ||
| 32 | +#include <QMutexLocker> | ||
| 33 | + | ||
| 34 | +/* | ||
| 35 | + * _________________________________________ | ||
| 36 | + * / If voting could change the system, it \ | ||
| 37 | + * | would be illegal. If not voting could | | ||
| 38 | + * \ change the system, it would be illegal. / | ||
| 39 | + * ----------------------------------------- | ||
| 40 | + * \ | ||
| 41 | + * \ | ||
| 42 | + * .--. | ||
| 43 | + * |o_o | | ||
| 44 | + * |:_/ | | ||
| 45 | + * // \ \ | ||
| 46 | + * (| | ) | ||
| 47 | + * /'\_ _/`\ | ||
| 48 | + * \___)=(___/ | ||
| 49 | + * | ||
| 50 | + */ | ||
| 51 | + | ||
| 52 | +namespace osdev { | ||
| 53 | +namespace components { | ||
| 54 | +/*! | ||
| 55 | + * \class TransQueue | ||
| 56 | + * \brief The TransQueue class implements a transaction queue which will | ||
| 57 | + * catch rejected transactions from the ORM layer and offers them | ||
| 58 | + * back through the ETL-layer. An ORMRelPackage is "tagged" with | ||
| 59 | + * a transacion-id, which will keep track on how many times an | ||
| 60 | + * ORMRelPackage enters the queue. If the "TTL_iD (Time_To_live)" | ||
| 61 | + * reaches zero, the package is dropped and the ID is removed from | ||
| 62 | + * the administration. | ||
| 63 | + */ | ||
| 64 | +class TransQueue : public QObject | ||
| 65 | +{ | ||
| 66 | + Q_OBJECT | ||
| 67 | + | ||
| 68 | +public: | ||
| 69 | + /*! | ||
| 70 | + * \brief Represents a queue of transactions. | ||
| 71 | + * \param parent The parent QObject instance. | ||
| 72 | + */ | ||
| 73 | + explicit TransQueue( QObject *parent = nullptr ); | ||
| 74 | + | ||
| 75 | + // Deleted copy- and move constructors | ||
| 76 | + TransQueue( const TransQueue& ) = delete; | ||
| 77 | + TransQueue( const TransQueue&& ) = delete; | ||
| 78 | + TransQueue& operator=( const TransQueue& ) = delete; | ||
| 79 | + TransQueue& operator=( const TransQueue&& ) = delete; | ||
| 80 | + | ||
| 81 | + /*! | ||
| 82 | + * \brief Sets the TimeOut. | ||
| 83 | + * \param milliseconds The timeout to set in milliseconds. | ||
| 84 | + */ | ||
| 85 | + void setTimeOut( int milliseconds = 1 ); | ||
| 86 | + | ||
| 87 | + /*! | ||
| 88 | + * \return Whether this instance is currently processing transactions. | ||
| 89 | + */ | ||
| 90 | + bool processing() const; | ||
| 91 | + | ||
| 92 | + /*! | ||
| 93 | + * \brief Starts processing of transactions. | ||
| 94 | + * \param force Forces start of processing. | ||
| 95 | + */ | ||
| 96 | + void startProcessing( bool force = false ); | ||
| 97 | + | ||
| 98 | + /*! | ||
| 99 | + * \brief Stops processing of transactions. | ||
| 100 | + * \param force Forces stop of processing. | ||
| 101 | + */ | ||
| 102 | + void stopProcessing( bool force = false ); | ||
| 103 | + | ||
| 104 | + /*! | ||
| 105 | + * \return The number of currently outstanding transactions. | ||
| 106 | + */ | ||
| 107 | + int transactions() const { return m_queue.size(); } | ||
| 108 | + | ||
| 109 | +private: | ||
| 110 | + /*! | ||
| 111 | + * \brief This method will write the Contents of the data structure | ||
| 112 | + * to a transaction file for archiving and traceability purposes. | ||
| 113 | + * Not really decided on the format yet, but this will evolve over time. | ||
| 114 | + * \param data - The datastructure we want to write to a transaction Logfile. | ||
| 115 | + * Send as pointer. After writing to disk, the object have to be deleted. | ||
| 116 | + */ | ||
| 117 | + bool dumpToDisk( const QSharedPointer<ORMRelData>& data ) const; | ||
| 118 | + | ||
| 119 | + int m_TTL; ///< Time to Live start value. | ||
| 120 | + QTimer m_queueTimer; ///< Timer controlling the processing of the queue. | ||
| 121 | + QMutex m_queueMutex; ///< Mutex to prevent race conditions. Although QQueue is thread safe, we have to make sure *we* are. | ||
| 122 | + QQueue<QSharedPointer<ORMRelData>> m_queue; ///< The actual FIFO taking an ORMRelData pointer as input. | ||
| 123 | + | ||
| 124 | +signals: | ||
| 125 | + void signalProcessData( QSharedPointer<ORMRelData> pData ); | ||
| 126 | + | ||
| 127 | +public slots: | ||
| 128 | + /*! | ||
| 129 | + * \brief Sets (adds) a transaction to the queue. | ||
| 130 | + * \param pData The transaction data to set. | ||
| 131 | + */ | ||
| 132 | + void setTransaction( const QSharedPointer<ORMRelData>& pData ); | ||
| 133 | + | ||
| 134 | + | ||
| 135 | +private slots: | ||
| 136 | + /*! | ||
| 137 | + * \brief slotProcessQueue | ||
| 138 | + */ | ||
| 139 | + void slotProcessQueue(); | ||
| 140 | +}; | ||
| 141 | + | ||
| 142 | +} /* End namespace components */ | ||
| 143 | +} /* End namespace osdev */ | ||
| 144 | + | ||
| 145 | +#endif /* OSDEV_COMPONENTS_TRANSQUEUE_H */ |
tests/CMakeLists.txt
0 → 100644
| 1 | +++ a/tests/CMakeLists.txt | ||
| 1 | +cmake_minimum_required(VERSION 3.0) | ||
| 2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) | ||
| 3 | + | ||
| 4 | +include(projectheader) | ||
| 5 | +project_header(test_logutils) | ||
| 6 | + | ||
| 7 | +include_directories( SYSTEM | ||
| 8 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../src | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +include(compiler) | ||
| 12 | +set(SRC_LIST | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +# add_executable( ${PROJECT_NAME} | ||
| 16 | +# ${SRC_LIST} | ||
| 17 | +# ) | ||
| 18 | + | ||
| 19 | +# target_link_libraries( | ||
| 20 | +# ${PROJECT_NAME} | ||
| 21 | +# ) | ||
| 22 | + | ||
| 23 | +# set_target_properties( ${PROJECT_NAME} PROPERTIES | ||
| 24 | +# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin | ||
| 25 | +# LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib | ||
| 26 | +# ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/archive | ||
| 27 | +# ) | ||
| 28 | + | ||
| 29 | +# include(installation) | ||
| 30 | +# install_application() |