##// END OF EJS Templates
Update networkcontroller for abort mechanism
perrinel -
r755:076c09acb9f6
parent child
Show More
@@ -1,133 +1,142
1 #include "Network/NetworkController.h"
1 #include "Network/NetworkController.h"
2
2
3 #include <QMutex>
3 #include <QMutex>
4 #include <QNetworkAccessManager>
4 #include <QNetworkAccessManager>
5 #include <QNetworkReply>
5 #include <QNetworkReply>
6 #include <QNetworkRequest>
6 #include <QNetworkRequest>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 #include <unordered_map>
10 #include <unordered_map>
11
11
12 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
12 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
13
13
14 struct NetworkController::NetworkControllerPrivate {
14 struct NetworkController::NetworkControllerPrivate {
15 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
15 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
16
16
17 void lockRead() { m_Lock.lockForRead(); }
17 void lockRead() { m_Lock.lockForRead(); }
18 void lockWrite() { m_Lock.lockForWrite(); }
18 void lockWrite() { m_Lock.lockForWrite(); }
19 void unlock() { m_Lock.unlock(); }
19 void unlock() { m_Lock.unlock(); }
20
20
21 QMutex m_WorkingMutex;
21 QMutex m_WorkingMutex;
22
22
23 QReadWriteLock m_Lock;
23 QReadWriteLock m_Lock;
24 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
24 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToId;
25 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
25 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
26 };
26 };
27
27
28 NetworkController::NetworkController(QObject *parent)
28 NetworkController::NetworkController(QObject *parent)
29 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
29 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
30 {
30 {
31 }
31 }
32
32
33 void NetworkController::onProcessRequested(std::shared_ptr<QNetworkRequest> request,
33 void NetworkController::onProcessRequested(std::shared_ptr<QNetworkRequest> request,
34 QUuid identifier,
34 QUuid identifier,
35 std::function<void(QNetworkReply *, QUuid)> callback)
35 std::function<void(QNetworkReply *, QUuid)> callback)
36 {
36 {
37 qCDebug(LOG_NetworkController()) << tr("NetworkController onProcessRequested")
37 qCDebug(LOG_NetworkController()) << tr("NetworkController onProcessRequested")
38 << QThread::currentThread()->objectName() << &request;
38 << QThread::currentThread()->objectName() << &request;
39 auto reply = impl->m_AccessManager->get(*request);
39 auto reply = impl->m_AccessManager->get(*request);
40
40
41 // Store the couple reply id
41 // Store the couple reply id
42 impl->lockWrite();
42 impl->lockWrite();
43 impl->m_NetworkReplyToVariableId[reply] = identifier;
43 impl->m_NetworkReplyToId[reply] = identifier;
44 qCDebug(LOG_NetworkController()) << tr("Store for reply: ") << identifier;
44 impl->unlock();
45 impl->unlock();
45
46
46 auto onReplyFinished = [request, reply, this, identifier, callback]() {
47 auto onReplyFinished = [request, reply, this, identifier, callback]() {
47
48
48 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
49 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
49 << QThread::currentThread() << request.get() << reply;
50 << QThread::currentThread() << request.get() << reply;
50 impl->lockRead();
51 impl->lockRead();
51 auto it = impl->m_NetworkReplyToVariableId.find(reply);
52 auto it = impl->m_NetworkReplyToId.find(reply);
52 impl->unlock();
53 impl->unlock();
53 if (it != impl->m_NetworkReplyToVariableId.cend()) {
54 if (it != impl->m_NetworkReplyToId.cend()) {
54 impl->lockWrite();
55 impl->lockWrite();
55 impl->m_NetworkReplyToVariableId.erase(reply);
56 qCDebug(LOG_NetworkController()) << tr("Remove for reply: ")
57 << impl->m_NetworkReplyToId[reply];
58 impl->m_NetworkReplyToId.erase(reply);
56 impl->unlock();
59 impl->unlock();
57 // Deletes reply
60 // Deletes reply
58 callback(reply, identifier);
61 callback(reply, identifier);
59 reply->deleteLater();
62 reply->deleteLater();
60 }
63 }
61
64
62 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
65 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
63 << QThread::currentThread() << reply;
66 << QThread::currentThread() << reply;
64 };
67 };
65
68
66 auto onReplyProgress = [reply, request, this](qint64 bytesRead, qint64 totalBytes) {
69 auto onReplyProgress = [reply, request, this](qint64 bytesRead, qint64 totalBytes) {
67
70
68 double progress = (bytesRead * 100.0) / totalBytes;
71 // NOTE: a totalbytes of 0 can happened when a request has been aborted
69 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
72 if (totalBytes > 0) {
70 << QThread::currentThread() << request.get() << reply;
73 double progress = (bytesRead * 100.0) / totalBytes;
71 impl->lockRead();
74 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
72 auto it = impl->m_NetworkReplyToVariableId.find(reply);
75 << QThread::currentThread() << request.get() << reply
73 impl->unlock();
76 << bytesRead << totalBytes;
74 if (it != impl->m_NetworkReplyToVariableId.cend()) {
77 impl->lockRead();
75 emit this->replyDownloadProgress(it->second, request, progress);
78 auto it = impl->m_NetworkReplyToId.find(reply);
79 impl->unlock();
80 if (it != impl->m_NetworkReplyToId.cend()) {
81 emit this->replyDownloadProgress(it->second, request, progress);
82 }
83 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
84 << QThread::currentThread() << reply;
76 }
85 }
77 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
78 << QThread::currentThread() << reply;
79 };
86 };
80
87
81
88
82 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
89 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
83 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
90 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
84 qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
91 qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
85 << QThread::currentThread()->objectName() << reply;
92 << QThread::currentThread()->objectName() << reply;
86 }
93 }
87
94
88 void NetworkController::initialize()
95 void NetworkController::initialize()
89 {
96 {
90 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
97 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
91 impl->m_WorkingMutex.lock();
98 impl->m_WorkingMutex.lock();
92 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
99 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
93
100
94
101
95 auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
102 auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
96
103
97 qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
104 qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
98
105
99 };
106 };
100
107
101
108
102 connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
109 connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
103
110
104 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
111 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
105 }
112 }
106
113
107 void NetworkController::finalize()
114 void NetworkController::finalize()
108 {
115 {
109 impl->m_WorkingMutex.unlock();
116 impl->m_WorkingMutex.unlock();
110 }
117 }
111
118
112 void NetworkController::onReplyCanceled(QUuid identifier)
119 void NetworkController::onReplyCanceled(QUuid identifier)
113 {
120 {
114 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
121 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
115 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
122 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
116 << QThread::currentThread();
123 << QThread::currentThread() << identifier;
117
124
118
125
119 impl->lockRead();
126 impl->lockRead();
120 auto end = impl->m_NetworkReplyToVariableId.cend();
127 auto end = impl->m_NetworkReplyToId.cend();
121 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
128 auto it = std::find_if(impl->m_NetworkReplyToId.cbegin(), end, findReply);
122 impl->unlock();
129 impl->unlock();
123 if (it != end) {
130 if (it != end) {
131 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled ABORT DONE")
132 << QThread::currentThread() << identifier;
124 it->first->abort();
133 it->first->abort();
125 }
134 }
126 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
135 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
127 << QThread::currentThread();
136 << QThread::currentThread();
128 }
137 }
129
138
130 void NetworkController::waitForFinish()
139 void NetworkController::waitForFinish()
131 {
140 {
132 QMutexLocker locker{&impl->m_WorkingMutex};
141 QMutexLocker locker{&impl->m_WorkingMutex};
133 }
142 }
General Comments 0
You need to be logged in to leave comments. Login now