Mercurial > hg > orthanc-stone
comparison Framework/Oracle/WebAssemblyOracle.cpp @ 1245:3d4dc87af04b broker
ParseDicomFromWadoCommand working in wasm
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 07 Jan 2020 11:56:20 +0100 |
parents | b17959d4da06 |
children | c1c83c1fb837 |
comparison
equal
deleted
inserted
replaced
1244:b17959d4da06 | 1245:3d4dc87af04b |
---|---|
24 #include "OracleCommandExceptionMessage.h" | 24 #include "OracleCommandExceptionMessage.h" |
25 #include "SleepOracleCommand.h" | 25 #include "SleepOracleCommand.h" |
26 | 26 |
27 #if ORTHANC_ENABLE_DCMTK == 1 | 27 #if ORTHANC_ENABLE_DCMTK == 1 |
28 # include "ParseDicomSuccessMessage.h" | 28 # include "ParseDicomSuccessMessage.h" |
29 static unsigned int BUCKET_SOP = 1; | |
29 #endif | 30 #endif |
30 | 31 |
31 #include <Core/OrthancException.h> | 32 #include <Core/OrthancException.h> |
32 #include <Core/Toolbox.h> | 33 #include <Core/Toolbox.h> |
33 | 34 |
144 const T& GetTypedCommand() const | 145 const T& GetTypedCommand() const |
145 { | 146 { |
146 return dynamic_cast<T&>(*command_); | 147 return dynamic_cast<T&>(*command_); |
147 } | 148 } |
148 | 149 |
150 #if ORTHANC_ENABLE_DCMTK == 1 | |
151 void StoreInCache(const std::string& sopInstanceUid, | |
152 std::auto_ptr<Orthanc::ParsedDicomFile>& dicom, | |
153 size_t fileSize) | |
154 { | |
155 if (oracle_.dicomCache_.get()) | |
156 { | |
157 // Store it into the cache for future use | |
158 oracle_.dicomCache_->Acquire(BUCKET_SOP, sopInstanceUid, | |
159 dicom.release(), fileSize, true); | |
160 } | |
161 } | |
162 #endif | |
163 | |
149 static void SuccessCallback(emscripten_fetch_t *fetch) | 164 static void SuccessCallback(emscripten_fetch_t *fetch) |
150 { | 165 { |
151 /** | 166 /** |
152 * Firstly, make a local copy of the fetched information, and | 167 * Firstly, make a local copy of the fetched information, and |
153 * free data associated with the fetch. | 168 * free data associated with the fetch. |
165 if (fetch->numBytes > 0) | 180 if (fetch->numBytes > 0) |
166 { | 181 { |
167 answer.assign(fetch->data, fetch->numBytes); | 182 answer.assign(fetch->data, fetch->numBytes); |
168 } | 183 } |
169 | 184 |
185 | |
170 /** | 186 /** |
171 * TODO - HACK - As of emscripten-1.38.31, the fetch API does | 187 * Retrieving the headers of the HTTP answer. |
172 * not contain a way to retrieve the HTTP headers of the | 188 **/ |
173 * answer. We make the assumption that the "Content-Type" header | 189 HttpHeaders headers; |
174 * of the response is the same as the "Accept" header of the | 190 |
175 * query. This should be fixed in future versions of emscripten. | 191 #if (__EMSCRIPTEN_major__ < 1 || \ |
192 (__EMSCRIPTEN_major__ == 1 && __EMSCRIPTEN_minor__ < 38) || \ | |
193 (__EMSCRIPTEN_major__ == 1 && __EMSCRIPTEN_minor__ == 38 && __EMSCRIPTEN_tiny__ < 37)) | |
194 # warning Consider upgrading Emscripten to a version above 1.38.37, incomplete support of Fetch API | |
195 | |
196 /** | |
197 * HACK - If emscripten < 1.38.37, the fetch API does not | |
198 * contain a way to retrieve the HTTP headers of the answer. We | |
199 * make the assumption that the "Content-Type" header of the | |
200 * response is the same as the "Accept" header of the | |
201 * query. This is fixed thanks to the | |
202 * "emscripten_fetch_get_response_headers()" function that was | |
203 * added to "fetch.h" at emscripten-1.38.37 on 2019-06-26. | |
204 * | |
205 * https://github.com/emscripten-core/emscripten/blob/1.38.37/system/include/emscripten/fetch.h | |
176 * https://github.com/emscripten-core/emscripten/pull/8486 | 206 * https://github.com/emscripten-core/emscripten/pull/8486 |
177 * | |
178 * TODO - The function "emscripten_fetch_get_response_headers()" | |
179 * was added to "fetch.h" at emscripten-1.38.37 on 2019-06-26. | |
180 * https://github.com/emscripten-core/emscripten/blob/1.38.37/system/include/emscripten/fetch.h | |
181 **/ | 207 **/ |
182 | |
183 HttpHeaders headers; | |
184 if (fetch->userData != NULL) | 208 if (fetch->userData != NULL) |
185 { | 209 { |
186 if (!context->GetExpectedContentType().empty()) | 210 if (!context->GetExpectedContentType().empty()) |
187 { | 211 { |
188 headers["Content-Type"] = context->GetExpectedContentType(); | 212 headers["Content-Type"] = context->GetExpectedContentType(); |
189 } | 213 } |
190 } | 214 } |
215 #else | |
216 { | |
217 size_t size = emscripten_fetch_get_response_headers_length(fetch); | |
218 | |
219 std::string plainHeaders(size + 1, '\0'); | |
220 emscripten_fetch_get_response_headers(fetch, &plainHeaders[0], size + 1); | |
221 | |
222 std::vector<std::string> tokens; | |
223 Orthanc::Toolbox::TokenizeString(tokens, plainHeaders, '\n'); | |
224 | |
225 for (size_t i = 0; i < tokens.size(); i++) | |
226 { | |
227 size_t p = tokens[i].find(':'); | |
228 if (p != std::string::npos) | |
229 { | |
230 std::string key = Orthanc::Toolbox::StripSpaces(tokens[i].substr(0, p)); | |
231 std::string value = Orthanc::Toolbox::StripSpaces(tokens[i].substr(p + 1)); | |
232 headers[key] = value; | |
233 } | |
234 } | |
235 } | |
236 #endif | |
191 | 237 |
192 LOG(TRACE) << "About to call emscripten_fetch_close"; | 238 LOG(TRACE) << "About to call emscripten_fetch_close"; |
193 emscripten_fetch_close(fetch); | 239 emscripten_fetch_close(fetch); |
194 LOG(TRACE) << "Successfully called emscripten_fetch_close"; | 240 LOG(TRACE) << "Successfully called emscripten_fetch_close"; |
195 | 241 |
240 } | 286 } |
241 | 287 |
242 case IOracleCommand::Type_ParseDicomFromWado: | 288 case IOracleCommand::Type_ParseDicomFromWado: |
243 { | 289 { |
244 #if ORTHANC_ENABLE_DCMTK == 1 | 290 #if ORTHANC_ENABLE_DCMTK == 1 |
291 const ParseDicomFromWadoCommand& command = | |
292 context->GetTypedCommand<ParseDicomFromWadoCommand>(); | |
293 | |
245 size_t fileSize; | 294 size_t fileSize; |
246 std::auto_ptr<Orthanc::ParsedDicomFile> dicom | 295 std::auto_ptr<Orthanc::ParsedDicomFile> dicom |
247 (ParseDicomSuccessMessage::ParseWadoAnswer(fileSize, answer, headers)); | 296 (ParseDicomSuccessMessage::ParseWadoAnswer(fileSize, answer, headers)); |
248 LOG(WARNING) << "bingo"; | 297 |
298 { | |
299 ParseDicomSuccessMessage message(command, *dicom, fileSize, true); | |
300 context->EmitMessage(message); | |
301 } | |
302 | |
303 context->StoreInCache(command.GetSopInstanceUid(), dicom, fileSize); | |
249 #else | 304 #else |
250 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 305 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
251 #endif | 306 #endif |
252 break; | 307 break; |
253 } | 308 } |
594 void WebAssemblyOracle::Execute(boost::weak_ptr<IObserver> receiver, | 649 void WebAssemblyOracle::Execute(boost::weak_ptr<IObserver> receiver, |
595 ParseDicomFromWadoCommand* command) | 650 ParseDicomFromWadoCommand* command) |
596 { | 651 { |
597 std::auto_ptr<ParseDicomFromWadoCommand> protection(command); | 652 std::auto_ptr<ParseDicomFromWadoCommand> protection(command); |
598 | 653 |
599 // TODO - CACHE | 654 #if ORTHANC_ENABLE_DCMTK == 1 |
600 | 655 if (dicomCache_.get()) |
601 | 656 { |
657 ParsedDicomCache::Reader reader(*dicomCache_, BUCKET_SOP, protection->GetSopInstanceUid()); | |
658 if (reader.IsValid() && | |
659 reader.HasPixelData()) | |
660 { | |
661 // Reuse the DICOM file from the cache | |
662 ParseDicomSuccessMessage message(*protection, reader.GetDicom(), | |
663 reader.GetFileSize(), reader.HasPixelData()); | |
664 EmitMessage(receiver, message); | |
665 return; | |
666 } | |
667 } | |
668 #endif | |
669 | |
602 switch (command->GetRestCommand().GetType()) | 670 switch (command->GetRestCommand().GetType()) |
603 { | 671 { |
604 case IOracleCommand::Type_Http: | 672 case IOracleCommand::Type_Http: |
605 { | 673 { |
606 const HttpCommand& rest = | 674 const HttpCommand& rest = |
706 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 774 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
707 } | 775 } |
708 | 776 |
709 return true; | 777 return true; |
710 } | 778 } |
779 | |
780 | |
781 void WebAssemblyOracle::SetDicomCacheSize(size_t size) | |
782 { | |
783 #if ORTHANC_ENABLE_DCMTK == 1 | |
784 if (size == 0) | |
785 { | |
786 dicomCache_.reset(); | |
787 } | |
788 else | |
789 { | |
790 dicomCache_.reset(new ParsedDicomCache(size)); | |
791 } | |
792 #else | |
793 LOG(INFO) << "DCMTK support is disabled, the DICOM cache is disabled"; | |
794 #endif | |
795 } | |
711 } | 796 } |