comparison OrthancStone/Sources/Loaders/LoaderStateMachine.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Loaders/LoaderStateMachine.cpp@30deba7bc8e2
children 85e117739eca
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
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 "LoaderStateMachine.h"
23
24 #include "../Loaders/ILoadersContext.h"
25
26 #include <OrthancException.h>
27
28 namespace OrthancStone
29 {
30 void LoaderStateMachine::State::Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
31 {
32 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
33 }
34
35
36 void LoaderStateMachine::State::Handle(const OrthancStone::GetOrthancImageCommand::SuccessMessage& message)
37 {
38 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
39 }
40
41
42 void LoaderStateMachine::State::Handle(const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message)
43 {
44 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
45 }
46
47
48 void LoaderStateMachine::Schedule(OrthancStone::OracleCommandBase* command)
49 {
50 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Schedule()";
51
52 std::unique_ptr<OrthancStone::OracleCommandBase> protection(command);
53
54 if (command == NULL)
55 {
56 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
57 }
58
59 if (!command->HasPayload())
60 {
61 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
62 "The payload must contain the next state");
63 }
64 pendingCommands_.push_back(protection.release());
65
66 Step();
67 }
68
69
70 void LoaderStateMachine::Start()
71 {
72 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Start()";
73
74 if (active_)
75 {
76 LOG(TRACE) << "LoaderStateMachine::Start() called while active_ is true";
77 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
78 }
79
80 active_ = true;
81
82 for (size_t i = 0; i < simultaneousDownloads_; i++)
83 {
84 Step();
85 }
86 }
87
88
89 void LoaderStateMachine::Step()
90 {
91 if (!pendingCommands_.empty() &&
92 activeCommands_ < simultaneousDownloads_)
93 {
94
95 OrthancStone::IOracleCommand* nextCommand = pendingCommands_.front();
96
97 LOG(TRACE) << " LoaderStateMachine(" << std::hex << this << std::dec <<
98 ")::Step(): activeCommands_ (" << activeCommands_ <<
99 ") < simultaneousDownloads_ (" << simultaneousDownloads_ <<
100 ") --> will Schedule command addr " << std::hex << nextCommand << std::dec;
101
102 {
103 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
104 boost::shared_ptr<IObserver> observer(GetSharedObserver());
105 lock->Schedule(observer, 0, nextCommand); // TODO: priority!
106 }
107 pendingCommands_.pop_front();
108
109 activeCommands_++;
110 }
111 else
112 {
113 LOG(TRACE) << " LoaderStateMachine(" << std::hex << this << std::dec <<
114 ")::Step(): activeCommands_ (" << activeCommands_ <<
115 ") >= simultaneousDownloads_ (" << simultaneousDownloads_ <<
116 ") --> will NOT Schedule command";
117 }
118 }
119
120
121 void LoaderStateMachine::Clear()
122 {
123 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Clear()";
124 for (PendingCommands::iterator it = pendingCommands_.begin();
125 it != pendingCommands_.end(); ++it)
126 {
127 delete *it;
128 }
129
130 pendingCommands_.clear();
131 }
132
133
134 void LoaderStateMachine::HandleExceptionMessage(const OrthancStone::OracleCommandExceptionMessage& message)
135 {
136 LOG(ERROR) << "LoaderStateMachine::HandleExceptionMessage: error in the state machine, stopping all processing";
137 LOG(ERROR) << "Error: " << message.GetException().What() << " Details: " <<
138 message.GetException().GetDetails();
139 Clear();
140 }
141
142 template <typename T>
143 void LoaderStateMachine::HandleSuccessMessage(const T& message)
144 {
145 if (activeCommands_ <= 0) {
146 LOG(ERROR) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::HandleSuccessMessage : activeCommands_ should be > 0 but is: " << activeCommands_;
147 }
148 else {
149 activeCommands_--;
150 try
151 {
152 dynamic_cast<State&>(message.GetOrigin().GetPayload()).Handle(message);
153 Step();
154 }
155 catch (Orthanc::OrthancException& e)
156 {
157 LOG(ERROR) << "Error in the state machine, stopping all processing: " <<
158 e.What() << " Details: " << e.GetDetails();
159 Clear();
160 }
161 }
162 }
163
164
165 LoaderStateMachine::LoaderStateMachine(
166 OrthancStone::ILoadersContext& loadersContext)
167 : loadersContext_(loadersContext)
168 , active_(false)
169 , simultaneousDownloads_(4)
170 , activeCommands_(0)
171 {
172 using OrthancStone::ILoadersContext;
173
174 LOG(TRACE)
175 << "LoaderStateMachine(" << std::hex << this
176 << std::dec << ")::LoaderStateMachine()";
177 }
178
179 void LoaderStateMachine::PostConstructor()
180 {
181 std::unique_ptr<OrthancStone::ILoadersContext::ILock>
182 lock(loadersContext_.Lock());
183
184 OrthancStone::IObservable& observable = lock->GetOracleObservable();
185
186 // TODO => Move this out of constructor
187 Register<OrthancStone::OrthancRestApiCommand::SuccessMessage>(
188 observable, &LoaderStateMachine::HandleSuccessMessage);
189 Register<OrthancStone::GetOrthancImageCommand::SuccessMessage>(
190 observable, &LoaderStateMachine::HandleSuccessMessage);
191 Register<OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage>(
192 observable, &LoaderStateMachine::HandleSuccessMessage);
193 Register<OrthancStone::OracleCommandExceptionMessage>(
194 observable, &LoaderStateMachine::HandleExceptionMessage);
195 }
196
197 LoaderStateMachine::~LoaderStateMachine()
198 {
199 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::~LoaderStateMachine()";
200 Clear();
201 }
202
203 void LoaderStateMachine::SetSimultaneousDownloads(unsigned int count)
204 {
205 if (active_)
206 {
207 LOG(ERROR) << "LoaderStateMachine::SetSimultaneousDownloads called while active_ is true";
208 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
209 }
210 else if (count == 0)
211 {
212 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
213 }
214 else
215 {
216 simultaneousDownloads_ = count;
217 }
218 }
219 }