comparison Framework/Oracle/GenericOracleRunner.cpp @ 1134:87fbeb823375 broker

allocating messages from oracle commands on the stack
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 06 Nov 2019 15:16:45 +0100
parents 8e3763d1736a
children a0a33e5ea5bb
comparison
equal deleted inserted replaced
1133:0e3a3be313fd 1134:87fbeb823375
98 << " to " << answer.size() << " bytes"; 98 << " to " << answer.size() << " bytes";
99 } 99 }
100 } 100 }
101 101
102 102
103 static IMessage* Execute(const HttpCommand& command) 103 static void RunInternal(boost::weak_ptr<IObserver> receiver,
104 IMessageEmitter& emitter,
105 HttpCommand& command)
104 { 106 {
105 Orthanc::HttpClient client; 107 Orthanc::HttpClient client;
106 client.SetUrl(command.GetUrl()); 108 client.SetUrl(command.GetUrl());
107 client.SetMethod(command.GetMethod()); 109 client.SetMethod(command.GetMethod());
108 client.SetTimeout(command.GetTimeout()); 110 client.SetTimeout(command.GetTimeout());
124 Orthanc::HttpClient::HttpHeaders answerHeaders; 126 Orthanc::HttpClient::HttpHeaders answerHeaders;
125 client.ApplyAndThrowException(answer, answerHeaders); 127 client.ApplyAndThrowException(answer, answerHeaders);
126 128
127 DecodeAnswer(answer, answerHeaders); 129 DecodeAnswer(answer, answerHeaders);
128 130
129 return new HttpCommand::SuccessMessage(command, answerHeaders, answer); 131 HttpCommand::SuccessMessage message(command, answerHeaders, answer);
130 } 132 emitter.EmitMessage(receiver, message);
131 133 }
132 134
133 static IMessage* Execute(const Orthanc::WebServiceParameters& orthanc, 135
134 const OrthancRestApiCommand& command) 136 static void RunInternal(boost::weak_ptr<IObserver> receiver,
137 IMessageEmitter& emitter,
138 const Orthanc::WebServiceParameters& orthanc,
139 OrthancRestApiCommand& command)
135 { 140 {
136 Orthanc::HttpClient client(orthanc, command.GetUri()); 141 Orthanc::HttpClient client(orthanc, command.GetUri());
137 client.SetMethod(command.GetMethod()); 142 client.SetMethod(command.GetMethod());
138 client.SetTimeout(command.GetTimeout()); 143 client.SetTimeout(command.GetTimeout());
139 144
149 Orthanc::HttpClient::HttpHeaders answerHeaders; 154 Orthanc::HttpClient::HttpHeaders answerHeaders;
150 client.ApplyAndThrowException(answer, answerHeaders); 155 client.ApplyAndThrowException(answer, answerHeaders);
151 156
152 DecodeAnswer(answer, answerHeaders); 157 DecodeAnswer(answer, answerHeaders);
153 158
154 return new OrthancRestApiCommand::SuccessMessage(command, answerHeaders, answer); 159 OrthancRestApiCommand::SuccessMessage message(command, answerHeaders, answer);
155 } 160 emitter.EmitMessage(receiver, message);
156 161 }
157 162
158 static IMessage* Execute(const Orthanc::WebServiceParameters& orthanc, 163
159 const GetOrthancImageCommand& command) 164 static void RunInternal(boost::weak_ptr<IObserver> receiver,
165 IMessageEmitter& emitter,
166 const Orthanc::WebServiceParameters& orthanc,
167 GetOrthancImageCommand& command)
160 { 168 {
161 Orthanc::HttpClient client(orthanc, command.GetUri()); 169 Orthanc::HttpClient client(orthanc, command.GetUri());
162 client.SetTimeout(command.GetTimeout()); 170 client.SetTimeout(command.GetTimeout());
163 171
164 CopyHttpHeaders(client, command.GetHttpHeaders()); 172 CopyHttpHeaders(client, command.GetHttpHeaders());
167 Orthanc::HttpClient::HttpHeaders answerHeaders; 175 Orthanc::HttpClient::HttpHeaders answerHeaders;
168 client.ApplyAndThrowException(answer, answerHeaders); 176 client.ApplyAndThrowException(answer, answerHeaders);
169 177
170 DecodeAnswer(answer, answerHeaders); 178 DecodeAnswer(answer, answerHeaders);
171 179
172 return command.ProcessHttpAnswer(answer, answerHeaders); 180 command.ProcessHttpAnswer(receiver, emitter, answer, answerHeaders);
173 } 181 }
174 182
175 183
176 static IMessage* Execute(const Orthanc::WebServiceParameters& orthanc, 184 static void RunInternal(boost::weak_ptr<IObserver> receiver,
177 const GetOrthancWebViewerJpegCommand& command) 185 IMessageEmitter& emitter,
186 const Orthanc::WebServiceParameters& orthanc,
187 GetOrthancWebViewerJpegCommand& command)
178 { 188 {
179 Orthanc::HttpClient client(orthanc, command.GetUri()); 189 Orthanc::HttpClient client(orthanc, command.GetUri());
180 client.SetTimeout(command.GetTimeout()); 190 client.SetTimeout(command.GetTimeout());
181 191
182 CopyHttpHeaders(client, command.GetHttpHeaders()); 192 CopyHttpHeaders(client, command.GetHttpHeaders());
185 Orthanc::HttpClient::HttpHeaders answerHeaders; 195 Orthanc::HttpClient::HttpHeaders answerHeaders;
186 client.ApplyAndThrowException(answer, answerHeaders); 196 client.ApplyAndThrowException(answer, answerHeaders);
187 197
188 DecodeAnswer(answer, answerHeaders); 198 DecodeAnswer(answer, answerHeaders);
189 199
190 return command.ProcessHttpAnswer(answer); 200 command.ProcessHttpAnswer(receiver, emitter, answer);
191 } 201 }
192 202
193 203
194 static std::string GetPath(const std::string& root, 204 static std::string GetPath(const std::string& root,
195 const std::string& file) 205 const std::string& file)
210 LOG(TRACE) << "Oracle reading file: " << c.string(); 220 LOG(TRACE) << "Oracle reading file: " << c.string();
211 return c.string(); 221 return c.string();
212 } 222 }
213 223
214 224
215 static IMessage* Execute(const std::string& root, 225 static void RunInternal(boost::weak_ptr<IObserver> receiver,
216 ReadFileCommand& command) 226 IMessageEmitter& emitter,
227 const std::string& root,
228 ReadFileCommand& command)
217 { 229 {
218 std::string path = GetPath(root, command.GetPath()); 230 std::string path = GetPath(root, command.GetPath());
219 231
220 std::string content; 232 std::string content;
221 Orthanc::SystemToolbox::ReadFile(content, path, true /* log */); 233 Orthanc::SystemToolbox::ReadFile(content, path, true /* log */);
222 234
223 return new ReadFileCommand::SuccessMessage(command, content); 235 ReadFileCommand::SuccessMessage message(command, content);
236 emitter.EmitMessage(receiver, message);
224 } 237 }
225 238
226 239
227 #if ORTHANC_ENABLE_DCMTK == 1 240 #if ORTHANC_ENABLE_DCMTK == 1
228 static ParseDicomFileCommand::SuccessMessage* Execute(const std::string& root, 241 static void RunInternal(boost::weak_ptr<IObserver> receiver,
229 const ParseDicomFileCommand& command) 242 IMessageEmitter& emitter,
243 const std::string& root,
244 ParseDicomFileCommand& command)
230 { 245 {
231 std::string path = GetPath(root, command.GetPath()); 246 std::string path = GetPath(root, command.GetPath());
232 247
233 if (!Orthanc::SystemToolbox::IsRegularFile(path)) 248 if (!Orthanc::SystemToolbox::IsRegularFile(path))
234 { 249 {
269 284
270 printf("Reading %s\n", path.c_str()); 285 printf("Reading %s\n", path.c_str());
271 286
272 if (ok) 287 if (ok)
273 { 288 {
274 return new ParseDicomFileCommand::SuccessMessage 289 Orthanc::ParsedDicomFile parsed(dicom);
275 (command, dicom, static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); 290 ParseDicomFileCommand::SuccessMessage message
291 (command, parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded());
292 emitter.EmitMessage(receiver, message);
276 } 293 }
277 else 294 else
278 { 295 {
279 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, 296 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
280 "Cannot parse file: " + path); 297 "Cannot parse file: " + path);
281 } 298 }
282 } 299 }
283 300
284 301
285 static ParseDicomFileCommand::SuccessMessage* Execute(boost::shared_ptr<ParsedDicomFileCache> cache, 302 static void RunInternal(boost::weak_ptr<IObserver> receiver,
286 const std::string& root, 303 IMessageEmitter& emitter,
287 const ParseDicomFileCommand& command) 304 boost::shared_ptr<ParsedDicomFileCache> cache,
305 const std::string& root,
306 ParseDicomFileCommand& command)
288 { 307 {
289 #if 0 308 #if 0
290 // The code to use the cache is buggy in multithreaded environments => TODO FIX 309 // The code to use the cache is buggy in multithreaded environments => TODO FIX
291 if (cache.get()) 310 if (cache.get())
292 { 311 {
297 reader.HasPixelData())) 316 reader.HasPixelData()))
298 { 317 {
299 // Reuse the DICOM file from the cache 318 // Reuse the DICOM file from the cache
300 return new ParseDicomFileCommand::SuccessMessage( 319 return new ParseDicomFileCommand::SuccessMessage(
301 command, reader.GetDicom(), reader.GetFileSize(), reader.HasPixelData()); 320 command, reader.GetDicom(), reader.GetFileSize(), reader.HasPixelData());
321 emitter.EmitMessage(receiver, message);
322 return;
302 } 323 }
303 } 324 }
304 325
305 // Not in the cache, first read and parse the DICOM file 326 // Not in the cache, first read and parse the DICOM file
306 std::auto_ptr<ParseDicomFileCommand::SuccessMessage> message(Execute(root, command)); 327 std::auto_ptr<ParseDicomFileCommand::SuccessMessage> message(RunInternal(root, command));
307 328
308 // Secondly, store it into the cache for future use 329 // Secondly, store it into the cache for future use
309 assert(&message->GetOrigin() == &command); 330 assert(&message->GetOrigin() == &command);
310 cache->Acquire(message->GetOrigin().GetPath(), message->GetDicom(), 331 cache->Acquire(message->GetOrigin().GetPath(), message->GetDicom(),
311 message->GetFileSize(), message->HasPixelData()); 332 message->GetFileSize(), message->HasPixelData());
313 return message.release(); 334 return message.release();
314 } 335 }
315 else 336 else
316 { 337 {
317 // No cache available 338 // No cache available
318 return Execute(root, command); 339 return RunInternal(root, command);
319 } 340 }
320 #else 341 #else
321 return Execute(root, command); 342 return RunInternal(receiver, emitter, root, command);
322 #endif 343 #endif
323 } 344 }
324 345
325 #endif 346 #endif
326 347
327 348
328 IMessage* GenericOracleRunner::Run(IOracleCommand& command) 349 void GenericOracleRunner::Run(boost::weak_ptr<IObserver> receiver,
329 { 350 IMessageEmitter& emitter,
351 IOracleCommand& command)
352 {
353 Orthanc::ErrorCode error = Orthanc::ErrorCode_Success;
354
330 try 355 try
331 { 356 {
332 switch (command.GetType()) 357 switch (command.GetType())
333 { 358 {
334 case IOracleCommand::Type_Sleep: 359 case IOracleCommand::Type_Sleep:
335 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType, 360 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType,
336 "Sleep command cannot be executed by the runner"); 361 "Sleep command cannot be executed by the runner");
337 362
338 case IOracleCommand::Type_Http: 363 case IOracleCommand::Type_Http:
339 return Execute(dynamic_cast<const HttpCommand&>(command)); 364 RunInternal(receiver, emitter, dynamic_cast<HttpCommand&>(command));
365 break;
340 366
341 case IOracleCommand::Type_OrthancRestApi: 367 case IOracleCommand::Type_OrthancRestApi:
342 return Execute(orthanc_, dynamic_cast<const OrthancRestApiCommand&>(command)); 368 RunInternal(receiver, emitter, orthanc_,
369 dynamic_cast<OrthancRestApiCommand&>(command));
370 break;
343 371
344 case IOracleCommand::Type_GetOrthancImage: 372 case IOracleCommand::Type_GetOrthancImage:
345 return Execute(orthanc_, dynamic_cast<const GetOrthancImageCommand&>(command)); 373 RunInternal(receiver, emitter, orthanc_,
374 dynamic_cast<GetOrthancImageCommand&>(command));
375 break;
346 376
347 case IOracleCommand::Type_GetOrthancWebViewerJpeg: 377 case IOracleCommand::Type_GetOrthancWebViewerJpeg:
348 return Execute(orthanc_, dynamic_cast<const GetOrthancWebViewerJpegCommand&>(command)); 378 RunInternal(receiver, emitter, orthanc_,
379 dynamic_cast<GetOrthancWebViewerJpegCommand&>(command));
380 break;
349 381
350 case IOracleCommand::Type_ReadFile: 382 case IOracleCommand::Type_ReadFile:
351 return Execute(rootDirectory_, dynamic_cast<ReadFileCommand&>(command)); 383 RunInternal(receiver, emitter, rootDirectory_,
384 dynamic_cast<ReadFileCommand&>(command));
385 break;
352 386
353 case IOracleCommand::Type_ParseDicomFile: 387 case IOracleCommand::Type_ParseDicomFile:
354 #if ORTHANC_ENABLE_DCMTK == 1 388 #if ORTHANC_ENABLE_DCMTK == 1
355 return Execute(dicomCache_, rootDirectory_, 389 RunInternal(receiver, emitter, dicomCache_, rootDirectory_,
356 dynamic_cast<const ParseDicomFileCommand&>(command)); 390 dynamic_cast<ParseDicomFileCommand&>(command));
391 break;
357 #else 392 #else
358 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, 393 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented,
359 "DCMTK must be enabled to parse DICOM files"); 394 "DCMTK must be enabled to parse DICOM files");
360 #endif 395 #endif
361 396
364 } 399 }
365 } 400 }
366 catch (Orthanc::OrthancException& e) 401 catch (Orthanc::OrthancException& e)
367 { 402 {
368 LOG(ERROR) << "Exception within the oracle: " << e.What(); 403 LOG(ERROR) << "Exception within the oracle: " << e.What();
369 return new OracleCommandExceptionMessage(command, e); 404 error = e.GetErrorCode();
370 } 405 }
371 catch (...) 406 catch (...)
372 { 407 {
373 LOG(ERROR) << "Threaded exception within the oracle"; 408 LOG(ERROR) << "Threaded exception within the oracle";
374 return new OracleCommandExceptionMessage(command, Orthanc::ErrorCode_InternalError); 409 error = Orthanc::ErrorCode_InternalError;
375 } 410 }
411
412 OracleCommandExceptionMessage message(command, error);
413 emitter.EmitMessage(receiver, message);
376 } 414 }
377 } 415 }