Skip to content

APAM composite state

diana-mg edited this page Dec 19, 2012 · 4 revisions

Conflict access management: ConflictMan

By default, a service is used by the clients that have established a wire to it. There is no limit for this usage duration. Therefore, exclusive services (and devices) once bound cannot be used by any other client; there is a need to control service users depending on different conditions.

The wires are removed only when deleted (either setting the variable to null, or calling the release method in the API). When an exclusive wire is released, an arbitrarily selected waiting client is resumed.

Exclusive service management (from core)

An instance is said to be exclusive if it is in limited supply (usually a single instance), and cannot be shared. It means that the associated service can only be offered to a limited amount of clients, and therefore there is a risk of conflict to the access to that service. In most scenarios, exclusive services are associated with devices that have the property not to be shared, as are most actioners.

<specification name="Door" interface="..."
   singleton="false" instantiable="false" shared="false">
   <definition name="location" type="exit, entrance, garage, bedroom, ..."/>

In this example, a device specified by "Door" is in exclusive access, but is in multiple instances (a house may have many doors). It defines a property "location" i.e. the location of a particular door. instantiable="false" means that it is not possible to create instances of the Door specification, doors "appears", i.e. they are detected by sensors; and shared="false" means that a single client can use a given door (i.e. to lock or unlock it) at any given point in time.

Composite state management

The composite designer knows more about the context in which the components execute, than components developers, and can decide under which conditions a component can use a given exclusive service.

APAM distinguishes a property "state" associated to any composite. The state attribute is intended for managing exclusivity conflicts, its type must be an enumeration:

<composite name="Security">
   ...
   <contentMngt>
	<state implementation="HouseState" property="houseState"/>

And implementation HouseState must define the attribute houseState:

<implementation name="HouseState" singleton="true">
   <definition name="houseState" field="state" internal="true" 
      type="empty, night, vacation, emergency, threat " value="night"/>

Each time an instance of composite Security is created, an instance of HouseState is also created and associated with the composite. That instance will be in charge of computing the composite state. While this is not required, it is strongly advised to define the state attribute as an internal field attribute, in order to be sure its value will not be changed by mistake or by malevolent programs.

The own primitive

The own primitive in intended to enforce the ownership of instances. This is a critical importance since, in APAM, only the owner can define visibility and conflict access rules.

The own primitive enforces the fact that all the instances matching the declaration will pertain to the current composite. The composite must be a singleton.

<composite name="security" singleton="true">
  <contentMngt>
    <own specification="Door" property="location" value="entrance, exit">

In this example, all Doors instances (i.e. all the doors) appearing dynamically in the system, will be owned (and located inside) the unique security composite instance. No other composite can own Doors instances (and create them if Door would be instantiable). In a composite declaration, a single own clause is allowed for a given specification (and all its implementations), or for a given implementation. In the whole system, all the own clauses referring to the same component must indicate the same property and different values. This is checked when deploying a new composite; in case one of the own clause of the new composite is inconsistent with those of the already installed composites, (different property or same value) the new composite is rejected.

The grant primitive

The grant primitive is intended to enforce the resolution of a given dependency on some specific situations. In most cases, this dependency leads to an exclusive service (a device for example). A grant primitive can be set only on dependencies with the wait behavior. It means that if the client is waiting for the resource, it is resumed as soon as the composite changes its state to the one mentioned in the definition and that it will not lose its dependency as long as the composite is in that state. However, when the composite leaves the state, the client may lose its dependency and can be turned in the waiting state.

<composite name="security" singleton="true">
   <contentMngt>
      <own specification="Door" property="location" value="entrance, exit">
         <grant when="emergency" implementation ="Fire" dependency="door" />
         <grant when="threat" implementation="break" />
      </own>
      <own specification="Door" property="location" value="garage">

In this example, when the (unique) instance of composite security is changed to enter the emergency state, the dependency called door of component Fire has priority on the access to the door target. To have priority means that if

  • Component Fire tries to resolve the door dependency while security is in the emergency state, APAM gives to Fire the unique access to the door matching the constraint (|(location=entrance)(location=exit)). If not in the emergency mode, door is resolved only against the unused doors, including the entrance and exit doors if unused. If no doors are available, the door dependency is turned into the wait mode.
  • If the door dependency of component Fire is in the wait mode, when security enters the emergency state, APAM resolves dependency door towards its target (all the entrance and exit doors), even if currently used by another client, and resumes the waiting threads.
This primitive can be used only if both the composite and the source implementation are singleton, which enforces a deterministic behavior.

The system checks, at compile time, that all the grant clauses are defined against a different and valid composite state. Conversely, it is not always possible to verify, at compile time, that all the own clauses toward the same resource are defined on different values of the same property. This control is performed when a new composite is deployed; if the own clause is invalid, the new composite is rejected. Own clauses conflict if they are against the same resource, but on a different property, or on the right property but the same value.

When security state changes to become emergency, APAM checks which doors owned by security are matching the door dependency. If these instances are currently wired by other client instances, these wires are removed, and the Fire instance is wired toward the selected doors. When security composite leaves the emergency state, if instances are waiting for doors, one of them is selected, wired to the door and resumed. The instances that have been disconnected to the conflicting service will fail to resolve it again as long as the dependency is granted. In our example, if the house has an entrance or an exit door (that can be dynamically discovered), we know that the security will own them, and the Fire application is sure that it will be able to manages these doors in case of emergency.

However, the resolution fails, as usually, if the dependency constraints are not satisfied i.e. security does not own any door instance, or the owned doors do not satisfy the dependency constraints. If that case the grant primitive fails, and the system does nothing.

The start primitive

It is possible to create an instance of a given implementation, inside the current composite, on the occurrence of an event: the apparition of an instance (either explicitly created of dynamically appearing in the system). This primitive has the same information as the instance primitive, but the event that triggers the instance creating in one case in the deployment of the bundle containing the instance declaration (for the instance primitive), while it is the apparition of an instance in the case of the start primitive.

<start implementation="S3Impl" name="s3Impl-int">				
   <property name="S3Impl-Attr" value="val"/> <!-- Init attr value-->	
   <dependency specification="S4"> <!--additional dependency constraints -->
	...			
   <trigger> <!--definition of the condition on which to start S3Impl -->
	<specification name="ASpec"> <!--an instance of ASpec appears -->
	   <constraints>
		<constraint filter="(constraint on the instance)"/>
	   </constraints>
	</specification>
   </trigger>
</start>

In this example, a new instance of specification S3Impl will be created when an instance of ASpec appears in the system (either created explicitly or dynamically appearing). This primitive will be executed at most once (the first time an instance of ASpec appears after the S1Compo deployment).

Clone this wiki locally