Mercurial > hg > orthanc
comparison Core/HttpClient.cpp @ 3590:d5740d3b1d67
fix for issue #156: Chunked Dicom-web transfer uses 100% CPU
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Mon, 23 Dec 2019 10:42:59 +0100 |
parents | 96780208dbd7 |
children | 19d88138c30f |
comparison
equal
deleted
inserted
replaced
3589:a648c2d67a65 | 3590:d5740d3b1d67 |
---|---|
42 | 42 |
43 #include <string.h> | 43 #include <string.h> |
44 #include <curl/curl.h> | 44 #include <curl/curl.h> |
45 #include <boost/algorithm/string/predicate.hpp> | 45 #include <boost/algorithm/string/predicate.hpp> |
46 #include <boost/thread/mutex.hpp> | 46 #include <boost/thread/mutex.hpp> |
47 | 47 #include <list> |
48 | 48 |
49 // Default timeout = 60 seconds (in Orthanc <= 1.5.6, it was 10 seconds) | 49 // Default timeout = 60 seconds (in Orthanc <= 1.5.6, it was 10 seconds) |
50 static const unsigned int DEFAULT_HTTP_TIMEOUT = 60; | 50 static const unsigned int DEFAULT_HTTP_TIMEOUT = 60; |
51 | 51 |
52 | 52 |
207 | 207 |
208 class HttpClient::CurlRequestBody : public boost::noncopyable | 208 class HttpClient::CurlRequestBody : public boost::noncopyable |
209 { | 209 { |
210 private: | 210 private: |
211 HttpClient::IRequestBody* body_; | 211 HttpClient::IRequestBody* body_; |
212 std::string buffer_; | 212 std::string sourceBuffer_; |
213 size_t sourceBufferTransmittedSize_; | |
213 | 214 |
214 size_t CallbackInternal(char* curlBuffer, | 215 size_t CallbackInternal(char* curlBuffer, |
215 size_t curlBufferSize) | 216 size_t curlBufferSize) |
216 { | 217 { |
217 if (body_ == NULL) | 218 if (body_ == NULL) |
223 { | 224 { |
224 throw OrthancException(ErrorCode_InternalError); | 225 throw OrthancException(ErrorCode_InternalError); |
225 } | 226 } |
226 | 227 |
227 // Read chunks from the body stream so as to fill the target buffer | 228 // Read chunks from the body stream so as to fill the target buffer |
228 std::string chunk; | 229 size_t curlBufferFilledSize = 0; |
230 size_t sourceRemainingSize = sourceBuffer_.size() - sourceBufferTransmittedSize_; | |
231 bool hasMore = true; | |
229 | 232 |
230 while (buffer_.size() < curlBufferSize && | 233 while (sourceRemainingSize < curlBufferSize && hasMore) |
231 body_->ReadNextChunk(chunk)) | 234 { |
232 { | 235 if (sourceRemainingSize > 0) |
233 buffer_ += chunk; | 236 { |
234 } | 237 // transmit the end of current source buffer |
235 | 238 memcpy(curlBuffer + curlBufferFilledSize, sourceBuffer_.data() + sourceBufferTransmittedSize_, sourceRemainingSize); |
236 size_t s = std::min(buffer_.size(), curlBufferSize); | 239 |
237 | 240 curlBufferFilledSize += sourceRemainingSize; |
238 if (s != 0) | 241 } |
239 { | 242 |
240 memcpy(curlBuffer, buffer_.c_str(), s); | 243 // start filling a new source buffer |
241 | 244 sourceBufferTransmittedSize_ = 0; |
242 // Remove the bytes that were actually sent from the buffer | 245 sourceBuffer_.clear(); |
243 buffer_.erase(0, s); | 246 |
244 } | 247 hasMore = body_->ReadNextChunk(sourceBuffer_); |
245 | 248 |
246 return s; | 249 sourceRemainingSize = sourceBuffer_.size(); |
250 } | |
251 | |
252 if (sourceRemainingSize > 0 && (curlBufferSize - curlBufferFilledSize) > 0) | |
253 { | |
254 size_t s = std::min(sourceRemainingSize, curlBufferSize - curlBufferFilledSize); | |
255 | |
256 memcpy(curlBuffer + curlBufferFilledSize, sourceBuffer_.data() + sourceBufferTransmittedSize_, s); | |
257 | |
258 sourceBufferTransmittedSize_ += s; | |
259 curlBufferFilledSize += s; | |
260 } | |
261 | |
262 return curlBufferFilledSize; | |
247 } | 263 } |
248 | 264 |
249 public: | 265 public: |
250 CurlRequestBody() : | 266 CurlRequestBody() : |
251 body_(NULL) | 267 body_(NULL), |
268 sourceBufferTransmittedSize_(0) | |
252 { | 269 { |
253 } | 270 } |
254 | 271 |
255 void SetBody(HttpClient::IRequestBody& body) | 272 void SetBody(HttpClient::IRequestBody& body) |
256 { | 273 { |
257 body_ = &body; | 274 body_ = &body; |
258 buffer_.clear(); | 275 sourceBufferTransmittedSize_ = 0; |
276 sourceBuffer_.clear(); | |
259 } | 277 } |
260 | 278 |
261 void Clear() | 279 void Clear() |
262 { | 280 { |
263 body_ = NULL; | 281 body_ = NULL; |
264 buffer_.clear(); | 282 sourceBufferTransmittedSize_ = 0; |
283 sourceBuffer_.clear(); | |
265 } | 284 } |
266 | 285 |
267 bool IsValid() const | 286 bool IsValid() const |
268 { | 287 { |
269 return body_ != NULL; | 288 return body_ != NULL; |