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() | ... | ... |