The Naming Context¶
DSOL stands for Distributed Simulation Object Library. DSOL has been set-up with distribution in mind. Distribution of models, distribution of model components, and the ability to get access to the state of the model, the model's animation, and the results from experiments from other computers than the computer(s) where the model is running. This means that we need sound communication between diferent computers on a network.
When objects want to communicate with each other within a program or over a network, different solutions exist. Objects can communicate through sockets using serialized content (as an example, see djutils-serialization and the sim0mq project). Java offers RMI (Remote Method Invocation) in addition to communicating content over the network. RMI allows to call methods on objects that are present in another JVM on another computer. Of course RMI can also find objects in another JVM on the same computer, or in the same JVM. Objects are bound to a registry within RMI, where they can be found using a key.
The RMI registry is a flat system, however, where all objects reside at the same level and key clashes can occur easily. In addition to RMI, Java has a system called JNDI (Java Naming and Directory Interface), which provides a hierarchical registry that looks like a directory structure. JNDI is ideal for creating the hierarchical structure that we would need for storing simulation results and simulation model state, and providing access to the results to other programs over the network. DSOL has a lightweight implementaton of JNDI, where the directories in which references are stored a Context
. Contexts can contain other Contexts, forming a tree structure with content that can be retrieved using a structure similar to an URL / URI or a directory structure: /level1/level2/key where level1 and level2 are sub-contexts and key is the key that is bound to an object of interest.
Use of Contexts in DSOL¶
In DSOL, different structures are stored in a context:
- 2D Animation objects, which enables viewing 2D animation from clients on other computers.
- 3D Animation objects, which enables viewing 3D animation from clients on other computers.
- Statistical objects, such as the
SimTally
,SimCounter
andSimPersistent
, which enables viewing of statistical results during the simumation run and at the end of a simulation run on other computers. - Output Plots, such as the
Histogram
,BoxAndWhiskerPlot
, and theXYPlot
, which enables viewing of graphs during the simumation run and at the end of a simulation run on other computers.
When a model is built, typically several Experiments are carried out with the model, and each experiment has several Replications. Therefore the structure of the Context directory tree is as follows:
root +-- experiment1 +-- replication1 +-- animation +--- D2 --- 2D animation objects | | | +--- D3 --- 3D animation objects | | | | | +--------- statistics --- statistics objects | | +----------charts ------- chart objects | | | +-- replication2 +-- animation +--- D2 --- 2D animation objects | | | +--- D3 --- 3D animation objects | | | | | +--------- statistics --- statistics objects | | +----------charts ------- chart objects | | | +-- etc. | | | +-- statistics ----- objects that capture averages over the replications | +-- experiment2 +-- replication1 +-- animation +--- D2 --- 2D animation objects | | | +--- D3 --- 3D animation objects | | | | | +--------- statistics --- statistics objects | | +----------charts ------- chart objects | +-- etc. +-- etc.
The advantage of this structure is that experiments can easily be compared (side-to-side), and that results from multiple replications can be retrieved. Statistical results are stored per replication, but also averaged over replications to provide averages and confidence intervals for the performance indicators per experiment.
Types of Contexts¶
DSOL implements four different types of lightweight Context
implementations (the interface that defines the contract of a Context
is the ContextInterface
):
1. The JvmContext
. This context stores all information in memory. The context cannot be reached over the network. It can be wrapped in a RemoteContext
, however, making the results available to other computers via the RemoteContext
.
2. The FileContext
. This is a JvmContext
that also serializaes all content to a file on disk. This makes a FileContext
a persistent context that will still contain the anmation objects, statistics, graphs after the program has ended (planned or after an error). The FileContext
can also be wrapped in a RemoteContext
.
3. The RemoteContext
. This is a context that is registered as one RMI object in the RMI registry, and is therefore accessible by other programs on the network. A RemoteContext
always wraps another Context to carry out the work.
The InitialEventContext
is not a Context itself, but it contains a pointer to one of the above Contexts, and it provides detailed information about changes that occur to the objects in the Context and in the Context's structure. All Contexts are an EventProducer
, but the InitialEventContext
can give information to subscribers about certain parts of the tree: a Node, a Level, or a Subtree. Thereby a Listener
that is only interested in updates of graphs will not also receive a multitude of animation events over the network. In a DSOL program, there is typically one Singleton InitialEventContext that contains information about the experiments and animation, but in theory, there could be more than one.
Interaction with a Context¶
The picture below shows how an InitialEventContext
is set-up locally within a JVM, where the InitialEventContext
points to a JvmContext
that contains the content. The top part of the diagram shows how the initial context is et-up. The second part shows how a subcontext is created. Below that, the DSOL program, which implements the EventListenerInterface
subscribes itself to the events within a certain tree in the JvmContext
by calling the addContextListener(key, Scope)
method in the InitialEventContext
. The InitialEventContext
delegates the actual firing of events to the JvmContext
object(s) that are part of the scope of the indicated scope when adding the ContextListener. When the DSOL program adds an object to the JvmContext
, listeners are automatically notified of the change through the notify(Event)
method (bottom part of the diagram).
Types of events that can be communicated to a listener are:
* OBJECT_ADDED_EVENT
is fired when an object is added to the Context, to those listeners that have a subscription including this Context. The payload is an Object[]
containing the context in which the object has been bound, the relative key in the context, and the bound object.
* OBJECT_REMOVED_EVENT
is fired when an object is removed from the Context, to those listeners that have a subscription including this Context. The payload is an Object[]
containing the context in which the object was bound, the relative key in the context, and the removed object.
* OBJECT_CHANGED_EVENT
is fired when an object's content changes, to those listeners that have a subscription including the Context in which the object is bound. The payload is an Object[]
containing the context in which the object is bound, the relative key in the context, and the object after the change.
Interaction with a RemoteContext¶
Interacting with a RemoteContext
is somewhat more complex than interacting with a JvmContext
as shown above. The picture below shows schematically how a piece of DSOL code, the InitialEventContext
, a RemoteContext
, and an embedded JvmContext
link together and interact.
Code can interact directly with the nodes in the Context tree, as is shown with the top arrow in the middle. Adding subcriptions for changes in a certain part of the tree (one Context object) can also be done directly. In such a case, one of the objects in the DSOL program adds itsef as an EventListener
to one Context in the JvmContext
, FileContext
or RemoteContext
directly. The InitialEventContext
is useful if we want to get subscriptions to multiple nodes. We subscribe in such a case to the events at the InitialEventContext
, which will take care that we receive updates of, e.g., an entire subtree of the Context.
The above picture is an extreme example. Typically, we will take care that the RemoteContext
is on the same computer as the DSOL program and the InitialEventContext
. A RemoteListener
subscribes to updates of the RemoteContext
that acts as a RemoteEventProducer
. The embedded JvmContext
or FileContext
acts as a normal EventProducer
and fires its events to the RemoveEventProducer
that retransmits the event to its RemoteListeners
. When RemoteListeners
want to subscribe to a certain scope of the Context tree, a RemoteInitialEventContext
needs to be set up that registers itself in the RMI registry and can later be found by a RemoteEventListener
. The way this works is shown conceptually in the following sequence diagram, where the DSOL program sets up a (Remote) InitialEventContext
that registers itself in the RMI Registry. It creates a RemoteContext
and an embedded JvmContext
, where the RemoteContext
also registers itself in the RMI Registry. The bottom part of the diagram shows that the DSOL program asks the RemoteContext
to create a child context. The request for this is delegated to the embedded JvmContext
(the RemoteContext
acts as an empty shell that delegates most methods, except for the registration of RemoteEventListeners and firing of events to these listeners):
Each of the JvmContexts is "wrapped" inside a RemoteContext. This is necessary, because