Mercurial > hg > orthanc
changeset 5905:dad78aa9141e get-scu
move/get jobs: progress
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Fri, 06 Dec 2024 12:06:05 +0100 |
parents | bed6a8ba5431 |
children | 573c538a2405 |
files | NEWS OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.cpp OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.h |
diffstat | 8 files changed, 103 insertions(+), 73 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Thu Dec 05 12:02:33 2024 +0100 +++ b/NEWS Fri Dec 06 12:06:05 2024 +0100 @@ -27,6 +27,7 @@ https://discourse.orthanc-server.org/t/dicomwebplugin-does-not-return-series-metadata-properly/5195 * /queries/../retrieve now accepts a new field in the payload: "RetrieveMethod" to define wheter Orthanc uses C-MOVE or C-GET to retrieve the resource. +* improved progress reporting of DicomMoveScu jobs. Maintenance -----------
--- a/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.cpp Fri Dec 06 12:06:05 2024 +0100 @@ -393,6 +393,22 @@ } } + void MoveProgressCallback(void *callbackData, + T_DIMSE_C_MoveRQ *request, + int responseCount, + T_DIMSE_C_MoveRSP *response) + { + DicomControlUserConnection::IProgressListener* listener = reinterpret_cast<DicomControlUserConnection::IProgressListener*>(callbackData); + if (listener) + { + LOG(INFO) << "---------" << response->NumberOfRemainingSubOperations << " " << response->NumberOfCompletedSubOperations; + listener->OnProgressUpdated(response->NumberOfRemainingSubOperations, + response->NumberOfCompletedSubOperations, + response->NumberOfFailedSubOperations, + response->NumberOfWarningSubOperations); + } + } + void DicomControlUserConnection::MoveInternal(const std::string& targetAet, ResourceType level, @@ -434,7 +450,8 @@ DcmDataset* statusDetail = NULL; DcmDataset* responseIdentifiers = NULL; OFCondition cond = DIMSE_moveUser( - &association_->GetDcmtkAssociation(), presID, &request, dataset, /*moveCallback*/ NULL, NULL, + &association_->GetDcmtkAssociation(), presID, &request, dataset, + (progressListener_ != NULL ? MoveProgressCallback : NULL), progressListener_, /*opt_blockMode*/ (parameters_.HasTimeout() ? DIMSE_NONBLOCKING : DIMSE_BLOCKING), /*opt_dimse_timeout*/ parameters_.GetTimeout(), &association_->GetDcmtkNetwork(), /*subOpCallback*/ NULL, NULL, @@ -456,6 +473,14 @@ OFString str; CLOG(TRACE, DICOM) << "Received Final Move Response:" << std::endl << DIMSE_dumpMessage(str, response, DIMSE_INCOMING); + + if (progressListener_ != NULL) + { + progressListener_->OnProgressUpdated(response.NumberOfRemainingSubOperations, + response.NumberOfCompletedSubOperations, + response.NumberOfFailedSubOperations, + response.NumberOfWarningSubOperations); + } } /** @@ -495,8 +520,6 @@ assert(association_.get() != NULL); association_->Open(parameters_); - // TODO-GET: if findResults is the result of a C-Find, we can use the SopClassUIDs for the negotiation - std::unique_ptr<ParsedDicomFile> query( ConvertQueryFields(findResult, parameters_.GetRemoteModality().GetManufacturer())); DcmDataset* queryDataset = query->GetDcmtkObject().getDataset(); @@ -550,7 +573,7 @@ OFCondition cond = DIMSE_sendMessageUsingMemoryData( &(association_->GetDcmtkAssociation()), cgetPresID, &msgGetRequest, NULL /* statusDetail */, queryDataset, - NULL /* progress callback TODO-GET */, NULL /* callback context */, NULL /* commandSet */); + NULL, NULL, NULL /* commandSet */); if (cond.bad()) { @@ -597,17 +620,18 @@ << DIMSE_dumpMessage(tempStr, rsp, DIMSE_INCOMING, NULL, cmdPresId); } - // TODO-GET: for progress handler - // OFunique_ptr<RetrieveResponse> getRSP(new RetrieveResponse()); - // getRSP->m_affectedSOPClassUID = rsp.msg.CGetRSP.AffectedSOPClassUID; - // getRSP->m_messageIDRespondedTo = rsp.msg.CGetRSP.MessageIDBeingRespondedTo; - // getRSP->m_status = rsp.msg.CGetRSP.DimseStatus; - // getRSP->m_numberOfRemainingSubops = rsp.msg.CGetRSP.NumberOfRemainingSubOperations; - // getRSP->m_numberOfCompletedSubops = rsp.msg.CGetRSP.NumberOfCompletedSubOperations; - // getRSP->m_numberOfFailedSubops = rsp.msg.CGetRSP.NumberOfFailedSubOperations; - // getRSP->m_numberOfWarningSubops = rsp.msg.CGetRSP.NumberOfWarningSubOperations; - // getRSP->m_statusDetail = statusDetail; + if (progressListener_ != NULL) + { + progressListener_->OnProgressUpdated(rsp.msg.CGetRSP.NumberOfRemainingSubOperations, + rsp.msg.CGetRSP.NumberOfCompletedSubOperations, + rsp.msg.CGetRSP.NumberOfFailedSubOperations, + rsp.msg.CGetRSP.NumberOfWarningSubOperations); + } + if (rsp.msg.CGetRSP.DimseStatus == 0x0000) // final success message + { + continueSession = false; + } } // Handle C-STORE Request else if (rsp.CommandField == DIMSE_C_STORE_RQ) @@ -669,7 +693,7 @@ result = DIMSE_sendMessageUsingMemoryData(&(association_->GetDcmtkAssociation()), cmdPresId, &storeResponse, NULL /* statusDetail */, NULL /* dataObject */, - NULL /* progress callback TODO-GET */, NULL /* callback context */, NULL /* commandSet */); + NULL, NULL, NULL /* commandSet */); if (result.bad()) { continueSession = false; @@ -704,7 +728,8 @@ DicomControlUserConnection::DicomControlUserConnection(const DicomAssociationParameters& params, ScuOperationFlags scuOperation) : parameters_(params), - association_(new DicomAssociation) + association_(new DicomAssociation), + progressListener_(NULL) { assert((scuOperation & ScuOperationFlags_Get) == 0); // you must provide acceptedStorageSopClassUids for Get SCU std::set<std::string> emptyStorageSopClasses; @@ -718,7 +743,8 @@ const std::set<std::string>& acceptedStorageSopClasses, const std::list<DicomTransferSyntax>& proposedStorageTransferSyntaxes) : parameters_(params), - association_(new DicomAssociation) + association_(new DicomAssociation), + progressListener_(NULL) { SetupPresentationContexts(scuOperation, acceptedStorageSopClasses, proposedStorageTransferSyntaxes); }
--- a/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancFramework/Sources/DicomNetworking/DicomControlUserConnection.h Fri Dec 06 12:06:05 2024 +0100 @@ -63,9 +63,20 @@ class DicomControlUserConnection : public boost::noncopyable { + public: + class IProgressListener + { + public: + virtual void OnProgressUpdated(uint16_t nbRemainingSubOperations, + uint16_t nbCompletedSubOperations, + uint16_t nbFailedSubOperations, + uint16_t nbWarningSubOperations) = 0; + }; + private: DicomAssociationParameters parameters_; boost::shared_ptr<DicomAssociation> association_; + IProgressListener* progressListener_; void SetupPresentationContexts(ScuOperationFlags scuOperation, const std::set<std::string>& acceptedStorageSopClasses, @@ -99,6 +110,11 @@ bool Echo(); + void SetProgressListener(IProgressListener* progressListener) + { + progressListener_ = progressListener; + } + void Find(DicomFindAnswers& result, ResourceType level, const DicomMap& originalFields,
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Fri Dec 06 12:06:05 2024 +0100 @@ -915,59 +915,6 @@ } - // static void SubmitGetScuJob(RestApiPostCall& call, - // bool allAnswers, - // size_t index) - // { - // ServerContext& context = OrthancRestApi::GetContext(call); - - // int timeout = -1; - // Json::Value body; - - // if (call.ParseJsonRequest(body)) - // { - // timeout = Toolbox::GetJsonIntegerField(body, KEY_TIMEOUT, -1); - // } - - // std::unique_ptr<DicomGetScuJob> job(new DicomGetScuJob(context)); - // job->SetQueryFormat(OrthancRestApi::GetDicomFormat(body, DicomToJsonFormat_Short)); - - // { - // QueryAccessor query(call); - // job->SetRemoteModality(query.GetHandler().GetRemoteModality()); - - // if (timeout >= 0) - // { - // // New in Orthanc 1.7.0 - // job->SetTimeout(static_cast<uint32_t>(timeout)); - // } - // else if (query.GetHandler().HasTimeout()) - // { - // // New in Orthanc 1.9.1 - // job->SetTimeout(query.GetHandler().GetTimeout()); - // } - - // LOG(WARNING) << "Driving C-Get SCU on remote modality " - // << query.GetHandler().GetRemoteModality().GetApplicationEntityTitle(); - - // if (allAnswers) - // { - // for (size_t i = 0; i < query.GetHandler().GetAnswersCount(); i++) - // { - // job->AddFindAnswer(query.GetHandler(), i); - // } - // } - // else - // { - // job->AddFindAnswer(query.GetHandler(), index); - // } - // } - - // OrthancRestApi::GetApi(call).SubmitCommandsJob - // (call, job.release(), true /* synchronous by default */, body); - // } - - static void SubmitRetrieveJob(RestApiPostCall& call, bool allAnswers, size_t index)
--- a/OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp Fri Dec 06 12:06:05 2024 +0100 @@ -99,7 +99,8 @@ sopClassesToPropose, proposedTransferSyntaxes)); } - + + connection_->SetProgressListener(this); connection_->Get(findAnswer, InstanceReceivedHandler, &context_); }
--- a/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp Fri Dec 06 12:06:05 2024 +0100 @@ -46,6 +46,7 @@ connection_.reset(new DicomControlUserConnection(parameters_, ScuOperationFlags_Move)); } + connection_->SetProgressListener(this); connection_->Move(targetAet_, findAnswer); }
--- a/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.cpp Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.cpp Fri Dec 06 12:06:05 2024 +0100 @@ -160,7 +160,11 @@ context_(context), parameters_(DicomAssociationParameters::UnserializeJob(serialized)), query_(true), - queryFormat_(DicomToJsonFormat_Short) + queryFormat_(DicomToJsonFormat_Short), + nbRemainingSubOperations_(0), + nbCompletedSubOperations_(0), + nbFailedSubOperations_(0), + nbWarningSubOperations_(0) { if (serialized.isMember(QUERY)) { @@ -202,4 +206,26 @@ return true; } } + + void DicomRetrieveScuBaseJob::OnProgressUpdated(uint16_t nbRemainingSubOperations, + uint16_t nbCompletedSubOperations, + uint16_t nbFailedSubOperations, + uint16_t nbWarningSubOperations) + { + nbRemainingSubOperations_ = nbRemainingSubOperations; + nbCompletedSubOperations_ = nbCompletedSubOperations; + nbFailedSubOperations_ = nbFailedSubOperations; + nbWarningSubOperations_ = nbWarningSubOperations; + } + + float DicomRetrieveScuBaseJob::GetProgress() + { + uint32_t totalOperations = nbRemainingSubOperations_ + nbCompletedSubOperations_ + nbFailedSubOperations_ + nbWarningSubOperations_; + if (totalOperations == 0) + { + return 0.0f; + } + + return float(nbCompletedSubOperations_ + nbFailedSubOperations_ + nbWarningSubOperations_) / float(totalOperations); + } }
--- a/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.h Thu Dec 05 12:02:33 2024 +0100 +++ b/OrthancServer/Sources/ServerJobs/DicomRetrieveScuBaseJob.h Fri Dec 06 12:06:05 2024 +0100 @@ -32,7 +32,7 @@ { class ServerContext; - class DicomRetrieveScuBaseJob : public SetOfCommandsJob + class DicomRetrieveScuBaseJob : public SetOfCommandsJob, public DicomControlUserConnection::IProgressListener { protected: class Command : public SetOfCommandsJob::ICommand @@ -87,6 +87,11 @@ std::unique_ptr<DicomControlUserConnection> connection_; + uint16_t nbRemainingSubOperations_; + uint16_t nbCompletedSubOperations_; + uint16_t nbFailedSubOperations_; + uint16_t nbWarningSubOperations_; + virtual void Retrieve(const DicomMap &findAnswer) = 0; explicit DicomRetrieveScuBaseJob(ServerContext &context) : @@ -130,5 +135,12 @@ virtual void GetPublicContent(Json::Value &value) ORTHANC_OVERRIDE; virtual bool Serialize(Json::Value &target) ORTHANC_OVERRIDE; + + virtual void OnProgressUpdated(uint16_t nbRemainingSubOperations, + uint16_t nbCompletedSubOperations, + uint16_t nbFailedSubOperations, + uint16_t nbWarningSubOperations) ORTHANC_OVERRIDE; + + virtual float GetProgress() ORTHANC_OVERRIDE; }; }