SimuLizar is a Palladio plug-in for analyzing self-adaptive systems, such as cloud computing systems, at design-time. With SimuLizar, we want to provide modeling support for self-adaptation rules as well as new analysis for scalability, elasticity, and efficiency.
A documentation of the contained testing framework for SimuLizar-based simulations can be found here
SimuLizar provides an elaborate Extension API, which relies on Dagger dependency injection. SimuLizar imposes a strict scoping of dependencies in order to provide simplified lifetime management and therefore, reusability. More details on Scoping in Dagger can be found here in the section on Singletons and Scoped Bindings.
We used the concept of Dagger Components to modularize the parts of SimuLizar. The current component hierarchy and the respective dependencies are visualized in the following diagram. In principle, we differentiate between four hierarchical levels:
- SimuLizarPlatformComponent (Services with one instance for the entire application, e.g. Eclipse Extension Point Management)
- SimuLizarRootComponent (Services with one instance per simulation run, e.g. preparation of blackboard)
- SimuLizarRuntimeComponent (Central interpretation runtime entities)
- SimulatedThreadComponent (DI-scope per simulated user. Created anew for every new user.)
SimuLizar currently provides support for several different types of extension. In general, if you develop your extension please follow the following guidelines:
- Select an extension interface fitting for your needs (if none are available, consult with the SimuLizar developers how to best achieve what you are doing)
- Specify all dependencies of your extension as parameters to its constructor. Please refrain from doing any other work in the constructor. Particularly, do NOT try to resolve any models or rely on the runtime state at that particular point in time.
- Every extension interface specifies an
initialize()
method, which is called by the framework, once all preceding simulation entities are initialized. Do your lookups and initialization work here. - If you introduced new runtime state, make sure to clean in up in the respective
cleanup()
method.
In order to make your extensions known to SimuLizar, please implement a Dagger Component interface, which provides the appropriate implementation of your extension. In order to access simulation entities and entities of other extensions, specify explicit Component Dependencies (e.g. @Component(dependencies = { QUALComponent.class })
to the required components. Have your Component extend the ExtensionComponent
interface. In line with Dagger, please add a nested static factory interface with one abstract method which takes an instance of each component dependency and returns your component type. The component, as well as the factory will be generated by Dagger. Have the factory extend ExtensionComponent.Factory
.
Please specify an implementation for the method ExtensionComponent.contributes()
. Have it return a Set<ExtensionContribution>
. For every extension contributed by your component, create one ExtensionContribution instance, specifying the extension interface, e.g. IModelObserver
and the function to retrieve it, given an instance of your component. SimuLizar takes care about instantiating your component and uses the specified function to retrieve the concrete implementations of your extensions.
An example of how to build an ExtensionComponent can be found here.
In order to register your extension with SimuLizar, there are two options:
- Define a custom launcher, and provide your ExtensionComponent.Factory to the
SimuLizarRootComponent.Factory.create(new ExtensionComponentsModule(...))
. We suggest this option whenever you want to reuse and extend SimuLizar functionality in your own analysis. - Use the eclipse extension point to contribute the factory. The Factory needs to be instantiable without parameters. We suggest this option when you want to transparently contribute additional support to the SimuLizar analysis. In this case, please ensure compatibility with existing SimuLizar models.
There are currently a few limitation to take into account with ExtensionComponents:
- ExtensionComponents cannot have circular dependencies (and really should not).
- ExtensionComponent factories can only have dependent components for parameters. Using
@BindsInstance
or module instances is currently not possible.
As of now, the set of available components consists of the following:
- SimuLizarRootComponent
- SimEngineComponent
- QUALComponent
- SimuComFrameworkComponent
- SimuLizarRuntimeComponent
- any contributed extension component
Please note, that the extension mechanism currently targets RootComponent and RuntimeComponent level. The point in time, when your extensions are available dependends on the component dependencies of your ExtensionComponent. There is currently no support for extending the SimulatedThread level, although that might change in the future.
SimuLizar currently provides the following extension points:
Interface | Purpose |
---|---|
ModelLoader | Allows to add further models to be loaded into the model partition |
ModelCompletion | Allows to modify the loaded models before running the interpreters. Called after all resources have been loaded |
IConfigurer | Allows to adapt selected run configuration parameters based on the current models in the blackboard. Called after all models have been resolved and all model completions have been executed. |
RuntimeStateEntityManager | Initialize new entities which constitute runtime state (e.g. user management, usage evolver management). Please do not evaluate the PCMPartition here. Add an IModelObserver to listen to changes in the model and update the runtime state accordingly. |
RuntimeStateEntityObserver | Allows to listen to changes in the runtime state of the simulation. E.g. to attach listeners to Calculators. |
IModelObserver | Watch the global partition and update the respective simulation entity accordingly. E. g. UsageModelSyncer updates SimulatedUsageModels . |
RDSeffSwitchContributionFactory | Provide a factory for a custom package of RDSEFF actions. When encountering actions from this package, the RDSEFF interpreter dispatches the events to your custom interpreter. If again traverse the model further, please make sure to use the provided RDSeffElementDispatcher to do so. |
IInterpreterListener | Register for ModelElementPassedEvent s of the core interpretation logic. |