comparison Framework/Loaders/LoaderStateMachine.cpp @ 973:38409549db43 toa2019082903

Log with addresses + added fingerprint mechanism to avoid calling zombie objects where: - a message is sent with a receiver - the receiver dies - another receiver with the SAME address is created - the message reply is executed --> execution on the wrong object! (since their "identity" is their address. The fix is to identify them with an UUID stored at creation time)
author Benjamin Golinvaux <bgo@osimis.io>
date Thu, 29 Aug 2019 18:07:55 +0200
parents 91f827272c1f
children e75fd08d6c75
comparison
equal deleted inserted replaced
972:fdf8b013f228 973:38409549db43
21 21
22 #include "LoaderStateMachine.h" 22 #include "LoaderStateMachine.h"
23 23
24 #include <Core/OrthancException.h> 24 #include <Core/OrthancException.h>
25 25
26 #if 0
27 extern bool logbgo233;
28 extern bool logbgo115;
29 #endif
30
31 namespace OrthancStone 26 namespace OrthancStone
32 { 27 {
33 void LoaderStateMachine::State::Handle(const OrthancRestApiCommand::SuccessMessage& message) 28 void LoaderStateMachine::State::Handle(const OrthancRestApiCommand::SuccessMessage& message)
34 { 29 {
35 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 30 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
48 } 43 }
49 44
50 45
51 void LoaderStateMachine::Schedule(OracleCommandWithPayload* command) 46 void LoaderStateMachine::Schedule(OracleCommandWithPayload* command)
52 { 47 {
53 #if 0 48 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Schedule()";
54 if (logbgo233) {
55 if (logbgo115)
56 LOG(TRACE) << " LoaderStateMachine::Schedule()";
57 }
58 #endif
59 49
60 std::auto_ptr<OracleCommandWithPayload> protection(command); 50 std::auto_ptr<OracleCommandWithPayload> protection(command);
61 51
62 if (command == NULL) 52 if (command == NULL)
63 { 53 {
67 if (!command->HasPayload()) 57 if (!command->HasPayload())
68 { 58 {
69 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, 59 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
70 "The payload must contain the next state"); 60 "The payload must contain the next state");
71 } 61 }
72
73 #if 0
74 if (logbgo233) {
75 if (logbgo115)
76 LOG(TRACE) << " * LoaderStateMachine::Schedule(): adding command with addr: " << std::hex << protection.get() << std::dec << " pendingCommands_.size() is now : " << pendingCommands_.size()+1;
77 }
78 #endif
79 pendingCommands_.push_back(protection.release()); 62 pendingCommands_.push_back(protection.release());
80 63
81 Step(); 64 Step();
82 } 65 }
83 66
84 67
85 void LoaderStateMachine::Start() 68 void LoaderStateMachine::Start()
86 { 69 {
70 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Start()";
71
87 if (active_) 72 if (active_)
88 { 73 {
89 LOG(TRACE) << "LoaderStateMachine::Start() called while active_ is true"; 74 LOG(TRACE) << "LoaderStateMachine::Start() called while active_ is true";
90 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 75 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
91 } 76 }
99 } 84 }
100 85
101 86
102 void LoaderStateMachine::Step() 87 void LoaderStateMachine::Step()
103 { 88 {
104 #if 0
105 if (logbgo115)
106 LOG(TRACE) << " LoaderStateMachine::Step(): pendingCommands_.size() = " << pendingCommands_.size();
107 #endif
108 if (!pendingCommands_.empty() && 89 if (!pendingCommands_.empty() &&
109 activeCommands_ < simultaneousDownloads_) 90 activeCommands_ < simultaneousDownloads_)
110 { 91 {
111 92
112 IOracleCommand* nextCommand = pendingCommands_.front(); 93 IOracleCommand* nextCommand = pendingCommands_.front();
113 94
114 #if 0 95 LOG(TRACE) << " LoaderStateMachine(" << std::hex << this << std::dec <<
115 if (logbgo233) { 96 ")::Step(): activeCommands_ (" << activeCommands_ <<
116 if (logbgo115) 97 ") < simultaneousDownloads_ (" << simultaneousDownloads_ <<
117 LOG(TRACE) << " * LoaderStateMachine::Step(): activeCommands_ (" << activeCommands_ << ") < simultaneousDownloads_ (" << simultaneousDownloads_ << ") --> will Schedule command addr " << std::hex << nextCommand << std::dec; 98 ") --> will Schedule command addr " << std::hex << nextCommand << std::dec;
118 }
119 #endif
120 99
121 oracle_.Schedule(*this, nextCommand); 100 oracle_.Schedule(*this, nextCommand);
122 pendingCommands_.pop_front(); 101 pendingCommands_.pop_front();
123 102
124 activeCommands_++; 103 activeCommands_++;
125 } 104 }
126 else 105 else
127 { 106 {
128 #if 0 107 LOG(TRACE) << " LoaderStateMachine(" << std::hex << this << std::dec <<
129 if (logbgo233) { 108 ")::Step(): activeCommands_ (" << activeCommands_ <<
130 if (logbgo115) 109 ") < simultaneousDownloads_ (" << simultaneousDownloads_ <<
131 LOG(TRACE) << " * pendingCommands_.size() == " << pendingCommands_.size() << " LoaderStateMachine::Step(): activeCommands_ (" << activeCommands_ << ") >= simultaneousDownloads_ (" << simultaneousDownloads_ << ") --> will NOT Schedule anything"; 110 ") --> will NOT Schedule command";
132 }
133 #endif
134 } 111 }
135 } 112 }
136 113
137 114
138 void LoaderStateMachine::Clear() 115 void LoaderStateMachine::Clear()
139 { 116 {
117 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::Clear()";
140 for (PendingCommands::iterator it = pendingCommands_.begin(); 118 for (PendingCommands::iterator it = pendingCommands_.begin();
141 it != pendingCommands_.end(); ++it) 119 it != pendingCommands_.end(); ++it)
142 { 120 {
143 delete *it; 121 delete *it;
144 } 122 }
156 } 134 }
157 135
158 template <typename T> 136 template <typename T>
159 void LoaderStateMachine::HandleSuccessMessage(const T& message) 137 void LoaderStateMachine::HandleSuccessMessage(const T& message)
160 { 138 {
161 assert(activeCommands_ > 0); 139 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::HandleSuccessMessage()";
140 if (activeCommands_ <= 0) {
141 LOG(ERROR) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::HandleSuccessMessage : activeCommands_ should be > 0 but is: " << activeCommands_;
142 }
162 activeCommands_--; 143 activeCommands_--;
163 144
164 try 145 try
165 { 146 {
166 dynamic_cast<State&>(message.GetOrigin().GetPayload()).Handle(message); 147 dynamic_cast<State&>(message.GetOrigin().GetPayload()).Handle(message);
181 oracle_(oracle), 162 oracle_(oracle),
182 active_(false), 163 active_(false),
183 simultaneousDownloads_(4), 164 simultaneousDownloads_(4),
184 activeCommands_(0) 165 activeCommands_(0)
185 { 166 {
167 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::LoaderStateMachine()";
168
186 oracleObservable.RegisterObserverCallback( 169 oracleObservable.RegisterObserverCallback(
187 new Callable<LoaderStateMachine, OrthancRestApiCommand::SuccessMessage> 170 new Callable<LoaderStateMachine, OrthancRestApiCommand::SuccessMessage>
188 (*this, &LoaderStateMachine::HandleSuccessMessage)); 171 (*this, &LoaderStateMachine::HandleSuccessMessage));
189 172
190 oracleObservable.RegisterObserverCallback( 173 oracleObservable.RegisterObserverCallback(
198 oracleObservable.RegisterObserverCallback( 181 oracleObservable.RegisterObserverCallback(
199 new Callable<LoaderStateMachine, OracleCommandExceptionMessage> 182 new Callable<LoaderStateMachine, OracleCommandExceptionMessage>
200 (*this, &LoaderStateMachine::HandleExceptionMessage)); 183 (*this, &LoaderStateMachine::HandleExceptionMessage));
201 } 184 }
202 185
186 LoaderStateMachine::~LoaderStateMachine()
187 {
188 LOG(TRACE) << "LoaderStateMachine(" << std::hex << this << std::dec << ")::~LoaderStateMachine()";
189 Clear();
190 }
203 191
204 void LoaderStateMachine::SetSimultaneousDownloads(unsigned int count) 192 void LoaderStateMachine::SetSimultaneousDownloads(unsigned int count)
205 { 193 {
206 if (active_) 194 if (active_)
207 { 195 {