Mercurial > hg > orthanc-transfers
annotate Framework/HttpQueries/HttpQueriesQueue.cpp @ 77:1e396fb509ca default
updated copyright, as Orthanc Team now replaces Osimis
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 30 May 2024 22:44:10 +0200 |
parents | f4e828607f02 |
children |
rev | line source |
---|---|
0 | 1 /** |
2 * Transfers accelerator plugin for Orthanc | |
77
1e396fb509ca
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
44
diff
changeset
|
3 * Copyright (C) 2018-2023 Osimis S.A., Belgium |
1e396fb509ca
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
44
diff
changeset
|
4 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
1e396fb509ca
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
44
diff
changeset
|
5 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "HttpQueriesQueue.h" | |
23 | |
20 | 24 #include <Logging.h> |
25 #include <OrthancException.h> | |
0 | 26 |
27 namespace OrthancPlugins | |
28 { | |
29 HttpQueriesQueue::Status HttpQueriesQueue::GetStatusInternal() const | |
30 { | |
31 if (successQueries_ == queries_.size()) | |
32 { | |
33 return Status_Success; | |
34 } | |
35 else if (isFailure_) | |
36 { | |
37 return Status_Failure; | |
38 } | |
39 else | |
40 { | |
41 return Status_Running; | |
42 } | |
43 } | |
44 | |
45 | |
8
4c3437217518
fix for compatibility with simplified OrthancPluginCppWrapper
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5
diff
changeset
|
46 HttpQueriesQueue::HttpQueriesQueue() : |
0 | 47 maxRetries_(0) |
48 { | |
49 Reset(); | |
50 } | |
51 | |
52 | |
53 HttpQueriesQueue::~HttpQueriesQueue() | |
54 { | |
55 for (size_t i = 0; i < queries_.size(); i++) | |
56 { | |
57 assert(queries_[i] != NULL); | |
58 delete queries_[i]; | |
59 } | |
60 } | |
61 | |
62 | |
63 unsigned int HttpQueriesQueue::GetMaxRetries() | |
64 { | |
65 boost::mutex::scoped_lock lock(mutex_); | |
66 return maxRetries_; | |
67 } | |
68 | |
69 | |
70 void HttpQueriesQueue::SetMaxRetries(unsigned int maxRetries) | |
71 { | |
72 boost::mutex::scoped_lock lock(mutex_); | |
73 maxRetries_ = maxRetries; | |
74 } | |
75 | |
76 | |
77 void HttpQueriesQueue::Reserve(size_t size) | |
78 { | |
79 boost::mutex::scoped_lock lock(mutex_); | |
80 queries_.reserve(size); | |
81 } | |
82 | |
83 | |
84 void HttpQueriesQueue::Reset() | |
85 { | |
86 boost::mutex::scoped_lock lock(mutex_); | |
87 position_ = 0; | |
88 downloadedSize_ = 0; | |
89 uploadedSize_ = 0; | |
90 successQueries_ = 0; | |
91 isFailure_ = false; | |
92 } | |
93 | |
94 | |
95 void HttpQueriesQueue::Enqueue(IHttpQuery* query) | |
96 { | |
97 if (query == NULL) | |
98 { | |
99 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
100 } | |
101 else | |
102 { | |
103 boost::mutex::scoped_lock lock(mutex_); | |
104 queries_.push_back(query); | |
105 } | |
106 } | |
107 | |
108 | |
3 | 109 bool HttpQueriesQueue::ExecuteOneQuery(size_t& networkTraffic) |
0 | 110 { |
111 networkTraffic = 0; | |
112 | |
113 unsigned int maxRetries; | |
114 IHttpQuery* query = NULL; | |
115 | |
116 { | |
117 boost::mutex::scoped_lock lock(mutex_); | |
118 | |
119 maxRetries = maxRetries_; | |
120 | |
121 if (position_ == queries_.size() || | |
122 isFailure_) | |
123 { | |
124 return false; | |
125 } | |
126 else | |
127 { | |
128 query = queries_[position_]; | |
129 position_ ++; | |
130 } | |
131 } | |
132 | |
133 std::string body; | |
134 | |
135 if (query->GetMethod() == Orthanc::HttpMethod_Post || | |
136 query->GetMethod() == Orthanc::HttpMethod_Put) | |
137 { | |
138 query->ReadBody(body); | |
139 } | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
140 |
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
141 std::map<std::string, std::string> headers; |
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
142 query->GetHttpHeaders(headers); |
0 | 143 |
144 unsigned int retry = 0; | |
145 | |
146 for (;;) | |
147 { | |
8
4c3437217518
fix for compatibility with simplified OrthancPluginCppWrapper
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
5
diff
changeset
|
148 MemoryBuffer answer; |
0 | 149 |
150 bool success; | |
151 | |
152 try | |
153 { | |
154 switch (query->GetMethod()) | |
155 { | |
156 case Orthanc::HttpMethod_Get: | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
157 success = peers_.DoGet(answer, query->GetPeer(), query->GetUri(), headers); |
0 | 158 break; |
159 | |
160 case Orthanc::HttpMethod_Post: | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
161 success = peers_.DoPost(answer, query->GetPeer(), query->GetUri(), body, headers); |
0 | 162 break; |
163 | |
164 case Orthanc::HttpMethod_Put: | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
165 success = peers_.DoPut(query->GetPeer(), query->GetUri(), body, headers); |
0 | 166 break; |
167 | |
168 case Orthanc::HttpMethod_Delete: | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
169 success = peers_.DoDelete(query->GetPeer(), query->GetUri(), headers); |
0 | 170 break; |
171 | |
172 default: | |
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
174 } | |
175 } | |
176 catch (Orthanc::OrthancException& e) | |
177 { | |
178 LOG(ERROR) << "Unhandled exception during an HTTP query to peer \"" | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
179 << query->GetPeer() << " " << query->GetUri() + "\": " << e.What(); |
0 | 180 success = false; |
181 } | |
182 | |
183 if (success) | |
184 { | |
185 size_t downloaded = 0; | |
186 size_t uploaded = 0; | |
187 | |
188 if (query->GetMethod() == Orthanc::HttpMethod_Get || | |
189 query->GetMethod() == Orthanc::HttpMethod_Post) | |
190 { | |
191 query->HandleAnswer(answer.GetData(), answer.GetSize()); | |
192 downloaded = answer.GetSize(); | |
193 } | |
194 | |
195 if (query->GetMethod() == Orthanc::HttpMethod_Put || | |
196 query->GetMethod() == Orthanc::HttpMethod_Post) | |
197 { | |
198 uploaded = body.size(); | |
199 } | |
200 | |
201 networkTraffic = downloaded + uploaded; | |
202 | |
203 { | |
204 boost::mutex::scoped_lock lock(mutex_); | |
205 downloadedSize_ += downloaded; | |
206 uploadedSize_ += uploaded; | |
207 successQueries_ ++; | |
208 | |
209 if (successQueries_ == queries_.size()) | |
210 { | |
211 completed_.notify_all(); | |
212 } | |
213 | |
214 return true; | |
215 } | |
216 } | |
217 else | |
218 { | |
219 // Error: Let's retry | |
220 retry ++; | |
221 | |
10
c9e28e31262e
new option: MaxHttpRetries
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
9
diff
changeset
|
222 if (retry <= maxRetries) |
0 | 223 { |
224 // Wait 1 second before retrying | |
225 boost::this_thread::sleep(boost::posix_time::seconds(1)); | |
226 } | |
227 else | |
228 { | |
44
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
229 if (maxRetries > 0) |
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
230 { |
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
231 LOG(ERROR) << "Reached the maximum number of retries for a HTTP query to peer " << query->GetPeer() << " " << query->GetUri(); |
f4e828607f02
Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
Alain Mazy <am@osimis.io>
parents:
33
diff
changeset
|
232 } |
0 | 233 |
234 { | |
235 boost::mutex::scoped_lock lock(mutex_); | |
236 isFailure_ = true; | |
237 completed_.notify_all(); | |
238 } | |
239 | |
240 return false; | |
241 } | |
242 } | |
243 } | |
244 } | |
245 | |
246 | |
247 HttpQueriesQueue::Status HttpQueriesQueue::WaitComplete(unsigned int timeoutMS) | |
248 { | |
249 boost::mutex::scoped_lock lock(mutex_); | |
250 | |
251 Status status = GetStatusInternal(); | |
252 | |
253 if (status == Status_Running) | |
254 { | |
255 completed_.timed_wait(lock, boost::posix_time::milliseconds(timeoutMS)); | |
256 return GetStatusInternal(); | |
257 } | |
258 else | |
259 { | |
260 return status; | |
261 } | |
262 } | |
263 | |
264 | |
265 void HttpQueriesQueue::WaitComplete() | |
266 { | |
267 boost::mutex::scoped_lock lock(mutex_); | |
268 | |
269 while (GetStatusInternal() == Status_Running) | |
270 { | |
271 completed_.timed_wait(lock, boost::posix_time::milliseconds(200)); | |
272 } | |
273 } | |
274 | |
275 | |
276 void HttpQueriesQueue::GetStatistics(size_t& scheduledQueriesCount, | |
277 size_t& successQueriesCount, | |
278 uint64_t& downloadedSize, | |
279 uint64_t& uploadedSize) | |
280 { | |
281 boost::mutex::scoped_lock lock(mutex_); | |
282 scheduledQueriesCount = queries_.size(); | |
283 successQueriesCount = successQueries_; | |
284 downloadedSize = downloadedSize_; | |
285 uploadedSize = uploadedSize_; | |
286 } | |
287 } |