Heart 1.4.918.d927d9c
Heart is base back end library for your c++ Qt projects.
Loading...
Searching...
No Matches
bigdataparser.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022-2025 QuasarApp.
3 * Distributed under the lgplv3 software license, see the accompanying
4 * Everyone is permitted to copy and distribute verbatim copies
5 * of this license document, but changing it is not allowed.
6*/
7
8#include "bigdataparser.h"
9#include "bigdataheader.h"
10#include "bigdatapart.h"
11
12#include <bigdatarequest.h>
13#include <abstractnode.h>
14#include <cmath>
15#include <params.h>
16#include <bigdatawraper.h>
17
18#define TIMEOUT_INTERVAL 30000
19
20namespace QH {
21
30
31ParserResult BigDataParser::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
32 const Header &pkgHeader,
33 AbstractNodeInfo *sender) {
34
35
36 auto result = commandHandler<PKG::BigDataRequest>(this,
38 pkg, sender, pkgHeader);
39 if (result != QH::ParserResult::NotProcessed) {
40 return result;
41 }
42
45 pkg, sender, pkgHeader);
46 if (result != QH::ParserResult::NotProcessed) {
47 return result;
48 }
49
52 pkg, sender, pkgHeader);
53 if (result != QH::ParserResult::NotProcessed) {
54 return result;
55 }
56
59 pkg, sender, pkgHeader);
60 if (result != QH::ParserResult::NotProcessed) {
61 return result;
62 }
63
65}
66
68 return 1;
69}
70
71QString BigDataParser::parserId() const {
72 return "HeartBigDataAPI";
73}
74
75void QH::BigDataParser::insertNewBigData(const QSharedPointer<PKG::BigDataHeader> &header) {
76 if (!_pool.contains(header->packageId())) {
77 QVector<QSharedPointer<PKG::BigDataPart>> _array;
78 _array.resize(header->getPackagesCount());
79 _pool[header->packageId()] = {header, _array, static_cast<int>(time(0))};
80 }
81
82 checkOutDatedPacakges(header->packageId());
83}
84
85bool BigDataParser::newPackage(const QSharedPointer<PKG::BigDataHeader> &header,
86 AbstractNodeInfo *sender,
87 const Header & hdr) {
88
89 if (!header->isValid())
90 return false;
91
92 insertNewBigData(header);
93
94 PKG::BigDataRequest request;
95 request.setCurrentPart(0);
96 request.setPackageId(header->packageId());
97
98 qDebug() << "Receive BigData Header:" << header->toString();
99
100 return node()->sendData(&request, sender, &hdr);
101}
102
103bool BigDataParser::processPart(const QSharedPointer<PKG::BigDataPart> &part,
104 AbstractNodeInfo *sender,
105 const Header & hdr) {
106
107 if (!_pool.contains(part->packageId())) {
108 return false;
109 }
110
111 checkOutDatedPacakges(part->packageId());
112
113 auto& localPool = _pool[part->packageId()];
114
115 qDebug () << "Process Part of" << part->packageId() << ": part" << part->getPakckageNumber() << "/" << localPool.chaindata.size() - 1;
116
117 localPool.chaindata[part->getPakckageNumber()] = part;
118
119 auto sendRequest = [sender, &hdr, this](int part, unsigned int id){
120
121 PKG::BigDataRequest request;
122 request.setCurrentPart(part);
123 request.setPackageId(id);
124
125 return node()->sendData(&request, sender, &hdr);
126 };
127
128 if (part->getPakckageNumber() + 1 < localPool.chaindata.size()) {
129 return sendRequest(part->getPakckageNumber() + 1,
130 part->packageId());
131
132 }
133
134 auto package = node()->genPackage(localPool.header->getCommand(),
135 sender);
136 if (!package)
137 return false;
138
139 QByteArray packageRawData;
140 for (int idx = 0; idx < localPool.chaindata.size(); ++idx) {
141 if (localPool.chaindata[idx]) {
142 packageRawData += localPool.chaindata[idx]->data();
143 } else {
144 return sendRequest(idx, part->packageId());
145 }
146 }
147
148 package->fromBytes(packageRawData);
149
150 if (node()->parsePackage(package, hdr, sender) == ParserResult::Error) {
151 return false;
152 }
153
154 _pool.remove(part->packageId());
155
156 return true;
157}
158
159bool BigDataParser::processRequest(const QSharedPointer<PKG::BigDataRequest> &request,
160 AbstractNodeInfo *sender,
161 const Header &pkgHeader) {
162
163
164 unsigned int id = request->packageId();
165
166 if (!_pool.contains(id)) {
167 qDebug() << "requested data is missing!";
168 return false;
169 }
170
171 checkOutDatedPacakges(id);
172
173 const auto &localPool = _pool[id];
174 if (request->currentPart() >= localPool.chaindata.size()) {
175 return false;
176 }
177
178 bool fLast = localPool.chaindata.size() - 1 == request->currentPart();
179
180 const auto &data = localPool.chaindata[request->currentPart()];
181 if (!node()->sendData(data.data(), sender, &pkgHeader)) {
182 return false;
183 }
184
185 if (fLast) {
186 _pool.remove(id);
187 }
188
189 return true;
190}
191
192bool BigDataParser::processBigDataWraper(const QSharedPointer<PKG::BigDataWraper> &request,
193 AbstractNodeInfo *sender,
194 const Header &pkgHeader) {
195 return sendBigDataPackage(request->data(), sender, &pkgHeader);
196}
197
198bool BigDataParser::sendBigDataPackage(const PKG::AbstractData *data,
199 const AbstractNodeInfo *sender,
200 const QH::Header *pkgHeader) {
201
202 unsigned int sizeLimit = Package::maximumSize() - sizeof (PKG::BigDataPart);
203 auto rawData = data->toBytes();
204
205 auto hdr = QSharedPointer<PKG::BigDataHeader>::create();
206 hdr->setPackagesCount(std::ceil(rawData.size() / static_cast<double>(sizeLimit)));
207 hdr->setPackageId(rand());
208 hdr->setCommand(data->cmd());
209
210 insertNewBigData(hdr);
211
212 for (int i = 0; i < hdr->getPackagesCount(); ++i) {
213 auto part = QSharedPointer<PKG::BigDataPart>::create();
214 part->setPackageId(hdr->packageId());
215 part->setPakckageNumber(i);
216 part->setData(rawData.mid(i * sizeLimit, sizeLimit));
217
218 _pool[hdr->packageId()].chaindata[i] = part;
219 }
220
221
222 if (!node()->sendData(hdr.data(), sender, pkgHeader)) {
223 return false;
224 }
225
226 return true;
227}
228
229void BigDataParser::checkOutDatedPacakges(unsigned int currentProcessedId) {
230 int utx = time(0);
231
232 if (_pool.contains(currentProcessedId)) {
233 _pool[currentProcessedId].lastUpdate = utx;
234 }
235
236 for (auto key = _pool.keyBegin(); key != _pool.keyEnd(); ++key) {
237 if (utx - _pool[*key].lastUpdate > TIMEOUT_INTERVAL) {
238 _pool.remove(*key);
239 }
240 }
241}
242
243}
#define TIMEOUT_INTERVAL
The AbstractNodeInfo class contains information about client or server connection and tcp socket of n...
virtual unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &address, const Header *req=nullptr)
sendData This method send data object another to node
QString parserId() const override
parserId This is id of the parsers. All parser will be synced betwin nodes by ids.
ParserResult parsePackage(const QSharedPointer< PKG::AbstractData > &pkg, const Header &pkgHeader, AbstractNodeInfo *sender) override
parsePackage This is main method of all childs classes of an AbstractNode class. This method work on ...
bool processBigDataWraper(const QSharedPointer< PKG::BigDataWraper > &request, AbstractNodeInfo *sender, const Header &pkgHeader)
sendBigDataPackage This method separate big pacakge and sent only heder ot serve.
bool processPart(const QSharedPointer< PKG::BigDataPart > &part, AbstractNodeInfo *sender, const QH::Header &pkgHeader)
processPart This method process part of package
bool processRequest(const QSharedPointer< PKG::BigDataRequest > &request, QH::AbstractNodeInfo *sender, const QH::Header &pkgHeader)
finishPart This metho process last package of big data transaction.
BigDataParser(AbstractNode *parentNode)
int version() const override
version This method return version of parser object
bool newPackage(const QSharedPointer< PKG::BigDataHeader > &header, AbstractNodeInfo *sender, const Header &pkgHeader)
newPackage This method process first header packge of the big data.
The AbstractData class is provide base functions for transport data by network For create you own pac...
virtual unsigned short cmd() const =0
cmd - This is command of this object, (for generate cmd use macross QH_PACKAGE)
void setPackageId(int newPackageId)
setPackageId This method sets new id of package that this package moving
The BigDataPart class This data class used for transporting big data files greater than 64kb.
Definition bigdatapart.h:22
The BigDataRequest class contains missing package parts for redownload. If missing parts count is 0 t...
void setCurrentPart(int newCurrentPart)
setCurrentPart This method sets current new value of current page
static unsigned int maximumSize()
maximumSize This method return maximu size of pacakge. If pacakge large the maximum size then package...
Definition package.cpp:49
QByteArray toBytes() const
toBytes This method convert a current object to bytes array.
virtual unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &address, const Header *req=nullptr) const
sendData This method send data object another to node
Definition iparser.cpp:50
void registerPackageType()
registerPackageType This method register package type T. This is need to prepare pacakge for parsing ...
Definition iparser.h:62
AbstractNode * node() const
Definition iparser.cpp:46
iParser(AbstractNode *parentNode)
Definition iparser.cpp:17
friend class AbstractNode
Definition iparser.h:266
ParserResult commandHandler(HandlerType handlerObject, HandlerMethod method, const QSharedPointer< QH::PKG::AbstractData > &pkg, QH::AbstractNodeInfo *sender, const QH::Header &pkgHeader)
commandHandler This method it is simple wrapper for the handle pacakges in the AbstractNode::parsePac...
Definition iparser.h:167
The QH namespace - QuasarApp Heart namespace. This namespace contains all classes of the Heart librar...
Definition heart.cpp:13
ParserResult
The ParserResult enum. Error - parser detect a errorob package. NotProcessed - the parser does not kn...
Definition iparser.h:35
@ NotProcessed
the parser does not know what to do with the package or has not finished processing it.
Definition iparser.h:39
@ Error
parser detect a errorob package.
Definition iparser.h:37
The Header struct 32 bytes.
Definition header.h:19