Reconfiguration
As discussed in the application kick-starting section, the Loader component (or any component inheriting from it) is responsible for configuring and starting a standard MARTe applicaton (i.e. one that relies on the MARTeApp.cpp).
The Loader component also offers a reconfiguration interface (see Loader::Reconfigure
) that can be used in runtime to modify the configuration of an application that is already in execution.
Any component inheriting from the Loader
class can implement the PostInit
method in order to receive runtime configuration parameters (e.g. a TCP port where to listen for new configurations).
The Loader
also offers a set of pre-defined message triggers that are sent: before the configuration is modified; after the configuration is (successfully) applied; in case a configuration error occurs; and if a configuration occurs and the user has configured the option to reload the last valid configuration.
Finally, the Loader
components also allows to query the currently loaded configuration (see Loader::GetLastValidConfiguration
).
The ConfigurationLoaderTCP in an implementation that allows changing the runtime configuration over a TCP connection.
Examples
Valid reconfiguration
This is an example of a MARTeApp
that uses a ConfigurationLoaderTCP
.
Start the application with the -m parameter.
To modify a configuration, start the application and, on another console, type nc localhost 24680 < RTApp-9-reload.cfg
.
The new configuration has a higher cycle time so that the frequency at which the signals are printed into console should significantly increase.
To return to a configuration running at a lower frequency, on another console, type nc localhost 24680 < RTApp-9-reload-2.cfg
.
1+LoaderPostInit = {
2 Class = ReferenceContainer
3 +Parameters = {
4 Class = ConfigurationDatabase
5 Port = 24680//The port where to listen for the TCP messages.
6 ReloadLast = true //Reload old configuration in case of (re)configuration failure? Default = true. If true the FailedConfiguration message will not to be sent.
7 }
8 +Messages = {
9 Class = ReferenceContainer
10 +PreConfiguration = { //Optional message to send before the configuration is applied.
11 Class = Message
12 Destination = StateMachine
13 Function = STOP
14 Mode = ExpectsReply
15 }
16 +PostConfiguration = { //Optional message to send if the configuration was successfully applied.
17 Class = Message
18 Destination = StateMachine
19 Function = START
20 Mode = ExpectsReply
21 }
22 }
23}
24+StateMachine = {
25 Class = StateMachine
26 +INITIAL = {
27 Class = ReferenceContainer
28 +START = {
29 Class = StateMachineEvent
30 NextState = "STATE1"
31 NextStateError = "ERROR"
32 Timeout = 0
33 +ChangeToState1Msg = {
34 Class = Message
35 Destination = TestApp
36 Mode = ExpectsReply
37 Function = PrepareNextState
38 +Parameters = {
39 Class = ConfigurationDatabase
40 param1 = State1
41 }
42 }
43 +StartNextStateExecutionMsg = {
44 Class = Message
45 Destination = TestApp
46 Function = StartNextStateExecution
47 Mode = ExpectsReply
48 }
49 }
50 }
51 +STATE1 = {
52 Class = ReferenceContainer
53 +GOTOSTATE2 = {
54 Class = StateMachineEvent
55 NextState = "STATE2"
56 NextStateError = "ERROR"
57 Timeout = 0
58 +PrepareChangeToState2Msg = {
59 Class = Message
60 Destination = TestApp
61 Mode = ExpectsReply
62 Function = PrepareNextState
63 +Parameters = {
64 Class = ConfigurationDatabase
65 param1 = State2
66 }
67 }
68 +StopCurrentStateExecutionMsg = {
69 Class = Message
70 Destination = TestApp
71 Function = StopCurrentStateExecution
72 Mode = ExpectsReply
73 }
74 +StartNextStateExecutionMsg = {
75 Class = Message
76 Destination = TestApp
77 Function = StartNextStateExecution
78 Mode = ExpectsReply
79 }
80 }
81 +STOP = {
82 Class = StateMachineEvent
83 NextState = "STOPPED"
84 NextStateError = "ERROR"
85 Timeout = 0
86 +StopCurrentStateExecutionMsg = {
87 Class = Message
88 Destination = TestApp
89 Function = StopCurrentStateExecution
90 Mode = ExpectsReply
91 }
92 }
93 +ERROR = {
94 Class = StateMachineEvent
95 NextState = "ERROR"
96 NextStateError = "ERROR"
97 }
98 }
99 +STATE2 = {
100 Class = ReferenceContainer
101 +GOTOSTATE1 = {
102 Class = StateMachineEvent
103 NextState = "STATE1"
104 NextStateError = "ERROR"
105 Timeout = 0
106 +PrepareChangeToState1Msg = {
107 Class = Message
108 Destination = TestApp
109 Mode = ExpectsReply
110 Function = PrepareNextState
111 +Parameters = {
112 Class = ConfigurationDatabase
113 param1 = State1
114 }
115 }
116 +StopCurrentStateExecutionMsg = {
117 Class = Message
118 Destination = TestApp
119 Function = StopCurrentStateExecution
120 Mode = ExpectsReply
121 }
122 +StartNextStateExecutionMsg = {
123 Class = Message
124 Destination = TestApp
125 Function = StartNextStateExecution
126 Mode = ExpectsReply
127 }
128 }
129 +STOP = {
130 Class = StateMachineEvent
131 NextState = "STOPPED"
132 NextStateError = "ERROR"
133 Timeout = 0
134 +StopCurrentStateExecutionMsg = {
135 Class = Message
136 Destination = TestApp
137 Function = StopCurrentStateExecution
138 Mode = ExpectsReply
139 }
140 }
141 +ERROR = {
142 Class = StateMachineEvent
143 NextState = "ERROR"
144 NextStateError = "ERROR"
145 }
146 }
147 +STOPPED = {
148 Class = ReferenceContainer
149 +START = {
150 Class = StateMachineEvent
151 NextState = "STATE1"
152 NextStateError = "ERROR"
153 Timeout = 0
154 +ChangeToState1Msg = {
155 Class = Message
156 Destination = TestApp
157 Mode = ExpectsReply
158 Function = PrepareNextState
159 +Parameters = {
160 Class = ConfigurationDatabase
161 param1 = State1
162 }
163 }
164 +StartNextStateExecutionMsg = {
165 Class = Message
166 Destination = TestApp
167 Function = StartNextStateExecution
168 Mode = ExpectsReply
169 }
170
171 }
172 }
173 +ERROR = {
174 Class = ReferenceContainer
175 +ENTER = {
176 Class = ReferenceContainer
177 +StopCurrentStateExecutionMsg = {
178 Class = Message
179 Destination = TestApp
180 Function = StopCurrentStateExecution
181 Mode = ExpectsReply
182 }
183 +PrepareChangeToErrorMsg = {
184 Class = Message
185 Destination = TestApp
186 Mode = ExpectsReply
187 Function = PrepareNextState
188 +Parameters = {
189 Class = ConfigurationDatabase
190 param1 = StateError
191 }
192 }
193 +StartNextStateExecutionMsg = {
194 Class = Message
195 Destination = TestApp
196 Function = StartNextStateExecution
197 Mode = ExpectsReply
198 }
199 }
200 +RESET = {
201 Class = StateMachineEvent
202 NextState = "STATE1"
203 NextStateError = "STATE1"
204 Timeout = 0
205 +StopCurrentStateExecutionMsg = {
206 Class = Message
207 Destination = TestApp
208 Function = StopCurrentStateExecution
209 Mode = ExpectsReply
210 }
211 +PrepareChangeToState1Msg = {
212 Class = Message
213 Destination = TestApp
214 Mode = ExpectsReply
215 Function = PrepareNextState
216 +Parameters = {
217 Class = ConfigurationDatabase
218 param1 = State1
219 }
220 }
221 +StartNextStateExecutionMsg = {
222 Class = Message
223 Destination = TestApp
224 Function = StartNextStateExecution
225 Mode = ExpectsReply
226 }
227 }
228 }
229}
230$TestApp = {
231 Class = RealTimeApplication
232 +Functions = {
233 Class = ReferenceContainer
234 +GAMTimer = {
235 Class = IOGAM
236 InputSignals = {
237 Counter = {
238 DataSource = Timer
239 Type = uint32
240 }
241 Time = {
242 Frequency = 1
243 DataSource = Timer
244 Type = uint32
245 }
246 }
247 OutputSignals = {
248 Counter = {
249 DataSource = DDB1
250 Type = uint32
251 }
252 Time = {
253 DataSource = DDB1
254 Type = uint32
255 }
256 }
257 }
258 +GAMVariable1 = {
259 Class = VariableGAMExample1
260 Gains = {2, 3, 4}
261 InputSignals = {
262 Counter = {
263 DataSource = DDB1
264 Type = uint32
265 }
266 }
267 OutputSignals = {
268 GainCounter1Thread1 = {
269 DataSource = DDB1
270 Type = uint32
271 }
272 GainCounter2Thread1 = {
273 DataSource = DDB1
274 Type = uint32
275 }
276 GainCounter3Thread1 = {
277 DataSource = DDB1
278 Type = uint32
279 }
280 }
281 }
282 +GAMT1TSynchOut = {
283 Class = IOGAM
284 InputSignals = {
285 GainCounter1Thread1 = {
286 DataSource = DDB1
287 Type = uint32
288 }
289 GainCounter2Thread1 = {
290 DataSource = DDB1
291 Type = uint32
292 }
293 GainCounter3Thread1 = {
294 DataSource = DDB1
295 Type = uint32
296 }
297 }
298 OutputSignals = {
299 GainCounter1Thread1 = {
300 DataSource = RTThreadSynch
301 Type = uint32
302 }
303 GainCounter2Thread1 = {
304 DataSource = RTThreadSynch
305 Type = uint32
306 }
307 GainCounter3Thread1 = {
308 DataSource = RTThreadSynch
309 Type = uint32
310 }
311 }
312 }
313 +GAMT1T2Interface = {
314 Class = IOGAM
315 InputSignals = {
316 GainCounter1Thread1 = {
317 DataSource = RTThreadSynch
318 Type = uint32
319 Samples = 2 //Run at half the frequency of thread 1
320 }
321 GainCounter2Thread1 = {
322 DataSource = RTThreadSynch
323 Type = uint32
324 Samples = 2 //Run at half the frequency of thread 1
325 }
326 GainCounter3Thread1 = {
327 DataSource = RTThreadSynch
328 Type = uint32
329 Samples = 2 //Run at half the frequency of thread 1
330 }
331 }
332 OutputSignals = {
333 GainCounter1Thread2 = {
334 DataSource = DDB1
335 Type = uint32
336 Samples = 1
337 NumberOfDimensions = 1
338 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
339 }
340 GainCounter2Thread2 = {
341 DataSource = DDB1
342 Type = uint32
343 Samples = 1
344 NumberOfDimensions = 1
345 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
346 }
347 GainCounter3Thread2 = {
348 DataSource = DDB1
349 Type = uint32
350 Samples = 1
351 NumberOfDimensions = 1
352 NumberOfElements = 2 //2 elements for each cycle (as it waits for 2 samples)
353 }
354 }
355 }
356 +GAMT1T3Interface = {
357 Class = IOGAM
358 InputSignals = {
359 GainCounter1Thread1 = {
360 DataSource = RTThreadSynch
361 Type = uint32
362 Samples = 4 //Run at one quarter of the frequency of thread 1
363 }
364 GainCounter2Thread1 = {
365 DataSource = RTThreadSynch
366 Type = uint32
367 Samples = 4 //Run at one quarter the frequency of thread 1
368 }
369 GainCounter3Thread1 = {
370 DataSource = RTThreadSynch
371 Type = uint32
372 Samples = 4 //Run at one quarter the frequency of thread 1
373 }
374 }
375 OutputSignals = {
376 GainCounter1Thread3 = {
377 DataSource = DDB1
378 Type = uint32
379 Samples = 1
380 NumberOfDimensions = 1
381 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
382 }
383 GainCounter2Thread3 = {
384 DataSource = DDB1
385 Type = uint32
386 Samples = 1
387 NumberOfDimensions = 1
388 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
389 }
390 GainCounter3Thread3 = {
391 DataSource = DDB1
392 Type = uint32
393 Samples = 1
394 NumberOfDimensions = 1
395 NumberOfElements = 4 //4 elements for each cycle (as it waits for 4 samples)
396 }
397 }
398 }
399 +GAMDisplayThread1 = {
400 Class = IOGAM
401 InputSignals = {
402 Counter = {
403 DataSource = DDB1
404 Type = uint32
405 }
406 GainCounter1Thread1 = {
407 DataSource = DDB1
408 Type = uint32
409 }
410 GainCounter2Thread1 = {
411 DataSource = DDB1
412 Type = uint32
413 }
414 GainCounter3Thread1 = {
415 DataSource = DDB1
416 Type = uint32
417 }
418 }
419 OutputSignals = {
420 Counter = {
421 DataSource = LoggerDataSource
422 Type = uint32
423 }
424 GainCounter1Thread1 = {
425 DataSource = LoggerDataSource
426 Type = uint32
427 }
428 GainCounter2Thread1 = {
429 DataSource = LoggerDataSource
430 Type = uint32
431 }
432 GainCounter3Thread1 = {
433 DataSource = LoggerDataSource
434 Type = uint32
435 }
436 }
437 }
438 +GAMDisplayThread2 = {
439 Class = IOGAM
440 InputSignals = {
441 GainCounter1Thread2 = {
442 DataSource = DDB1
443 Type = uint32
444 }
445 GainCounter2Thread2 = {
446 DataSource = DDB1
447 Type = uint32
448 }
449 GainCounter3Thread2 = {
450 DataSource = DDB1
451 Type = uint32
452 }
453 }
454 OutputSignals = {
455 GainCounter1Thread2 = {
456 DataSource = LoggerDataSource
457 Type = uint32
458 NumberOfDimensions = 1
459 NumberOfElements = 2
460 }
461 GainCounter2Thread2 = {
462 DataSource = LoggerDataSource
463 Type = uint32
464 NumberOfDimensions = 1
465 NumberOfElements = 2
466 }
467 GainCounter3Thread2 = {
468 DataSource = LoggerDataSource
469 Type = uint32
470 NumberOfDimensions = 1
471 NumberOfElements = 2
472 }
473 }
474 }
475 +GAMDisplayThread3 = {
476 Class = IOGAM
477 InputSignals = {
478 GainCounter1Thread3 = {
479 DataSource = DDB1
480 Type = uint32
481 }
482 GainCounter2Thread3 = {
483 DataSource = DDB1
484 Type = uint32
485 }
486 GainCounter3Thread3 = {
487 DataSource = DDB1
488 Type = uint32
489 }
490 }
491 OutputSignals = {
492 GainCounter1Thread3 = {
493 DataSource = LoggerDataSource
494 Type = uint32
495 NumberOfDimensions = 1
496 NumberOfElements = 4
497 }
498 GainCounter2Thread3 = {
499 DataSource = LoggerDataSource
500 Type = uint32
501 NumberOfDimensions = 1
502 NumberOfElements = 4
503 }
504 GainCounter3Thread3 = {
505 DataSource = LoggerDataSource
506 Type = uint32
507 NumberOfDimensions = 1
508 NumberOfElements = 4
509 }
510 }
511 }
512 }
513 +Data = {
514 Class = ReferenceContainer
515 DefaultDataSource = DDB1
516 +DDB1 = {
517 Class = GAMDataSource
518 }
519 +LoggerDataSource = {
520 Class = LoggerDataSource
521 }
522 +Timings = {
523 Class = TimingDataSource
524 }
525 +RTThreadSynch = {
526 Class = RealTimeThreadSynchronisation
527 Timeout = 5000 //Timeout in ms to wait for the thread to cycle.
528 }
529 +Timer = {
530 Class = LinuxTimer
531 SleepNature = "Default"
532 Signals = {
533 Counter = {
534 Type = uint32
535 }
536 Time = {
537 Type = uint32
538 }
539 }
540 }
541 }
542 +States = {
543 Class = ReferenceContainer
544 +State1 = {
545 Class = RealTimeState
546 +Threads = {
547 Class = ReferenceContainer
548 +Thread1 = {
549 Class = RealTimeThread
550 CPUs = 0x1
551 Functions = {GAMTimer GAMVariable1 GAMT1TSynchOut GAMDisplayThread1}
552 }
553 }
554 }
555 +State2 = {
556 Class = RealTimeState
557 +Threads = {
558 Class = ReferenceContainer
559 +Thread1 = {
560 Class = RealTimeThread
561 CPUs = 0x1
562 Functions = {GAMTimer GAMVariable1 GAMT1TSynchOut GAMDisplayThread1}
563 }
564 +Thread2 = {
565 Class = RealTimeThread
566 CPUs = 0x2
567 Functions = {GAMT1T2Interface GAMDisplayThread2}
568 }
569 +Thread3 = {
570 Class = RealTimeThread
571 CPUs = 0x4
572 Functions = {GAMT1T3Interface GAMDisplayThread3}
573 }
574 }
575 }
576 +StateError = {
577 Class = RealTimeState
578 +Threads = {
579 Class = ReferenceContainer
580 +Thread1 = {
581 Class = RealTimeThread
582 CPUs = 0x1
583 Functions = {GAMTimer}
584 }
585 }
586 }
587 }
588 +Scheduler = {
589 Class = GAMScheduler
590 TimingDataSource = Timings
591 }
592}
Invalid reconfiguration
Given that the application was launched with the parameter ReloadLast=true, a failed reconfiguration attempt will trigger the reloading of the last valid configuration.
To load an invalid configuration, start the application and, on another console, type nc localhost 24680 < RTApp-9-reload-fail.cfg
. Notice that the application will continue to run at the original frequency.