1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00
cdt/plugins/org.eclipse.dd.doc.dsf/docs/dsf_services_model.html

363 lines
18 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>DSF Services Model</title>
</head>
<body>
<h2>DSF Services Model</h2>
<br>
<b><span style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;">Version
1.0<br>
Pawel Piech <br>
</span></b><b><span
style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;">&copy; 2006,
Wind River Systems.<span style="">&nbsp; </span>Release under EPL
version 1.0.</span></b><b><span
style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;"><br style="">
</span></b>
<p>Debugger Services Framework (DSF) is primarily a service framework
defining rules for how
services should be registered, discovered, organized into functional
groups, communicated with, and started/ended.&nbsp; These rules help to
organize the services into a functional system that efficiently
abstracts various debugger back end capabilities.&nbsp; </p>
<p>DSF services build on top of the OSGI services framework, so
it's important to understand OSGI services before looking at DSF
itself.&nbsp; For an overview of OSGI including services, see the <a
href="http://eclipsezilla.eclipsecon.org/php/attachment.php?bugid=185">presentation
on OSGI from EclipseCon 2006</a>.&nbsp; For detailed information, see
OSGI javadocs, primarily: <a style="font-family: monospace;"
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/package-summary.html">org.osgi.framework</a><a
style="font-family: monospace;"
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/ServiceRegistration.html">ServiceRegistration</a>,
<a
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/BundleContext.html"><span
style="font-family: monospace;">BundleContext</span></a>, <a
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/BundleContext.html"><span
style="font-family: monospace;">ServiceReference</span></a>, <a
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/framework/Filter.html"><span
style="font-family: monospace;">Filter</span></a>, and <a
style="font-family: monospace;"
href="http://help.eclipse.org/help31/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/util/tracker/ServiceTracker.html">ServiceTracker</a>.
</p>
<h3>Services<br>
</h3>
In OSGI any class can be registered as a service.&nbsp; In DSF,
Services must implement the <a
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/IDsfService.html"><span
style="font-family: monospace;">IDsfService</span></a>&nbsp;
interface, which requires that the service
provide:<br>
<ol>
<li>Access to the <span style="font-family: monospace;">DsfExecutor </span>that
has to be used to access service methods.</li>
<li>Full list of properties used to uniquely identify the service in
OSGI.</li>
<li>Startup and shutdown methods.</li>
</ol>
For the first two items, a service must use the data it received from
its constructor.&nbsp; For the third item, a service must register and
unregister itself with OSGI.&nbsp; But beyond that, this is all that
services have in common, everything else is up to the specific service
interface.<br>
<h3>Sessions (<a
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/DsfSession.html"><span
style="font-family: monospace;">org.eclipse.dd.dsf.service.DsfSession</span></a>)<br>
</h3>
DSF services are organized into logical groups, called
sessions.&nbsp; Sessions are only necessary because we want multiple
instances of systems built with DSF services to run at the same
time&nbsp; This is because there is only a single OSGI service
registry, so if multiple services are registered with a given class
name, OSGI will not be able to distinguish between the two based on the
class name alone.&nbsp; So there is an additional property which is
used by every DSF service when registering with OSGI, <span
style="font-family: monospace;">IDsfService.PROP_SESSION_ID</span>.&nbsp;
<br>
<p>A <span style="font-family: monospace;">Session</span> object
(TODO: link javadoc) has the following data associated with it:<br>
</p>
<ul>
<li><span style="text-decoration: underline;">Session ID</span> - A <span
style="font-family: monospace;">String</span> object that is unique
among all other sessions.&nbsp; Its ID is used by services as the <span
style="font-family: monospace;">IDsfService.PROP_SESSION_ID</span>
property, and it is used by the client to obtain the <span
style="font-family: monospace;">Session</span> object instance.</li>
<li><span style="font-family: monospace; text-decoration: underline;">DsfExecutor</span>
- Each session has a single executor.&nbsp; This means that all the
services in a single session share the same executor and dispatch
thread, and conversely it means that when operating in the dispatch
thread, the state of all the services in a session will remain the same
until the end of a dispatch.&nbsp; Note: multiple sessions <span
style="font-style: italic;">could</span> share the same <span
style="font-family: monospace;">DsfExecutor</span>.</li>
<li><span style="text-decoration: underline;">Service startup counter</span>
- An integer counter which is read and incremented by every service
that is started in a session.&nbsp; This counter is used to determine
the dependency order among services, which is used by events.</li>
<li><span style="text-decoration: underline;">Event listener list</span>
- This will be covered in the "Events" section.</li>
<li><span style="text-decoration: underline;">Adapter list</span> - A
list of adapters, providing functionality analogous to runtime's <span
style="font-family: monospace;">org.eclipse.core.internal.runtime.AdapterManager</span>.&nbsp;
Sessions need to manage their own lists of adapters, so that <span
style="font-family: monospace;">IAdapter</span> objects which
originate from DSF services can provider different adapters, based
on the session that they originate from.&nbsp; This feature is covered
in detail in the "DSF Data Model" document.<br>
</li>
</ul>
<p>The Session class also has a number of static features used to
manage Session objects:</p>
<ul>
<li><span style="text-decoration: underline;">Session ID counter</span>
- Used to generate new session IDs.</li>
<li><span style="text-decoration: underline;">Methods for starting
and ending sessions</span> <br>
</li>
<li><span style="text-decoration: underline;">Session started/ended
event listener list</span> - This allows clients to be notified when
sessions are created or terminated, which is used mostly for clean-up
purposes.<br>
</li>
</ul>
<h3>Startup/Shutdown</h3>
Managing the startup and shutdown process is often the most complicated
aspect of modular systems.&nbsp; The details of how the startup and
shutdown processes should be performed are also highly dependent on the
specifics of the system and service implementations.&nbsp; To help
with this, DSF provides two simple guidelines:<br>
<ol>
<li><span style="text-decoration: underline;">There should be a clear
dependency tree of all services within a session</span> - When the
dependencies between services are clearly defined, it is possible to
bring-up and bring-down the services in an order that guarantees each
running service can access all of the services that it depends on.</li>
<li><span style="text-decoration: underline;">There needs to be a
single point of control, which brings up and shuts down all the
services.</span> - In other words, services should not initialize or
shut-down themselves, based on some global event that they are all
listening to.&nbsp; But rather an external piece of logic needs to be
in charge of performing this operation.</li>
</ol>
The main implication of the first guideline, is that each service can
get and hold onto references to other services, without having to
repeatedly check, whether the service references are still valid.&nbsp;
This is because if a given service is to be shut-down, all services
that depend on this service will already have been shut down.&nbsp; The
second guideline, simply ensures that startup and shutdown procedures
are clear and easy to follow.<br>
<h3><a
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/service/DsfServicesTracker.html"><span
style="font-family: monospace;">org.eclipse.dd.dsf.service.DsfServicesTracker</span></a>
vs <a
href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/osgi/org/osgi/util/tracker/ServiceTracker.html"><span
style="font-family: monospace;">org.osgi.util.tracker.ServiceTracker</span></a></h3>
OSGI methods for obtaining and tracking services can be rather
complicated.&nbsp; To obtain a reference to a service, the client has
to:<br>
<ol>
<li>Get a reference to a <span style="font-family: monospace;">BundleContext
</span>object, which can be retrieved from the plugin class.</li>
<li>Obtain a service reference object by calling <span
style="font-family: monospace;">BundleContext.getServiceReference()</span>;</li>
<li>Obtain an instance of the service by calling <span
style="font-family: monospace;">BundleContext.getService(ServiceReference)</span>.</li>
</ol>
But worst of all, when the client is finished using the service, it has
to call <span style="font-family: monospace;">BundleContext.ungetService(ServiceReference)</span>,
because the bundle context counts the used references to a given
service.&nbsp; All this paperwork is useful for services which manage
their own life-cycle, and could be un-registered at any time.&nbsp; To
make managing references to these kinds of services, OSGI provides a
utility class, called <span style="font-family: monospace;">ServiceTracker</span>.&nbsp;
<br>
<p>For DSF services, the life cycle of the services is much more
predictable, but the process of obtaining a reference to a service is
just as onerous.&nbsp; DSF provides its own utility, which is
separate from the <span style="font-family: monospace;">ServiceTracker</span>,
named <span style="font-family: monospace;">DsfServicesTracker</span>.&nbsp;
The differences between the two are listed in table below:<br>
</p>
<table style="width: 100%; text-align: left;" border="1" cellpadding="3"
cellspacing="0">
<tbody>
<tr>
<th
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">Property<br>
</th>
<th
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">OSGI
<span style="font-family: monospace;">ServiceTracker</span><br
style="font-family: monospace;">
</th>
<th
style="vertical-align: top; background-color: rgb(204, 204, 204); font-family: helvetica,arial,sans-serif;">DSF
<span style="font-family: monospace;">DsfServicesTracker</span><br>
</th>
</tr>
<tr>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Number
of services tracked<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">While
not strictly limited, it is optimized for tracking services of a single
class type, or more typically to track a single service reference.<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Designed
to track services within a single DSF session.&nbsp; <br>
</td>
</tr>
<tr>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">When
are service references obtained<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Obtain
references automatically as the services register themselves.<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Service
references are obtained as requested by the client, and cached.</td>
</tr>
<tr>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Synchronization<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Multi-thread
accessible.&nbsp; <br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Can
be accessed only on the session's dispatch thread.<br>
</td>
</tr>
<tr>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Clean-up<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Automatically
un-gets references for services that are shut down.<br>
</td>
<td
style="vertical-align: top; font-family: helvetica,arial,sans-serif;">Client
must listen to session events, and clean up as needed.<br>
</td>
</tr>
</tbody>
</table>
<p>Both trackers are useful.&nbsp; Service implementations that depend
on a number of other services are most likely to use DSF <span
style="font-family: monospace;">ServicesTracker</span>, while some
clients, which use a single service may find OSGI <span
style="font-family: monospace;">ServiceTracker </span>more suitable.<br>
</p>
<h3>Events</h3>
Events are the most un-conventional component of the services package
and probably most likely to need modifications to the design by the
community.&nbsp; The design goal of
the event system is to allow a hierarchy of event classes, where a
listener could register itself for a specific event class or for all
events which derive from a base class.&nbsp; The use case for this
behavior is in the data model, where we would like to have the ability
to capture all model-related events with a generic listener while at
the same time allowing for services to fully use class types.&nbsp; <br>
<p>The event model is made up of the following components:<br>
</p>
<ul>
<li><span style="font-weight: bold;"><span
style="font-family: monospace;">DsfServiceEventHandler </span>annotation</span>
- This is the only indicator that a given method is an event
listener.&nbsp; The class with the event handler doesn't have to
implement any interfaces, but it must be public, which is a big
drawback.</li>
<li><span style="font-weight: bold;"><span
style="font-family: monospace;">Session.addServiceEventListener</span>,
<span style="font-family: monospace;">Session.removeServiceEventListener</span>
methods</span> - These methods allow clients to register for an event
based on an event class and a service filter, where the filter can be
used to uniquely identify a service in case of services with multiple
instances of same class.</li>
<li><span style="font-weight: bold;"><span
style="font-family: monospace;">Session.dispatchEvent</span> method -</span>
This is the method that actually dispatches the event to the
listeners.&nbsp;
The method must be called by a service that generates the event.</li>
</ul>
There are only a few more notes about the events mechanism:<br>
<ol>
<li>The event is always dispatched in its own <span
style="font-family: monospace;">Runnable</span> submitted to
the session's <span style="font-family: monospace;">DsfExecutor</span>.</li>
<li>There is a slight convenience for clients not to have to register
for each type of event separately.</li>
<li>There is a slight inconvenience for clients, because anonymous
classes cannot be used as listeners, due to the public class
requirement.</li>
</ol>
<h3>Debugger Services (<a
href="http://dsdp.eclipse.org/help/latest/topic/org.eclipse.dd.dsf.doc/reference/api/org/eclipse/dd/dsf/debug/package-summary.html"><span
style="font-family: monospace;">org.eclipse.dd.dsf.debug</span></a>)<br>
</h3>
DSF framework includes a set of service interfaces for a typical
debugger implementation.&nbsp; Functionally, they are pretty much
equivalent to the platform debug interfaces, but they are structured in
a way that allows a debugger to implement only some of them.&nbsp; In
order for the startup and shutdown process to work effectively, the
dependencies between services need to be clearly defined.&nbsp; The
dependencies between the main service interfaces are shown in the graph
below:<br>
<img alt="" title="Debugger Services Dependencies"
src="dsf_services_model-1.png" style="width: 720px; height: 540px;"><br>
<p>It's also important to realize that it's unlikely that a single
hierarchy of interfaces will adequately fit all the various debugger
use cases, and it is likely that some interfaces will be needed which
partially duplicate functionality found in other interfaces.&nbsp;
An example of this in the proposed interface set are the interfaces
which are used to initiate a debugging session.&nbsp; The <span
style="font-family: monospace;">INativeProcesses</span> service is
intended as the simple abstraction for native debuggers, where a
debugger only needs an existing host process ID or an executable image
name.&nbsp; Based on this a <span style="font-family: monospace;">INativeProcess</span>
debugger implementation should be able to initiate a debugging session,
and return run-control, memory, and symbol contexts that are required
to carry out debugging operations.&nbsp; By comparison, <span
style="font-family: monospace;">IOS</span> and <span
style="font-family: monospace;">ITarget</span> are generic interfaces
which allow clients to manage multiple target definitions, to
examine a wide array of OS objects, and to attach a debugger to a
process or some other debuggable entity.&nbsp; <br>
<img alt="" title="Process Managment Services"
src="dsf_services_model-2.png" style="width: 720px; height: 540px;"><br>
</p>
<h4>Disclaimer</h4>
Drafting large APIs that are intended to have many implementations and
by clients is a notoriously difficult task.&nbsp; It is
impossible to expect that a first draft of such interfaces will not
require changes, and only time and multiple successful implementation
can validate them.&nbsp; While we can draw upon many examples of
debugger
APIs in Eclipse in and our commercial debugger, this is a new API with
a
prototype that exercises only a small portion of its interfaces.<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</body>
</html>