2015-05-27 04:01:09 +02:00
|
|
|
Startup and Shutdown of Subsystems
|
|
|
|
|
==================================
|
|
|
|
|
:Date: Dec 2008
|
|
|
|
|
:Author: Ichthyo
|
|
|
|
|
|
|
|
|
|
//MENU: label Subsystem start
|
|
|
|
|
|
|
|
|
|
.copied from 'pipapo.org'
|
|
|
|
|
NOTE: This page was moved from _Cehteh_'s MoinMoin-wiki,
|
|
|
|
|
which at that time was the first home of Lumiera development +
|
|
|
|
|
The design and techniques outlined here are in use without major
|
|
|
|
|
changes as of 2015 (and can be expected to remain this way). The
|
|
|
|
|
documentation needs rewording in a more neutral and descriptive
|
|
|
|
|
way and probably an introductory paragraph might be helpful [yellow-background]#TODO#
|
|
|
|
|
|
|
|
|
|
...There is now sort-of an ``application realm'', which doesn't belong strictly to
|
|
|
|
|
any one of the Layers. It serves the purpose of pulling up and tearing down the
|
2010-11-15 02:21:13 +01:00
|
|
|
application in a controlled fashion. And additionally, it provides the Interface
|
|
|
|
|
and Config core services. Within the application, we find a small number of
|
|
|
|
|
_Subsystems_, which are more or less independent. These subsystems are
|
|
|
|
|
conceptual entities and don't correspond 1:1 to a layer, an interface, a class
|
|
|
|
|
or a plugin. These subsystems are _of no relevance_ outside the mentioned
|
|
|
|
|
"application realm". When the application is in normal operational mode, we have
|
|
|
|
|
the usual components, interfaces, services, aggregated into the three Layers.
|
|
|
|
|
|
|
|
|
|
__Currently I've identified the following subsystems:__
|
|
|
|
|
|
|
|
|
|
- Engine
|
|
|
|
|
- Builder
|
|
|
|
|
- Session
|
|
|
|
|
- Lumiera GUI
|
|
|
|
|
- Script runner
|
|
|
|
|
- Renderfarm node server
|
|
|
|
|
|
2015-05-27 04:01:09 +02:00
|
|
|
To deal with those subsystems, I've created an Interface to define the
|
2010-11-15 02:21:13 +01:00
|
|
|
operations and liabilities of a subsystem. Additionally, I assume that for each
|
2015-05-27 04:01:09 +02:00
|
|
|
subsystem there is a _Façade_, which the subsystem is free to implement as it
|
|
|
|
|
sees fit. Typically, this façade will load plugins, register and provide further
|
2010-11-15 02:21:13 +01:00
|
|
|
"business interfaces", and especially set up the _Layer separation interfaces_
|
|
|
|
|
which canalise any communication going on between the layers.
|
|
|
|
|
|
2015-05-27 04:01:09 +02:00
|
|
|
TIP: The code from my `startup` branch has meanwhile been merged to master. Look
|
2010-11-15 02:21:13 +01:00
|
|
|
http://git.lumiera.org/gitweb?p=LUMIERA;a=tree;h=a0a0e456a5b149df81b25a08358cd488631639fb;hb=a0a0e456a5b149df81b25a08358cd488631639fb[here]
|
2015-05-27 04:01:09 +02:00
|
|
|
for the code referred in the following discussion.
|
2010-11-15 02:21:13 +01:00
|
|
|
|
2015-05-27 04:01:09 +02:00
|
|
|
- +common/subsys.hpp+ contains the subsystem interface mentioned above.
|
2010-11-15 02:21:13 +01:00
|
|
|
- +lumiera/main.cpp+ uses the subsystem instances provided by the facades, and
|
|
|
|
|
additionally the services of +lumiera::AppState+ (+common/appstate.hpp+)
|
|
|
|
|
- AppState represents the state as relevant for the "application realm", i.e.
|
|
|
|
|
it performs global initialisation and shutdown. See especially +AppState::init()+
|
2015-05-27 04:01:09 +02:00
|
|
|
- see +backend/enginefacade.hpp|cpp+ as an (unimplemented) façade skeleton. +backend::EngineFacade::getDescriptor()+
|
|
|
|
|
yields the subsystem interface
|
2010-11-15 02:21:13 +01:00
|
|
|
- the GuiFacade is somewhat special, because we want to load the GUI from a
|
2015-05-27 04:01:09 +02:00
|
|
|
shared library. This façade is basically completed and working, but it currently
|
2010-11-15 02:21:13 +01:00
|
|
|
just loads a dummy plugin. The implementation of the GuiFacade needs to be in
|
|
|
|
|
core (because it pulls the plugin); that's why I've put it into
|
|
|
|
|
+common/guifacade.cpp+, while the interface is in +gui/guifacade.hpp+ as usual.
|
|
|
|
|
- as an example for a _Layer separation interface_, I've implemented the
|
|
|
|
|
GuiNotificationFacade, which will be used by the lower layers to push
|
2015-05-27 04:01:09 +02:00
|
|
|
informations into the GUI (and finally to request the GUI to shut down). Layer
|
2010-11-15 02:21:13 +01:00
|
|
|
separation interfaces are considered part of the public Lumiera API, thus the
|
|
|
|
|
headers go into +src/include/**+
|
|
|
|
|
* include/guinotification.h (C/C++ combined header) defines an C++ interface (abstract class) and a CLI interface.
|
|
|
|
|
* embedded into the interface is a factory, i.e. by gui::GuiNotification::facade() you get an instance...
|
|
|
|
|
* which actually is a proxy and routes any call through the instance of the
|
2015-05-27 04:01:09 +02:00
|
|
|
accompanying CLI interface which is defined within the interface/plugin system
|
2010-11-15 02:21:13 +01:00
|
|
|
* this in turn forwards to the implementation class in
|
|
|
|
|
gui/guinotificationfacade.cpp, which is assumed to live within the GUI
|
|
|
|
|
(shared lib)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Parallelism
|
|
|
|
|
-----------
|
|
|
|
|
Actually this system builds on the assumption, that starting each subsystem
|
|
|
|
|
doesn't block the overall start/main/stop thread. I.e. any subsystem is supposed
|
|
|
|
|
to spawn its control/event threads if necessary. Not every subsystem needs to
|
|
|
|
|
spawn threads though (for example, the session doesn't). In the current
|
2015-05-27 04:01:09 +02:00
|
|
|
implementation _no spawning of threads happens_. Likewise, I've commented out
|
|
|
|
|
the synchronisation primitives. +
|
|
|
|
|
[yellow-background]#TODO 2015# _meanwhile we do spawn threads and perform synchronisation_
|
2010-11-15 02:21:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Initialisation and Lifecycle
|
|
|
|
|
----------------------------
|
|
|
|
|
Basically, everything workes as discussed last spring in the
|
|
|
|
|
link:{ldoc}/devel/rfc/GlobalInitialization.html[GlobalInitialisation]
|
|
|
|
|
design entry. I've considered to switch to simple functions +pre_init(), init(),
|
|
|
|
|
...+ as proposed by Cehteh, but I'm not happy with this idea, because it creates
|
|
|
|
|
a coupling between anything which needs to be done in a certain initialisation
|
|
|
|
|
function. Actually, I prefer the usual approach of lifecycle events (or signals)
|
|
|
|
|
used in many application frameworks, i.e. the publisher-subscriber model. This
|
|
|
|
|
allows to keep the registration immediately within the implementation of a
|
2015-05-27 04:01:09 +02:00
|
|
|
facility, and it allows to add an arbitrary number of additional lifecycle
|
2010-11-15 02:21:13 +01:00
|
|
|
events, like *ON_SESSION_CLOSE*, *ON_BUILD*, *ON_EMERGENCY_EXIT*.
|
|
|
|
|
|
2015-05-27 04:01:09 +02:00
|
|
|
Basically we have now the following steps and events happening
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2010-11-15 02:21:13 +01:00
|
|
|
|
|
|
|
|
* *ON_BASIC_INIT* runs "somewhere" in the static initialisation phase before
|
|
|
|
|
main(). To schedule something there, you need to place a statc C++ variable.
|
2015-05-27 04:01:09 +02:00
|
|
|
This should be reserved for very basic initialisation tasks which need to be
|
|
|
|
|
done even prior to any global initialisation, e.g. the NOBUG_INIT is done this
|
2010-11-15 02:21:13 +01:00
|
|
|
way, the config system, maybe setting up a dispatcher table based on (compile
|
|
|
|
|
time) type information (for the rules engine).
|
2015-05-27 04:01:09 +02:00
|
|
|
* +AppState::init()+ cares for bringing up the plugin loader and opens the config-interface.
|
|
|
|
|
* ...followed by triggering *ON_GLOBAL_INIT*
|
2010-11-15 02:21:13 +01:00
|
|
|
* +main()+ pulls up the subsystems according to the command line options.
|
2015-05-27 04:01:09 +02:00
|
|
|
* within each subsystem, façade interfaces shall be opened with the interface
|
|
|
|
|
system. Any initialisation of components should be tied to these.
|
2010-11-15 02:21:13 +01:00
|
|
|
* as a rule and if possible, _any service should be written such as to come up on demand._
|
|
|
|
|
* shutdown or failure of _any given subsystem_ initiates the shutdown sequence
|
|
|
|
|
by requesting all other running subsystems to terminate
|
|
|
|
|
* there is an *ON_GLOBAL_SHUTDOWN* event, which can be used for normal cleanup.
|
|
|
|
|
In case of an emergency exit, this hook may be skipped
|
|
|
|
|
* alternatively, the *ON_EMERGENCY_EXIT* event is triggered. In case of nested
|
|
|
|
|
exceptions, this may happen twice.
|
|
|
|
|
* the AppState destructor tries to bring down the core systems (config-interface and pluginloader).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Demo Run
|
|
|
|
|
--------
|
|
|
|
|
* building with scons (default target) now yields a bin/guistart.so, besides the bin/lumiera exe the scons built created since day one.
|
|
|
|
|
* we need to set the LUMIERA_PLUGIN_PATH from the commandline to point to this bin directory, e.g.
|
|
|
|
|
* +++LUMIERA_PLUGIN_PATH=/home/hiv/devel/lumi/.libs NOBUG_LOG='test:TRACE,lumiera:TRACE,config:TRACE' bin/lumiera 2>&1 | egrep -v '(TODO)|(FIXME)'+++
|
|
|
|
|
------
|
|
|
|
|
00000392: configfacade.cpp:74: INFO: thread_1: Config: Config system ready.
|
|
|
|
|
00000394: main.cpp:55: NOTICE: thread_1: main: *** Lumiera NLE for Linux ***
|
|
|
|
|
00000395: appstate.cpp:114: TRACE: thread_1: init: initialising application core...
|
|
|
|
|
00000405: interface.c:54: TRACE: thread_1: lumiera_interface_open: lumieraorg_interface
|
|
|
|
|
00000406: interface.c:55: WARNING: thread_1: lumiera_interface_open: opening experimental interface: lumieraorg_interface_0_lumieraorg_interface
|
|
|
|
|
00000412: interface.c:168: TRACE: thread_1: lumiera_interface_open_interfacenode: lumieraorg_interface 0 ()
|
|
|
|
|
00000437: config.c:199: NOTICE: thread_1: lumiera_config_get: envvar override for config LUMIERA_PLUGIN_PATH = /home/hiv/devel/lumi/
|
|
|
|
|
00000444: config.c:199: NOTICE: thread_1: lumiera_config_get: envvar override for config LUMIERA_PLUGIN_PATH = /home/hiv/devel/lumi/
|
|
|
|
|
00000467: appstate.cpp:132: TRACE: thread_1: init: Lumiera core started successfully.
|
|
|
|
|
00000469: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Builder...?
|
|
|
|
|
00000472: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Renderfarm node...?
|
|
|
|
|
00000475: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Lumiera GTK GUI...?
|
|
|
|
|
00000476: subsystemrunner.hpp:144: INFO: thread_1: triggerStartup: Starting subsystem "Lumiera GTK GUI"
|
|
|
|
|
00000477: interface.c:54: TRACE: thread_1: lumiera_interface_open: lumieraorg_GuiStarterPlugin
|
|
|
|
|
00000483: interface.c:168: TRACE: thread_1: lumiera_interface_open_interfacenode: lumieraorg_GuiStarterPlugin 0 ()
|
|
|
|
|
*** Ha Ha Ha
|
|
|
|
|
this is the GuiStarterPlugin speaking!
|
|
|
|
|
now, the Lumiera GUI should be spawned....
|
|
|
|
|
but actually nothing happens!!!!!!!!!!!!!!
|
|
|
|
|
00000491: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Script runner...?
|
|
|
|
|
00000494: appstate.cpp:171: NOTICE: thread_1: maybeWait: Shutting down Lumiera...
|
|
|
|
|
00000495: interface.c:230: TRACE: thread_1: lumiera_interface_close:
|
|
|
|
|
00000498: interface.c:258: TRACE: thread_1: lumiera_interfacenode_close: lumieraorg_GuiStarterPlugin 1 ()
|
|
|
|
|
00000634: configfacade.cpp:83: TRACE: thread_1: ~Config: config system closed.
|
|
|
|
|
00000635: appstate.cpp:245: TRACE: thread_1: ~AppState: shutting down basic application layer...
|
|
|
|
|
00000643: interface.c:230: TRACE: thread_1: lumiera_interface_close:
|
|
|
|
|
00000646: interface.c:258: TRACE: thread_1: lumiera_interfacenode_close: lumieraorg_interface 1 ()
|
|
|
|
|
------
|
2015-05-27 04:01:09 +02:00
|
|
|
* incidentally, running... `lumiera --help` produces the following output
|
2010-11-15 02:21:13 +01:00
|
|
|
------
|
|
|
|
|
00000392: configfacade.cpp:74: INFO: thread_1: Config: Config system ready.
|
|
|
|
|
00000394: main.cpp:55: NOTICE: thread_1: main: *** Lumiera NLE for Linux ***
|
|
|
|
|
Lumiera, the non linear video editor. Supported parameters:
|
|
|
|
|
-h [ --help ] produce help message
|
|
|
|
|
-f [ --session ] arg session file to load (UNIMPLEMENTED)
|
|
|
|
|
-s [ --script ] arg execute the given LUA script (UNIMPLEMENTED)
|
|
|
|
|
--headless start without GUI
|
|
|
|
|
-p [ --port ] arg open renderfarm node at given port (UNIMPLEMENTED)
|
|
|
|
|
-d [ --define ] arg enter definition into config system (UNIMPLEMENTED)
|
|
|
|
|
------
|
|
|
|
|
|